aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS413
-rw-r--r--NEWS10
-rw-r--r--audio/audiostream.cpp4
-rw-r--r--audio/decoders/aiff.h1
-rw-r--r--audio/decoders/quicktime.cpp8
-rw-r--r--audio/decoders/quicktime.h1
-rw-r--r--audio/decoders/quicktime_intern.h4
-rw-r--r--audio/mididrv.cpp2
-rw-r--r--audio/midiparser.cpp210
-rw-r--r--audio/midiparser.h66
-rw-r--r--audio/midiparser_smf.cpp176
-rw-r--r--audio/midiparser_xmidi.cpp99
-rw-r--r--audio/softsynth/mt32/Part.cpp2
-rw-r--r--audio/softsynth/mt32/Partial.h2
-rw-r--r--audio/softsynth/mt32/PartialManager.cpp2
-rw-r--r--audio/softsynth/mt32/Synth.cpp2
-rw-r--r--audio/softsynth/mt32/TVA.cpp2
-rw-r--r--audio/softsynth/mt32/TVF.cpp4
-rw-r--r--audio/softsynth/mt32/freeverb.cpp2
-rw-r--r--backends/events/sdl/sdl-events.cpp2
-rw-r--r--backends/events/sdl/sdl-events.h2
-rw-r--r--backends/events/webossdl/webossdl-events.h6
-rw-r--r--backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp2
-rw-r--r--backends/graphics/openglsdl/openglsdl-graphics.cpp2
-rw-r--r--backends/midi/coreaudio.cpp31
-rw-r--r--backends/midi/sndio.cpp4
-rw-r--r--backends/mixer/sdl13/sdl13-mixer.cpp4
-rw-r--r--backends/platform/android/android.h2
-rw-r--r--backends/platform/android/android.mk21
-rw-r--r--backends/platform/android/events.cpp78
-rw-r--r--backends/platform/android/org/scummvm/scummvm/MouseHelper.java129
-rw-r--r--backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java21
-rw-r--r--backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java51
-rw-r--r--backends/platform/bada/application.cpp2
-rw-r--r--backends/platform/bada/sscanf.cpp2
-rw-r--r--backends/platform/iphone/iphone_video.mm13
-rw-r--r--backends/platform/iphone/osys_video.mm4
-rwxr-xr-xbackends/platform/maemo/debian/rules2
-rw-r--r--backends/platform/sdl/macosx/macosx.cpp2
-rw-r--r--backends/platform/sdl/macosx/macosx.h2
-rw-r--r--backends/platform/sdl/main.cpp66
-rw-r--r--backends/platform/sdl/module.mk1
-rw-r--r--backends/taskbar/win32/mingw-compat.h4
-rw-r--r--backends/timer/bada/timer.cpp4
-rw-r--r--backends/timer/bada/timer.h2
-rw-r--r--backends/timer/default/default-timer.cpp2
-rw-r--r--base/commandLine.cpp2
-rw-r--r--base/main.cpp3
-rw-r--r--common/array.h2
-rw-r--r--common/coroutines.cpp4
-rw-r--r--common/cosinetables.cpp2
-rw-r--r--common/gui_options.h2
-rw-r--r--common/keyboard.h9
-rw-r--r--common/macresman.cpp22
-rw-r--r--common/macresman.h3
-rw-r--r--common/memstream.h11
-rw-r--r--common/quicktime.h2
-rw-r--r--common/rational.h3
-rw-r--r--common/rect.h14
-rw-r--r--common/savefile.h4
-rw-r--r--common/sinetables.cpp2
-rw-r--r--common/zlib.h2
-rwxr-xr-xconfigure189
-rw-r--r--devtools/create_project/config.h7
-rw-r--r--devtools/create_project/create_project.cpp28
-rw-r--r--devtools/create_project/create_project.h24
-rw-r--r--devtools/create_project/msbuild.cpp21
-rw-r--r--devtools/create_project/msvc.cpp19
-rw-r--r--devtools/create_project/msvc.h2
-rw-r--r--devtools/create_project/scripts/postbuild.cmd4
-rw-r--r--devtools/create_project/visualstudio.cpp8
-rw-r--r--devtools/create_project/xcode.cpp4
-rw-r--r--devtools/create_teenagent/create_teenagent.cpp140
-rw-r--r--devtools/create_teenagent/md5.cpp264
-rw-r--r--devtools/create_teenagent/module.mk2
-rw-r--r--devtools/create_teenagent/static_tables.h16317
-rw-r--r--devtools/create_teenagent/util.cpp152
-rw-r--r--devtools/create_teenagent/util.h1
-rw-r--r--devtools/create_tony/create_tony.h2
-rw-r--r--devtools/create_tony/staticdata.h234
-rwxr-xr-xdevtools/credits.pl36
-rw-r--r--devtools/module.mk2
-rw-r--r--dists/engine-data/README12
-rw-r--r--dists/engine-data/tony.datbin24584 -> 24584 bytes
-rw-r--r--dists/scummvm.rc3
-rw-r--r--dists/win32/ScummVM.iss12
-rw-r--r--engines/advancedDetector.h4
-rw-r--r--engines/agi/agi.cpp2
-rw-r--r--engines/agi/detection_tables.h4
-rw-r--r--engines/agi/loader_v1.cpp16
-rw-r--r--engines/agi/menu.cpp2
-rw-r--r--engines/agi/op_cmd.cpp6
-rw-r--r--engines/agi/op_test.cpp2
-rw-r--r--engines/agi/opcodes.cpp2
-rw-r--r--engines/agi/saveload.cpp2
-rw-r--r--engines/agi/sound_pcjr.cpp4
-rw-r--r--engines/agi/text.cpp4
-rw-r--r--engines/agi/words.cpp4
-rw-r--r--engines/agos/midiparser_s1d.cpp47
-rw-r--r--engines/agos/saveload.cpp4
-rw-r--r--engines/agos/sound.cpp2
-rw-r--r--engines/cge/bitmap.cpp4
-rw-r--r--engines/cge/cge_main.cpp8
-rw-r--r--engines/cge/detection.cpp4
-rw-r--r--engines/cge/events.h2
-rw-r--r--engines/cge/fileio.cpp2
-rw-r--r--engines/cge/text.cpp2
-rw-r--r--engines/cine/anim.cpp62
-rw-r--r--engines/cine/cine.cpp13
-rw-r--r--engines/cine/cine.h2
-rw-r--r--engines/cine/console.cpp2
-rw-r--r--engines/cine/gfx.cpp87
-rw-r--r--engines/cine/gfx.h3
-rw-r--r--engines/cine/main_loop.cpp29
-rw-r--r--engines/cine/object.cpp2
-rw-r--r--engines/cine/pal.cpp3
-rw-r--r--engines/cine/part.cpp2
-rw-r--r--engines/cine/saveload.cpp2
-rw-r--r--engines/cine/saveload.h2
-rw-r--r--engines/cine/script.h1
-rw-r--r--engines/cine/script_fw.cpp1640
-rw-r--r--engines/cine/sound.cpp161
-rw-r--r--engines/cine/sound.h36
-rw-r--r--engines/cine/texte.cpp2
-rw-r--r--engines/cine/texte.h2
-rw-r--r--engines/cine/various.cpp218
-rw-r--r--engines/composer/composer.cpp7
-rw-r--r--engines/composer/composer.h2
-rw-r--r--engines/composer/graphics.cpp14
-rw-r--r--engines/composer/resource.cpp2
-rw-r--r--engines/configure.engines28
-rw-r--r--engines/cruise/detection.cpp2
-rw-r--r--engines/dialogs.cpp2
-rw-r--r--engines/draci/detection.cpp2
-rw-r--r--engines/drascula/detection.cpp14
-rw-r--r--engines/dreamweb/dreamweb.cpp6
-rw-r--r--engines/dreamweb/dreamweb.h2
-rw-r--r--engines/dreamweb/monitor.cpp4
-rw-r--r--engines/dreamweb/object.cpp4
-rw-r--r--engines/dreamweb/people.cpp16
-rw-r--r--engines/dreamweb/print.cpp2
-rw-r--r--engines/dreamweb/sprite.cpp14
-rw-r--r--engines/dreamweb/vgagrafx.cpp72
-rw-r--r--engines/engines.mk5
-rw-r--r--engines/groovie/detection.cpp2
-rw-r--r--engines/groovie/roq.cpp27
-rw-r--r--engines/hugo/file.cpp82
-rw-r--r--engines/hugo/file.h5
-rw-r--r--engines/lure/decode.cpp4
-rw-r--r--engines/made/screenfx.cpp8
-rw-r--r--engines/mohawk/bitmap.cpp6
-rw-r--r--engines/mohawk/video.cpp2
-rw-r--r--engines/mohawk/video.h2
-rw-r--r--engines/parallaction/adlib.cpp808
-rw-r--r--engines/parallaction/callables_ns.cpp12
-rw-r--r--engines/parallaction/debug.cpp8
-rw-r--r--engines/parallaction/dialogue.cpp8
-rw-r--r--engines/parallaction/disk_br.cpp4
-rw-r--r--engines/parallaction/disk_ns.cpp11
-rw-r--r--engines/parallaction/exec.cpp6
-rw-r--r--engines/parallaction/exec_br.cpp8
-rw-r--r--engines/parallaction/exec_ns.cpp8
-rw-r--r--engines/parallaction/font.cpp4
-rw-r--r--engines/parallaction/gfxbase.cpp13
-rw-r--r--engines/parallaction/graphics.cpp4
-rw-r--r--engines/parallaction/graphics.h4
-rw-r--r--engines/parallaction/gui_ns.cpp2
-rw-r--r--engines/parallaction/input.cpp22
-rw-r--r--engines/parallaction/module.mk1
-rw-r--r--engines/parallaction/objects.cpp4
-rw-r--r--engines/parallaction/parallaction.cpp32
-rw-r--r--engines/parallaction/parallaction.h24
-rw-r--r--engines/parallaction/parallaction_br.cpp14
-rw-r--r--engines/parallaction/parallaction_ns.cpp20
-rw-r--r--engines/parallaction/parser_br.cpp4
-rw-r--r--engines/parallaction/parser_ns.cpp2
-rw-r--r--engines/parallaction/saveload.cpp6
-rw-r--r--engines/parallaction/sound.h2
-rw-r--r--engines/parallaction/sound_br.cpp34
-rw-r--r--engines/parallaction/sound_ns.cpp6
-rw-r--r--engines/parallaction/staticres.cpp28
-rw-r--r--engines/parallaction/walk.cpp28
-rw-r--r--engines/parallaction/walk.h8
-rw-r--r--engines/pegasus/ai/ai_action.cpp78
-rw-r--r--engines/pegasus/ai/ai_action.h136
-rw-r--r--engines/pegasus/ai/ai_area.cpp613
-rw-r--r--engines/pegasus/ai/ai_area.h172
-rw-r--r--engines/pegasus/ai/ai_condition.cpp290
-rw-r--r--engines/pegasus/ai/ai_condition.h287
-rw-r--r--engines/pegasus/ai/ai_rule.cpp78
-rw-r--r--engines/pegasus/ai/ai_rule.h86
-rw-r--r--engines/pegasus/compass.cpp82
-rw-r--r--engines/pegasus/compass.h58
-rw-r--r--engines/pegasus/console.cpp102
-rw-r--r--engines/pegasus/console.h (renamed from devtools/create_teenagent/md5.h)30
-rw-r--r--engines/pegasus/constants.h729
-rw-r--r--engines/pegasus/cursor.cpp213
-rw-r--r--engines/pegasus/cursor.h84
-rw-r--r--engines/pegasus/detection.cpp157
-rw-r--r--engines/pegasus/elements.cpp568
-rw-r--r--engines/pegasus/elements.h254
-rw-r--r--engines/pegasus/energymonitor.cpp296
-rw-r--r--engines/pegasus/energymonitor.h111
-rw-r--r--engines/pegasus/fader.cpp218
-rw-r--r--engines/pegasus/fader.h130
-rw-r--r--engines/pegasus/gamestate.cpp2359
-rw-r--r--engines/pegasus/gamestate.h886
-rw-r--r--engines/pegasus/graphics.cpp346
-rw-r--r--engines/pegasus/graphics.h95
-rw-r--r--engines/pegasus/hotspot.cpp325
-rw-r--r--engines/pegasus/hotspot.h152
-rw-r--r--engines/pegasus/input.cpp373
-rw-r--r--engines/pegasus/input.h500
-rw-r--r--engines/pegasus/interaction.h110
-rw-r--r--engines/pegasus/interface.cpp667
-rw-r--r--engines/pegasus/interface.h148
-rw-r--r--engines/pegasus/items/autodragger.cpp91
-rw-r--r--engines/pegasus/items/autodragger.h57
-rw-r--r--engines/pegasus/items/biochips/aichip.cpp279
-rw-r--r--engines/pegasus/items/biochips/aichip.h69
-rw-r--r--engines/pegasus/items/biochips/biochipitem.cpp95
-rw-r--r--engines/pegasus/items/biochips/biochipitem.h54
-rw-r--r--engines/pegasus/items/biochips/mapchip.cpp106
-rw-r--r--engines/pegasus/items/biochips/mapchip.h64
-rw-r--r--engines/pegasus/items/biochips/mapimage.cpp443
-rw-r--r--engines/pegasus/items/biochips/mapimage.h84
-rw-r--r--engines/pegasus/items/biochips/opticalchip.cpp190
-rw-r--r--engines/pegasus/items/biochips/opticalchip.h71
-rw-r--r--engines/pegasus/items/biochips/pegasuschip.cpp198
-rw-r--r--engines/pegasus/items/biochips/pegasuschip.h55
-rw-r--r--engines/pegasus/items/biochips/retscanchip.cpp49
-rw-r--r--engines/pegasus/items/biochips/retscanchip.h43
-rw-r--r--engines/pegasus/items/biochips/shieldchip.cpp53
-rw-r--r--engines/pegasus/items/biochips/shieldchip.h46
-rw-r--r--engines/pegasus/items/inventory.cpp175
-rw-r--r--engines/pegasus/items/inventory.h80
-rw-r--r--engines/pegasus/items/inventory/airmask.cpp249
-rw-r--r--engines/pegasus/items/inventory/airmask.h76
-rw-r--r--engines/pegasus/items/inventory/gascanister.cpp46
-rw-r--r--engines/pegasus/items/inventory/gascanister.h44
-rw-r--r--engines/pegasus/items/inventory/inventoryitem.cpp110
-rw-r--r--engines/pegasus/items/inventory/inventoryitem.h67
-rw-r--r--engines/pegasus/items/inventory/keycard.cpp59
-rw-r--r--engines/pegasus/items/inventory/keycard.h48
-rw-r--r--engines/pegasus/items/inventorypicture.cpp370
-rw-r--r--engines/pegasus/items/inventorypicture.h125
-rw-r--r--engines/pegasus/items/item.cpp314
-rw-r--r--engines/pegasus/items/item.h363
-rw-r--r--engines/pegasus/items/itemdragger.cpp193
-rw-r--r--engines/pegasus/items/itemdragger.h96
-rw-r--r--engines/pegasus/items/itemlist.cpp67
-rw-r--r--engines/pegasus/items/itemlist.h59
-rw-r--r--engines/pegasus/menu.cpp1219
-rw-r--r--engines/pegasus/menu.h171
-rw-r--r--engines/pegasus/module.mk100
-rw-r--r--engines/pegasus/movie.cpp280
-rw-r--r--engines/pegasus/movie.h105
-rw-r--r--engines/pegasus/neighborhood/caldoria/caldoria.cpp1962
-rw-r--r--engines/pegasus/neighborhood/caldoria/caldoria.h523
-rw-r--r--engines/pegasus/neighborhood/caldoria/caldoria4dsystem.cpp370
-rw-r--r--engines/pegasus/neighborhood/caldoria/caldoria4dsystem.h78
-rw-r--r--engines/pegasus/neighborhood/caldoria/caldoriabomb.cpp1442
-rw-r--r--engines/pegasus/neighborhood/caldoria/caldoriabomb.h156
-rw-r--r--engines/pegasus/neighborhood/caldoria/caldoriamessages.cpp115
-rw-r--r--engines/pegasus/neighborhood/caldoria/caldoriamessages.h60
-rw-r--r--engines/pegasus/neighborhood/caldoria/caldoriamirror.cpp135
-rw-r--r--engines/pegasus/neighborhood/caldoria/caldoriamirror.h54
-rw-r--r--engines/pegasus/neighborhood/door.cpp64
-rw-r--r--engines/pegasus/neighborhood/door.h90
-rw-r--r--engines/pegasus/neighborhood/exit.cpp70
-rw-r--r--engines/pegasus/neighborhood/exit.h93
-rw-r--r--engines/pegasus/neighborhood/extra.cpp58
-rw-r--r--engines/pegasus/neighborhood/extra.h67
-rw-r--r--engines/pegasus/neighborhood/hotspotinfo.cpp65
-rw-r--r--engines/pegasus/neighborhood/hotspotinfo.h77
-rw-r--r--engines/pegasus/neighborhood/mars/constants.h941
-rw-r--r--engines/pegasus/neighborhood/mars/energybeam.cpp70
-rw-r--r--engines/pegasus/neighborhood/mars/energybeam.h43
-rw-r--r--engines/pegasus/neighborhood/mars/gravitoncannon.cpp134
-rw-r--r--engines/pegasus/neighborhood/mars/gravitoncannon.h57
-rw-r--r--engines/pegasus/neighborhood/mars/hermite.cpp76
-rw-r--r--engines/pegasus/neighborhood/mars/hermite.h41
-rw-r--r--engines/pegasus/neighborhood/mars/mars.cpp3735
-rw-r--r--engines/pegasus/neighborhood/mars/mars.h238
-rw-r--r--engines/pegasus/neighborhood/mars/planetmover.cpp104
-rw-r--r--engines/pegasus/neighborhood/mars/planetmover.h57
-rw-r--r--engines/pegasus/neighborhood/mars/reactor.cpp297
-rw-r--r--engines/pegasus/neighborhood/mars/reactor.h108
-rw-r--r--engines/pegasus/neighborhood/mars/robotship.cpp267
-rw-r--r--engines/pegasus/neighborhood/mars/robotship.h84
-rw-r--r--engines/pegasus/neighborhood/mars/shuttleenergymeter.cpp116
-rw-r--r--engines/pegasus/neighborhood/mars/shuttleenergymeter.h73
-rw-r--r--engines/pegasus/neighborhood/mars/shuttlehud.cpp246
-rw-r--r--engines/pegasus/neighborhood/mars/shuttlehud.h60
-rw-r--r--engines/pegasus/neighborhood/mars/shuttleweapon.cpp129
-rw-r--r--engines/pegasus/neighborhood/mars/shuttleweapon.h68
-rw-r--r--engines/pegasus/neighborhood/mars/spacechase3d.cpp106
-rw-r--r--engines/pegasus/neighborhood/mars/spacechase3d.h91
-rw-r--r--engines/pegasus/neighborhood/mars/spacejunk.cpp212
-rw-r--r--engines/pegasus/neighborhood/mars/spacejunk.h78
-rw-r--r--engines/pegasus/neighborhood/mars/tractorbeam.cpp139
-rw-r--r--engines/pegasus/neighborhood/mars/tractorbeam.h43
-rw-r--r--engines/pegasus/neighborhood/neighborhood.cpp1774
-rw-r--r--engines/pegasus/neighborhood/neighborhood.h408
-rw-r--r--engines/pegasus/neighborhood/norad/alpha/ecrmonitor.cpp219
-rw-r--r--engines/pegasus/neighborhood/norad/alpha/ecrmonitor.h65
-rw-r--r--engines/pegasus/neighborhood/norad/alpha/fillingstation.cpp445
-rw-r--r--engines/pegasus/neighborhood/norad/alpha/fillingstation.h91
-rw-r--r--engines/pegasus/neighborhood/norad/alpha/noradalpha.cpp763
-rw-r--r--engines/pegasus/neighborhood/norad/alpha/noradalpha.h115
-rw-r--r--engines/pegasus/neighborhood/norad/alpha/panorama.cpp239
-rw-r--r--engines/pegasus/neighborhood/norad/alpha/panorama.h98
-rw-r--r--engines/pegasus/neighborhood/norad/alpha/panoramascroll.cpp91
-rw-r--r--engines/pegasus/neighborhood/norad/alpha/panoramascroll.h60
-rw-r--r--engines/pegasus/neighborhood/norad/constants.h755
-rw-r--r--engines/pegasus/neighborhood/norad/delta/globegame.cpp1062
-rw-r--r--engines/pegasus/neighborhood/norad/delta/globegame.h169
-rw-r--r--engines/pegasus/neighborhood/norad/delta/noraddelta.cpp869
-rw-r--r--engines/pegasus/neighborhood/norad/delta/noraddelta.h117
-rw-r--r--engines/pegasus/neighborhood/norad/norad.cpp285
-rw-r--r--engines/pegasus/neighborhood/norad/norad.h121
-rw-r--r--engines/pegasus/neighborhood/norad/noradelevator.cpp130
-rw-r--r--engines/pegasus/neighborhood/norad/noradelevator.h67
-rw-r--r--engines/pegasus/neighborhood/norad/pressuredoor.cpp554
-rw-r--r--engines/pegasus/neighborhood/norad/pressuredoor.h93
-rw-r--r--engines/pegasus/neighborhood/norad/pressuretracker.cpp87
-rw-r--r--engines/pegasus/neighborhood/norad/pressuretracker.h69
-rw-r--r--engines/pegasus/neighborhood/norad/subcontrolroom.cpp1178
-rw-r--r--engines/pegasus/neighborhood/norad/subcontrolroom.h133
-rw-r--r--engines/pegasus/neighborhood/norad/subplatform.cpp205
-rw-r--r--engines/pegasus/neighborhood/norad/subplatform.h63
-rw-r--r--engines/pegasus/neighborhood/prehistoric/prehistoric.cpp689
-rw-r--r--engines/pegasus/neighborhood/prehistoric/prehistoric.h158
-rw-r--r--engines/pegasus/neighborhood/spot.cpp70
-rw-r--r--engines/pegasus/neighborhood/spot.h97
-rw-r--r--engines/pegasus/neighborhood/tsa/fulltsa.cpp3023
-rw-r--r--engines/pegasus/neighborhood/tsa/fulltsa.h159
-rw-r--r--engines/pegasus/neighborhood/tsa/tinytsa.cpp453
-rw-r--r--engines/pegasus/neighborhood/tsa/tinytsa.h71
-rw-r--r--engines/pegasus/neighborhood/turn.cpp63
-rw-r--r--engines/pegasus/neighborhood/turn.h69
-rw-r--r--engines/pegasus/neighborhood/view.cpp60
-rw-r--r--engines/pegasus/neighborhood/view.h68
-rw-r--r--engines/pegasus/neighborhood/wsc/moleculebin.cpp127
-rw-r--r--engines/pegasus/neighborhood/wsc/moleculebin.h72
-rw-r--r--engines/pegasus/neighborhood/wsc/wsc.cpp2546
-rw-r--r--engines/pegasus/neighborhood/wsc/wsc.h166
-rw-r--r--engines/pegasus/neighborhood/zoom.cpp74
-rw-r--r--engines/pegasus/neighborhood/zoom.h70
-rw-r--r--engines/pegasus/notification.cpp149
-rw-r--r--engines/pegasus/notification.h123
-rw-r--r--engines/pegasus/pegasus.cpp2347
-rw-r--r--engines/pegasus/pegasus.h327
-rw-r--r--engines/pegasus/scoring.h281
-rw-r--r--engines/pegasus/sound.cpp181
-rw-r--r--engines/pegasus/sound.h108
-rw-r--r--engines/pegasus/surface.cpp396
-rw-r--r--engines/pegasus/surface.h140
-rw-r--r--engines/pegasus/timers.cpp429
-rw-r--r--engines/pegasus/timers.h260
-rw-r--r--engines/pegasus/transition.cpp200
-rw-r--r--engines/pegasus/transition.h108
-rw-r--r--engines/pegasus/types.h161
-rw-r--r--engines/pegasus/util.cpp77
-rw-r--r--engines/pegasus/util.h117
-rw-r--r--engines/plugins_table.h3
-rw-r--r--engines/queen/display.cpp38
-rw-r--r--engines/queen/queen.cpp4
-rw-r--r--engines/saga/script.cpp2
-rw-r--r--engines/sci/console.cpp6
-rw-r--r--engines/sci/detection.cpp11
-rw-r--r--engines/sci/detection_tables.h22
-rw-r--r--engines/sci/engine/features.cpp8
-rw-r--r--engines/sci/engine/file.cpp4
-rw-r--r--engines/sci/engine/kernel_tables.h4
-rw-r--r--engines/sci/engine/kfile.cpp6
-rw-r--r--engines/sci/engine/kpathing.cpp647
-rw-r--r--engines/sci/engine/kstring.cpp1
-rw-r--r--engines/sci/engine/kvideo.cpp2
-rw-r--r--engines/sci/engine/script.cpp2
-rw-r--r--engines/sci/engine/script_patches.cpp81
-rw-r--r--engines/sci/engine/scriptdebug.cpp5
-rw-r--r--engines/sci/engine/seg_manager.cpp2
-rw-r--r--engines/sci/engine/vm.cpp2
-rw-r--r--engines/sci/engine/workarounds.cpp3
-rw-r--r--engines/sci/graphics/controls32.cpp6
-rw-r--r--engines/sci/graphics/frameout.cpp14
-rw-r--r--engines/sci/graphics/paint16.cpp4
-rw-r--r--engines/sci/graphics/ports.cpp41
-rw-r--r--engines/sci/sci.cpp1
-rw-r--r--engines/sci/sci.h21
-rw-r--r--engines/sci/sound/drivers/fmtowns.cpp12
-rw-r--r--engines/sci/sound/midiparser_sci.cpp80
-rw-r--r--engines/sci/sound/midiparser_sci.h2
-rw-r--r--engines/sci/sound/soundcmd.cpp6
-rw-r--r--engines/sci/video/robot_decoder.cpp6
-rw-r--r--engines/sci/video/robot_decoder.h4
-rw-r--r--engines/scumm/actor.cpp30
-rw-r--r--engines/scumm/actor.h2
-rw-r--r--engines/scumm/charset.cpp8
-rw-r--r--engines/scumm/charset.h4
-rw-r--r--engines/scumm/costume.cpp4
-rw-r--r--engines/scumm/cursor.cpp2
-rw-r--r--engines/scumm/debugger.cpp2
-rw-r--r--engines/scumm/detection.cpp9
-rw-r--r--engines/scumm/detection_tables.h2
-rw-r--r--engines/scumm/dialogs.cpp2
-rw-r--r--engines/scumm/he/logic/soccer.cpp4
-rw-r--r--engines/scumm/he/wiz_he.cpp3
-rw-r--r--engines/scumm/imuse/imuse.cpp41
-rw-r--r--engines/scumm/imuse/imuse_internal.h2
-rw-r--r--engines/scumm/imuse/imuse_part.cpp13
-rw-r--r--engines/scumm/imuse/imuse_player.cpp5
-rw-r--r--engines/scumm/imuse/instrument.cpp60
-rw-r--r--engines/scumm/imuse/instrument.h4
-rw-r--r--engines/scumm/imuse/mac_m68k.cpp514
-rw-r--r--engines/scumm/imuse/mac_m68k.h177
-rw-r--r--engines/scumm/imuse/sysex_scumm.cpp2
-rw-r--r--engines/scumm/midiparser_ro.cpp16
-rw-r--r--engines/scumm/module.mk1
-rw-r--r--engines/scumm/object.cpp4
-rw-r--r--engines/scumm/player_apple2.cpp68
-rw-r--r--engines/scumm/player_apple2.h10
-rw-r--r--engines/scumm/player_towns.cpp2
-rw-r--r--engines/scumm/player_v2cms.cpp64
-rw-r--r--engines/scumm/saveload.cpp2
-rw-r--r--engines/scumm/saveload.h2
-rw-r--r--engines/scumm/script_v0.cpp12
-rw-r--r--engines/scumm/script_v2.cpp6
-rw-r--r--engines/scumm/script_v5.cpp2
-rw-r--r--engines/scumm/scumm.cpp37
-rw-r--r--engines/scumm/scumm.h13
-rw-r--r--engines/scumm/sound.cpp9
-rw-r--r--engines/scumm/verbs.cpp4
-rw-r--r--engines/sky/detection.cpp4
-rw-r--r--engines/sword1/animation.cpp6
-rw-r--r--engines/sword1/control.cpp4
-rw-r--r--engines/sword1/objectman.cpp4
-rw-r--r--engines/sword1/sword1.cpp4
-rw-r--r--engines/sword1/sword1.h1
-rw-r--r--engines/sword2/sprite.cpp4
-rw-r--r--engines/sword25/sfx/soundengine.cpp2
-rw-r--r--engines/teenagent/actor.cpp87
-rw-r--r--engines/teenagent/actor.h17
-rw-r--r--engines/teenagent/animation.cpp120
-rw-r--r--engines/teenagent/animation.h8
-rw-r--r--engines/teenagent/callbacks.cpp4676
-rw-r--r--engines/teenagent/detection.cpp3
-rw-r--r--engines/teenagent/dialog.cpp117
-rw-r--r--engines/teenagent/dialog.h55
-rw-r--r--engines/teenagent/font.cpp83
-rw-r--r--engines/teenagent/font.h18
-rw-r--r--engines/teenagent/inventory.cpp160
-rw-r--r--engines/teenagent/inventory.h115
-rw-r--r--engines/teenagent/music.cpp48
-rw-r--r--engines/teenagent/music.h7
-rw-r--r--engines/teenagent/objects.cpp53
-rw-r--r--engines/teenagent/objects.h23
-rw-r--r--engines/teenagent/pack.cpp19
-rw-r--r--engines/teenagent/resources.cpp71
-rw-r--r--engines/teenagent/resources.h1149
-rw-r--r--engines/teenagent/scene.cpp884
-rw-r--r--engines/teenagent/scene.h74
-rw-r--r--engines/teenagent/segment.h12
-rw-r--r--engines/teenagent/surface.cpp70
-rw-r--r--engines/teenagent/surface.h11
-rw-r--r--engines/teenagent/surface_list.cpp23
-rw-r--r--engines/teenagent/surface_list.h8
-rw-r--r--engines/teenagent/teenagent.cpp442
-rw-r--r--engines/teenagent/teenagent.h106
-rw-r--r--engines/tinsel/actors.cpp4
-rw-r--r--engines/tinsel/pcode.cpp4
-rw-r--r--engines/tinsel/saveload.cpp2
-rw-r--r--engines/toltecs/animation.cpp14
-rw-r--r--engines/toltecs/animation.h2
-rw-r--r--engines/toltecs/menu.cpp110
-rw-r--r--engines/toltecs/menu.h21
-rw-r--r--engines/toltecs/microtiles.cpp2
-rw-r--r--engines/toltecs/movie.cpp58
-rw-r--r--engines/toltecs/movie.h8
-rw-r--r--engines/toltecs/music.cpp20
-rw-r--r--engines/toltecs/music.h2
-rw-r--r--engines/toltecs/palette.cpp18
-rw-r--r--engines/toltecs/palette.h2
-rw-r--r--engines/toltecs/render.cpp14
-rw-r--r--engines/toltecs/render.h4
-rw-r--r--engines/toltecs/resource.cpp8
-rw-r--r--engines/toltecs/saveload.cpp17
-rw-r--r--engines/toltecs/screen.cpp49
-rw-r--r--engines/toltecs/screen.h19
-rw-r--r--engines/toltecs/script.cpp41
-rw-r--r--engines/toltecs/script.h6
-rw-r--r--engines/toltecs/segmap.cpp20
-rw-r--r--engines/toltecs/segmap.h8
-rw-r--r--engines/toltecs/sound.cpp107
-rw-r--r--engines/toltecs/sound.h7
-rw-r--r--engines/toltecs/sprite.cpp20
-rw-r--r--engines/toltecs/toltecs.cpp82
-rw-r--r--engines/toltecs/toltecs.h23
-rw-r--r--engines/tony/custom.cpp825
-rw-r--r--engines/tony/custom.h18
-rw-r--r--engines/tony/detection_tables.h49
-rw-r--r--engines/tony/font.cpp71
-rw-r--r--engines/tony/font.h4
-rw-r--r--engines/tony/game.cpp35
-rw-r--r--engines/tony/gfxcore.cpp282
-rw-r--r--engines/tony/gfxcore.h40
-rw-r--r--engines/tony/gfxengine.cpp59
-rw-r--r--engines/tony/inventory.cpp49
-rw-r--r--engines/tony/loc.cpp368
-rw-r--r--engines/tony/loc.h10
-rw-r--r--engines/tony/mpal/expr.cpp92
-rw-r--r--engines/tony/mpal/expr.h61
-rw-r--r--engines/tony/mpal/loadmpc.cpp6
-rw-r--r--engines/tony/mpal/memory.cpp4
-rw-r--r--engines/tony/mpal/memory.h2
-rw-r--r--engines/tony/mpal/mpal.cpp55
-rw-r--r--engines/tony/mpal/mpal.h2
-rw-r--r--engines/tony/mpal/mpalutils.cpp2
-rw-r--r--engines/tony/mpal/mpalutils.h2
-rw-r--r--engines/tony/sound.cpp247
-rw-r--r--engines/tony/sound.h98
-rw-r--r--engines/tony/tony.cpp31
-rw-r--r--engines/tony/tony.h3
-rw-r--r--engines/tony/utils.cpp2
-rw-r--r--engines/tony/window.cpp2
-rw-r--r--engines/toon/detection.cpp2
-rw-r--r--engines/toon/movie.h2
-rw-r--r--engines/toon/picture.cpp2
-rw-r--r--engines/touche/staticres.cpp5
-rw-r--r--engines/tsage/blue_force/blueforce_scenes3.cpp8
-rw-r--r--engines/tsage/blue_force/blueforce_scenes7.cpp2
-rw-r--r--engines/tsage/blue_force/blueforce_speakers.cpp28
-rw-r--r--engines/tsage/blue_force/blueforce_speakers.h6
-rw-r--r--engines/tsage/detection.cpp2
-rw-r--r--engines/tsage/globals.cpp8
-rw-r--r--engines/tsage/ringworld/ringworld_logic.cpp2
-rw-r--r--engines/tsage/ringworld2/ringworld2_logic.cpp6
-rw-r--r--engines/tsage/scenes.h2
-rw-r--r--engines/tsage/tsage.cpp6
-rw-r--r--engines/tucker/resource.cpp33
-rw-r--r--engines/wintermute/ad/ad_actor.cpp34
-rw-r--r--engines/wintermute/ad/ad_actor.h2
-rw-r--r--engines/wintermute/ad/ad_entity.cpp47
-rw-r--r--engines/wintermute/ad/ad_entity.h2
-rw-r--r--engines/wintermute/ad/ad_game.cpp37
-rw-r--r--engines/wintermute/ad/ad_game.h2
-rw-r--r--engines/wintermute/ad/ad_inventory_box.cpp1
-rw-r--r--engines/wintermute/ad/ad_item.cpp28
-rw-r--r--engines/wintermute/ad/ad_item.h2
-rw-r--r--engines/wintermute/ad/ad_layer.cpp20
-rw-r--r--engines/wintermute/ad/ad_layer.h2
-rw-r--r--engines/wintermute/ad/ad_object.cpp37
-rw-r--r--engines/wintermute/ad/ad_object.h2
-rw-r--r--engines/wintermute/ad/ad_region.cpp20
-rw-r--r--engines/wintermute/ad/ad_region.h2
-rw-r--r--engines/wintermute/ad/ad_response.cpp2
-rw-r--r--engines/wintermute/ad/ad_response_box.cpp13
-rw-r--r--engines/wintermute/ad/ad_rot_level.cpp4
-rw-r--r--engines/wintermute/ad/ad_scale_level.cpp4
-rw-r--r--engines/wintermute/ad/ad_scene.cpp39
-rw-r--r--engines/wintermute/ad/ad_scene.h2
-rw-r--r--engines/wintermute/ad/ad_scene_state.cpp2
-rw-r--r--engines/wintermute/ad/ad_sentence.cpp9
-rw-r--r--engines/wintermute/ad/ad_sprite_set.cpp2
-rw-r--r--engines/wintermute/ad/ad_talk_def.cpp2
-rw-r--r--engines/wintermute/ad/ad_talk_holder.cpp10
-rw-r--r--engines/wintermute/ad/ad_talk_holder.h2
-rw-r--r--engines/wintermute/ad/ad_talk_node.cpp6
-rw-r--r--engines/wintermute/ad/ad_waypoint_group.cpp12
-rw-r--r--engines/wintermute/ad/ad_waypoint_group.h2
-rw-r--r--engines/wintermute/base/base_active_rect.cpp1
-rw-r--r--engines/wintermute/base/base_dynamic_buffer.h7
-rw-r--r--engines/wintermute/base/base_engine.cpp12
-rw-r--r--engines/wintermute/base/base_engine.h6
-rw-r--r--engines/wintermute/base/base_fader.cpp1
-rw-r--r--engines/wintermute/base/base_fader.h2
-rw-r--r--engines/wintermute/base/base_frame.cpp24
-rw-r--r--engines/wintermute/base/base_frame.h12
-rw-r--r--engines/wintermute/base/base_game.cpp103
-rw-r--r--engines/wintermute/base/base_game.h3
-rw-r--r--engines/wintermute/base/base_keyboard_state.cpp16
-rw-r--r--engines/wintermute/base/base_keyboard_state.h2
-rw-r--r--engines/wintermute/base/base_object.cpp48
-rw-r--r--engines/wintermute/base/base_object.h2
-rw-r--r--engines/wintermute/base/base_quick_msg.h6
-rw-r--r--engines/wintermute/base/base_region.cpp10
-rw-r--r--engines/wintermute/base/base_region.h9
-rw-r--r--engines/wintermute/base/base_save_thumb_helper.cpp1
-rw-r--r--engines/wintermute/base/base_script_holder.cpp8
-rw-r--r--engines/wintermute/base/base_script_holder.h2
-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.cpp29
-rw-r--r--engines/wintermute/base/base_sprite.h39
-rw-r--r--engines/wintermute/base/base_sub_frame.cpp26
-rw-r--r--engines/wintermute/base/base_sub_frame.h5
-rw-r--r--engines/wintermute/base/base_surface_storage.cpp1
-rw-r--r--engines/wintermute/base/base_transition_manager.cpp1
-rw-r--r--engines/wintermute/base/base_viewport.cpp1
-rw-r--r--engines/wintermute/base/file/base_disk_file.cpp4
-rw-r--r--engines/wintermute/base/file/base_package.cpp8
-rw-r--r--engines/wintermute/base/file/base_save_thumb_file.cpp1
-rw-r--r--engines/wintermute/base/font/base_font_bitmap.cpp1
-rw-r--r--engines/wintermute/base/font/base_font_storage.cpp1
-rw-r--r--engines/wintermute/base/font/base_font_truetype.cpp8
-rw-r--r--engines/wintermute/base/gfx/base_renderer.cpp10
-rw-r--r--engines/wintermute/base/gfx/osystem/base_render_osystem.cpp7
-rw-r--r--engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp1
-rw-r--r--engines/wintermute/base/particles/part_emitter.cpp73
-rw-r--r--engines/wintermute/base/particles/part_emitter.h2
-rw-r--r--engines/wintermute/base/saveload.cpp47
-rw-r--r--engines/wintermute/base/saveload.h8
-rw-r--r--engines/wintermute/base/scriptables/script_engine.cpp1
-rw-r--r--engines/wintermute/base/scriptables/script_ext_array.cpp8
-rw-r--r--engines/wintermute/base/scriptables/script_ext_array.h2
-rw-r--r--engines/wintermute/base/scriptables/script_ext_date.cpp6
-rw-r--r--engines/wintermute/base/scriptables/script_ext_date.h2
-rw-r--r--engines/wintermute/base/scriptables/script_ext_file.cpp15
-rw-r--r--engines/wintermute/base/scriptables/script_ext_file.h2
-rw-r--r--engines/wintermute/base/scriptables/script_ext_math.cpp6
-rw-r--r--engines/wintermute/base/scriptables/script_ext_math.h2
-rw-r--r--engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp6
-rw-r--r--engines/wintermute/base/scriptables/script_ext_mem_buffer.h2
-rw-r--r--engines/wintermute/base/scriptables/script_ext_string.cpp8
-rw-r--r--engines/wintermute/base/scriptables/script_ext_string.h2
-rw-r--r--engines/wintermute/base/sound/base_sound_buffer.cpp2
-rw-r--r--engines/wintermute/base/sound/base_sound_manager.cpp1
-rw-r--r--engines/wintermute/graphics/transparent_surface.cpp6
-rw-r--r--engines/wintermute/persistent.h4
-rw-r--r--engines/wintermute/readme.txt155
-rw-r--r--engines/wintermute/system/sys_class_registry.cpp1
-rw-r--r--engines/wintermute/ui/ui_button.cpp13
-rw-r--r--engines/wintermute/ui/ui_button.h2
-rw-r--r--engines/wintermute/ui/ui_edit.cpp19
-rw-r--r--engines/wintermute/ui/ui_edit.h2
-rw-r--r--engines/wintermute/ui/ui_entity.cpp6
-rw-r--r--engines/wintermute/ui/ui_entity.h2
-rw-r--r--engines/wintermute/ui/ui_object.cpp25
-rw-r--r--engines/wintermute/ui/ui_object.h2
-rw-r--r--engines/wintermute/ui/ui_text.cpp8
-rw-r--r--engines/wintermute/ui/ui_text.h2
-rw-r--r--engines/wintermute/ui/ui_tiled_image.cpp5
-rw-r--r--engines/wintermute/ui/ui_window.cpp23
-rw-r--r--engines/wintermute/ui/ui_window.h2
-rw-r--r--engines/wintermute/utils/string_util.cpp12
-rw-r--r--engines/wintermute/video/video_theora_player.cpp33
-rw-r--r--engines/wintermute/wintermute.cpp1
-rw-r--r--graphics/VectorRenderer.cpp2
-rw-r--r--graphics/VectorRenderer.h2
-rw-r--r--graphics/VectorRendererSpec.cpp64
-rw-r--r--graphics/conversion.cpp202
-rw-r--r--graphics/conversion.h19
-rw-r--r--graphics/decoders/bmp.cpp12
-rw-r--r--graphics/decoders/bmp.h1
-rw-r--r--graphics/decoders/image_decoder.h7
-rw-r--r--graphics/decoders/jpeg.cpp4
-rw-r--r--graphics/decoders/jpeg.h1
-rw-r--r--graphics/decoders/pcx.cpp213
-rw-r--r--graphics/decoders/pcx.h68
-rw-r--r--graphics/decoders/pict.cpp25
-rw-r--r--graphics/decoders/pict.h5
-rw-r--r--graphics/decoders/png.cpp1
-rw-r--r--graphics/decoders/png.h1
-rw-r--r--graphics/decoders/tga.cpp5
-rw-r--r--graphics/decoders/tga.h2
-rw-r--r--graphics/fonts/consolefont.cpp2
-rw-r--r--graphics/fonts/newfont.cpp2
-rw-r--r--graphics/fonts/newfont_big.cpp2
-rw-r--r--graphics/module.mk1
-rw-r--r--graphics/primitives.cpp62
-rw-r--r--graphics/primitives.h2
-rw-r--r--graphics/scaler/aspect.cpp56
-rw-r--r--graphics/sjis.h2
-rw-r--r--graphics/surface.cpp78
-rw-r--r--graphics/surface.h30
-rw-r--r--graphics/yuv_to_rgb.cpp188
-rw-r--r--graphics/yuv_to_rgb.h116
-rw-r--r--gui/ThemeParser.cpp4
-rw-r--r--gui/ThemeParser.h2
-rw-r--r--gui/credits.h22
-rw-r--r--gui/launcher.cpp2
-rw-r--r--gui/options.cpp2
-rw-r--r--gui/predictivedialog.cpp18
-rw-r--r--gui/saveload-dialog.cpp78
-rw-r--r--gui/saveload-dialog.h1
-rw-r--r--gui/themes/translations.datbin370908 -> 371963 bytes
-rw-r--r--gui/widget.cpp66
-rw-r--r--gui/widget.h4
-rw-r--r--gui/widgets/editable.h4
-rw-r--r--gui/widgets/list.h1
-rw-r--r--po/ru_RU.po27
-rw-r--r--po/uk_UA.po33
-rw-r--r--ports.mk3
-rw-r--r--test/common/memorywritestream.h31
-rw-r--r--video/avi_decoder.cpp2
-rw-r--r--video/avi_decoder.h2
-rw-r--r--video/bink_decoder.cpp26
-rw-r--r--video/bink_decoder.h2
-rw-r--r--video/codecs/svq1.cpp43
-rw-r--r--video/coktel_decoder.cpp2
-rw-r--r--video/psx_decoder.cpp6
-rw-r--r--video/psx_decoder.h2
-rw-r--r--video/qt_decoder.cpp43
-rw-r--r--video/qt_decoder.h1
-rw-r--r--video/smk_decoder.cpp2
-rw-r--r--video/theora_decoder.cpp4
-rw-r--r--video/theora_decoder.h1
-rw-r--r--video/video_decoder.cpp42
-rw-r--r--video/video_decoder.h19
710 files changed, 84827 insertions, 8999 deletions
diff --git a/AUTHORS b/AUTHORS
index fe806c4490..2ae50159c3 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -6,8 +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
---------
@@ -18,29 +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:
@@ -48,26 +50,26 @@ 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)
CGE:
Arnaud Boutonne
Paul Gilbert
Cine:
- Vincent Hamm - (retired)
+ Vincent Hamm - (retired)
Pawel Kolodziejski
- Gregory Montoir - (retired)
+ Gregory Montoir - (retired)
Kari Salminen
Eugene Sandulenko
@@ -76,7 +78,7 @@ ScummVM Team
CruisE:
Paul Gilbert
- Vincent Hamm - (retired)
+ Vincent Hamm - (retired)
Draci:
Denis Kasak
@@ -90,7 +92,7 @@ ScummVM Team
Torbjorn Andersson
Bertrand Augereau
Filippos Karapetis
- Vladimir Menshakov - (retired)
+ Vladimir Menshakov - (retired)
Willem Jan Palenstijn
Gob:
@@ -110,10 +112,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:
@@ -139,15 +141,18 @@ ScummVM Team
Parallaction:
peres
+ Pegasus:
+ 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
@@ -155,61 +160,69 @@ 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
+ Tony:
+ Arnaud Boutonne
+ Paul Gilbert
+ Alyssa Milburn
+
Toon:
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
Backend Teams
-------------
@@ -233,26 +246,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):
@@ -260,8 +273,8 @@ 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
@@ -276,8 +289,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
@@ -287,30 +301,31 @@ 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)
- 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)
+ 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)
@@ -319,31 +334,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
@@ -353,22 +368,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
@@ -386,12 +401,12 @@ Other contributions
Travis Howell
Win64:
- Chris Gray - (retired)
+ Chris Gray - (retired)
Johannes Schickel
Translations
------------
- Thierry Crozat - Translation Lead
+ Thierry Crozat - Translation Lead
Basque:
Mikel Iturbe Urretxa
@@ -413,7 +428,7 @@ Other contributions
German:
Simon Sawatzki
- Lothar Serra Mari
+ Lothar Serra Mari - (retired)
Hungarian:
Alex Bevilacqua
@@ -449,92 +464,95 @@ Other contributions
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
+ 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. Lansdo - 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.
@@ -546,28 +564,27 @@ Other contributions
Special thanks to
*****************
- Daniel Balsom - For the original Reinherit (SAGA) code
- Sander Buskens - For his work on the initial reversing of Monkey2
- Canadacow - For the original MT-32 emulator
- Kevin Carnes - For Scumm16, the basis of ScummVM's older gfx codecs
- Curt Coder - For the original TrollVM (preAGI) code
- Patrick Combet - For the original Gobliiins ADL player
- Ivan Dubrov - For contributing the initial version of the Gobliiins
- engine
- Henrik Engqvist - For generously providing hosting for our buildbot, SVN
- repository, planet and doxygen sites as well as tons of
- HD space
- DOSBox Team - For their awesome OPL2 and OPL3 emulator
- Till Kresslein - For design of modern ScummVM GUI
- Jezar - For his freeverb filter implementation
- Jim Leiterman - Various info on his FM-TOWNS/Marty SCUMM ports
- lloyd - For deep tech details about C64 Zak & MM
- Sarien Team - Original AGI engine code
- Jimmi Thogersen - For ScummRev, and much obscure code/documentation
- Tristan - For additional work on the original MT-32 emulator
- James Woodcock - Soundtrack enhancements
-
- Some icons by Yusuke Kamiyamane
+ Daniel Balsom - For the original Reinherit (SAGA) code
+ Sander Buskens - For his work on the initial reversing of Monkey2
+ Canadacow - For the original MT-32 emulator
+ Kevin Carnes - For Scumm16, the basis of ScummVM's older gfx codecs
+ Curt Coder - For the original TrollVM (preAGI) code
+ Patrick Combet - For the original Gobliiins ADL player
+ Ivan Dubrov - For contributing the initial version of the Gobliiins
+ engine
+ Henrik Engqvist - For generously providing hosting for our buildbot, SVN
+ repository, planet and doxygen sites as well as tons
+ of HD space
+ DOSBox Team - For their awesome OPL2 and OPL3 emulator
+ Yusuke Kamiyamane - For contributing some GUI icons
+ Till Kresslein - For design of modern ScummVM GUI
+ Jezar - For his freeverb filter implementation
+ Jim Leiterman - Various info on his FM-TOWNS/Marty SCUMM ports
+ lloyd - For deep tech details about C64 Zak & MM
+ Sarien Team - Original AGI engine code
+ Jimmi Thogersen - For ScummRev, and much obscure code/documentation
+ Tristan - For additional work on the original MT-32 emulator
+ James Woodcock - Soundtrack enhancements
Tony Warriner and everyone at Revolution Software Ltd. for sharing with us
the source of some of their brilliant games, allowing us to release
@@ -606,6 +623,12 @@ Special thanks to
of Dreamweb and for their tremendous support.
Janusz Wisniewski and Miroslaw Liminowicz from Laboratorium Komputerowe
- Avalon for providing full source code for Soltys and letting us to
+ Avalon for providing full source code for Soltys and letting us
redistribute the game.
+ Jan Nedoma for providing the sources to the Wintermute-engine, and for his
+ support while porting the engine to ScummVM.
+
+ Bob Bell, Michel Kripalani, Tommy Yune, from Presto Studios for providing
+ the source code of The Journeyman Project: Pegasus Prime.
+
diff --git a/NEWS b/NEWS
index 1f736aa74f..923844e32c 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,16 @@ For a more comprehensive changelog of the latest experimental code, see:
- Rewrote VideoDecoder subsystem.
- Added Galician translation.
+ Cine:
+ - Improved audio support for Amiga and AtariST versions of Future Wars.
+ Now music fades out slowly instead of stopping immediately. Sound
+ effects are now properly panned, when requested by the game.
+
+ SCUMM:
+ - Implemented Monkey Island 2 Macintosh's audio driver. Now we properly
+ support its sample based audio output. The same output is also used for
+ the m68k Macintosh version of Indiana Jones and the Fate of Atlantis.
+
1.5.0 (2012-07-27)
New Games:
- Added support for Backyard Baseball 2003.
diff --git a/audio/audiostream.cpp b/audio/audiostream.cpp
index 6e185702f0..2d65d4afef 100644
--- a/audio/audiostream.cpp
+++ b/audio/audiostream.cpp
@@ -402,7 +402,7 @@ public:
}
int readBuffer(int16 *buffer, const int numSamples) {
- // Cap us off so we don't read past _totalSamples
+ // Cap us off so we don't read past _totalSamples
int samplesRead = _parentStream->readBuffer(buffer, MIN<int>(numSamples, _totalSamples - _samplesRead));
_samplesRead += samplesRead;
return samplesRead;
@@ -413,7 +413,7 @@ public:
int getRate() const { return _parentStream->getRate(); }
private:
- int getChannels() const { return isStereo() ? 2 : 1; }
+ int getChannels() const { return isStereo() ? 2 : 1; }
AudioStream *_parentStream;
DisposeAfterUse::Flag _disposeAfterUse;
diff --git a/audio/decoders/aiff.h b/audio/decoders/aiff.h
index 59664bb85a..afcdb6ae6c 100644
--- a/audio/decoders/aiff.h
+++ b/audio/decoders/aiff.h
@@ -23,6 +23,7 @@
/**
* @file
* Sound decoder used in engines:
+ * - pegasus
* - saga
* - sci
* - sword1
diff --git a/audio/decoders/quicktime.cpp b/audio/decoders/quicktime.cpp
index 5276cfc530..0588650ec6 100644
--- a/audio/decoders/quicktime.cpp
+++ b/audio/decoders/quicktime.cpp
@@ -195,7 +195,7 @@ QuickTimeAudioDecoder::QuickTimeAudioTrack::QuickTimeAudioTrack(QuickTimeAudioDe
if (entry->getCodecTag() == MKTAG('r', 'a', 'w', ' ') || entry->getCodecTag() == MKTAG('t', 'w', 'o', 's'))
_parentTrack->sampleSize = (entry->_bitsPerSample / 8) * entry->_channels;
-
+
// Initialize our edit parser too
_curEdit = 0;
enterNewEdit(Timestamp());
@@ -395,9 +395,9 @@ AudioStream *QuickTimeAudioDecoder::QuickTimeAudioTrack::readAudioChunk(uint chu
}
void QuickTimeAudioDecoder::QuickTimeAudioTrack::skipSamples(const Timestamp &length, AudioStream *stream) {
- uint32 sampleCount = length.convertToFramerate(getRate()).totalNumberOfFrames();
+ int32 sampleCount = length.convertToFramerate(getRate()).totalNumberOfFrames();
- if (sampleCount == 0)
+ if (sampleCount <= 0)
return;
if (isStereo())
@@ -426,7 +426,7 @@ void QuickTimeAudioDecoder::QuickTimeAudioTrack::enterNewEdit(const Timestamp &p
// If we're at the end of the edit list, there's nothing else for us to do here
if (allDataRead())
return;
-
+
// For an empty edit, we may need to adjust the start time
if (_parentTrack->editList[_curEdit].mediaTime == -1) {
// Just invalidate the current media position (and make sure the scale
diff --git a/audio/decoders/quicktime.h b/audio/decoders/quicktime.h
index 4dd1a57710..4c0b93488e 100644
--- a/audio/decoders/quicktime.h
+++ b/audio/decoders/quicktime.h
@@ -25,6 +25,7 @@
* Sound decoder used in engines:
* - groovie
* - mohawk
+ * - pegasus
* - sci
*/
diff --git a/audio/decoders/quicktime_intern.h b/audio/decoders/quicktime_intern.h
index efc97cbd13..f1ab037d89 100644
--- a/audio/decoders/quicktime_intern.h
+++ b/audio/decoders/quicktime_intern.h
@@ -88,7 +88,7 @@ protected:
private:
QuickTimeAudioDecoder *_decoder;
- Track *_parentTrack;
+ Track *_parentTrack;
QueuingAudioStream *_queue;
uint _curChunk;
Timestamp _curMediaPos, _skipSamples;
@@ -115,7 +115,7 @@ protected:
~AudioSampleDesc();
bool isAudioCodecSupported() const;
-
+
AudioStream *createAudioStream(Common::SeekableReadStream *stream) const;
void initCodec();
diff --git a/audio/mididrv.cpp b/audio/mididrv.cpp
index 0518915e81..dea07a739b 100644
--- a/audio/mididrv.cpp
+++ b/audio/mididrv.cpp
@@ -240,7 +240,7 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
devStr = ConfMan.hasKey("gm_device") ? ConfMan.get("gm_device") : Common::String("null");
else
devStr = "auto";
-
+
// Default to Null device here, since we also register a default null setting for
// the MT32 or GM device in the config manager.
hdl = getDeviceHandle(devStr.empty() ? Common::String("null") : devStr);
diff --git a/audio/midiparser.cpp b/audio/midiparser.cpp
index 943a6067a4..eec32c05d1 100644
--- a/audio/midiparser.cpp
+++ b/audio/midiparser.cpp
@@ -32,24 +32,24 @@
//////////////////////////////////////////////////
MidiParser::MidiParser() :
-_hanging_notes_count(0),
+_hangingNotesCount(0),
_driver(0),
-_timer_rate(0x4A0000),
+_timerRate(0x4A0000),
_ppqn(96),
_tempo(500000),
-_psec_per_tick(5208), // 500000 / 96
+_psecPerTick(5208), // 500000 / 96
_autoLoop(false),
_smartJump(false),
_centerPitchWheelOnUnload(false),
_sendSustainOffOnNotesOff(false),
-_num_tracks(0),
-_active_track(255),
-_abort_parse(0) {
- memset(_active_notes, 0, sizeof(_active_notes));
- _next_event.start = NULL;
- _next_event.delta = 0;
- _next_event.event = 0;
- _next_event.length = 0;
+_numTracks(0),
+_activeTrack(255),
+_abortParse(0) {
+ memset(_activeNotes, 0, sizeof(_activeNotes));
+ _nextEvent.start = NULL;
+ _nextEvent.delta = 0;
+ _nextEvent.event = 0;
+ _nextEvent.length = 0;
}
void MidiParser::property(int prop, int value) {
@@ -76,7 +76,7 @@ void MidiParser::sendToDriver(uint32 b) {
void MidiParser::setTempo(uint32 tempo) {
_tempo = tempo;
if (_ppqn)
- _psec_per_tick = (tempo + (_ppqn >> 2)) / _ppqn;
+ _psecPerTick = (tempo + (_ppqn >> 2)) / _ppqn;
}
// This is the conventional (i.e. SMF) variable length quantity
@@ -100,44 +100,44 @@ void MidiParser::activeNote(byte channel, byte note, bool active) {
return;
if (active)
- _active_notes[note] |= (1 << channel);
+ _activeNotes[note] |= (1 << channel);
else
- _active_notes[note] &= ~(1 << channel);
+ _activeNotes[note] &= ~(1 << channel);
// See if there are hanging notes that we can cancel
- NoteTimer *ptr = _hanging_notes;
+ NoteTimer *ptr = _hangingNotes;
int i;
- for (i = ARRAYSIZE(_hanging_notes); i; --i, ++ptr) {
- if (ptr->channel == channel && ptr->note == note && ptr->time_left) {
- ptr->time_left = 0;
- --_hanging_notes_count;
+ for (i = ARRAYSIZE(_hangingNotes); i; --i, ++ptr) {
+ if (ptr->channel == channel && ptr->note == note && ptr->timeLeft) {
+ ptr->timeLeft = 0;
+ --_hangingNotesCount;
break;
}
}
}
-void MidiParser::hangingNote(byte channel, byte note, uint32 time_left, bool recycle) {
+void MidiParser::hangingNote(byte channel, byte note, uint32 timeLeft, bool recycle) {
NoteTimer *best = 0;
- NoteTimer *ptr = _hanging_notes;
+ NoteTimer *ptr = _hangingNotes;
int i;
- if (_hanging_notes_count >= ARRAYSIZE(_hanging_notes)) {
+ if (_hangingNotesCount >= ARRAYSIZE(_hangingNotes)) {
warning("MidiParser::hangingNote(): Exceeded polyphony");
return;
}
- for (i = ARRAYSIZE(_hanging_notes); i; --i, ++ptr) {
+ for (i = ARRAYSIZE(_hangingNotes); i; --i, ++ptr) {
if (ptr->channel == channel && ptr->note == note) {
- if (ptr->time_left && ptr->time_left < time_left && recycle)
+ if (ptr->timeLeft && ptr->timeLeft < timeLeft && recycle)
return;
best = ptr;
- if (ptr->time_left) {
+ if (ptr->timeLeft) {
if (recycle)
sendToDriver(0x80 | channel, note, 0);
- --_hanging_notes_count;
+ --_hangingNotesCount;
}
break;
- } else if (!best && ptr->time_left == 0) {
+ } else if (!best && ptr->timeLeft == 0) {
best = ptr;
}
}
@@ -146,14 +146,14 @@ void MidiParser::hangingNote(byte channel, byte note, uint32 time_left, bool rec
// length, if the note should be turned on and off in
// the same iteration. For now just set it to 1 and
// we'll turn it off in the next cycle.
- if (!time_left || time_left & 0x80000000)
- time_left = 1;
+ if (!timeLeft || timeLeft & 0x80000000)
+ timeLeft = 1;
if (best) {
best->channel = channel;
best->note = note;
- best->time_left = time_left;
- ++_hanging_notes_count;
+ best->timeLeft = timeLeft;
+ ++_hangingNotesCount;
} else {
// We checked this up top. We should never get here!
warning("MidiParser::hangingNote(): Internal error");
@@ -161,45 +161,45 @@ void MidiParser::hangingNote(byte channel, byte note, uint32 time_left, bool rec
}
void MidiParser::onTimer() {
- uint32 end_time;
- uint32 event_time;
+ uint32 endTime;
+ uint32 eventTime;
- if (!_position._play_pos || !_driver)
+ if (!_position._playPos || !_driver)
return;
- _abort_parse = false;
- end_time = _position._play_time + _timer_rate;
+ _abortParse = false;
+ endTime = _position._playTime + _timerRate;
// Scan our hanging notes for any
// that should be turned off.
- if (_hanging_notes_count) {
- NoteTimer *ptr = &_hanging_notes[0];
+ if (_hangingNotesCount) {
+ NoteTimer *ptr = &_hangingNotes[0];
int i;
- for (i = ARRAYSIZE(_hanging_notes); i; --i, ++ptr) {
- if (ptr->time_left) {
- if (ptr->time_left <= _timer_rate) {
+ for (i = ARRAYSIZE(_hangingNotes); i; --i, ++ptr) {
+ if (ptr->timeLeft) {
+ if (ptr->timeLeft <= _timerRate) {
sendToDriver(0x80 | ptr->channel, ptr->note, 0);
- ptr->time_left = 0;
- --_hanging_notes_count;
+ ptr->timeLeft = 0;
+ --_hangingNotesCount;
} else {
- ptr->time_left -= _timer_rate;
+ ptr->timeLeft -= _timerRate;
}
}
}
}
- while (!_abort_parse) {
- EventInfo &info = _next_event;
+ while (!_abortParse) {
+ EventInfo &info = _nextEvent;
- event_time = _position._last_event_time + info.delta * _psec_per_tick;
- if (event_time > end_time)
+ eventTime = _position._lastEventTime + info.delta * _psecPerTick;
+ if (eventTime > endTime)
break;
// Process the next info.
- _position._last_event_tick += info.delta;
+ _position._lastEventTick += info.delta;
if (info.event < 0x80) {
warning("Bad command or running status %02X", info.event);
- _position._play_pos = 0;
+ _position._playPos = 0;
return;
}
@@ -217,7 +217,7 @@ void MidiParser::onTimer() {
// as well as sending it to the output device.
if (_autoLoop) {
jumpToTick(0);
- parseNextEvent(_next_event);
+ parseNextEvent(_nextEvent);
} else {
stopPlaying();
_driver->metaEvent(info.ext.type, info.ext.data, (uint16)info.length);
@@ -234,7 +234,7 @@ void MidiParser::onTimer() {
activeNote(info.channel(), info.basic.param1, false);
} else if (info.command() == 0x9) {
if (info.length > 0)
- hangingNote(info.channel(), info.basic.param1, info.length * _psec_per_tick - (end_time - event_time));
+ hangingNote(info.channel(), info.basic.param1, info.length * _psecPerTick - (endTime - eventTime));
else
activeNote(info.channel(), info.basic.param1, true);
}
@@ -242,15 +242,15 @@ void MidiParser::onTimer() {
}
- if (!_abort_parse) {
- _position._last_event_time = event_time;
- parseNextEvent(_next_event);
+ if (!_abortParse) {
+ _position._lastEventTime = eventTime;
+ parseNextEvent(_nextEvent);
}
}
- if (!_abort_parse) {
- _position._play_time = end_time;
- _position._play_tick = (_position._play_time - _position._last_event_time) / _psec_per_tick + _position._last_event_tick;
+ if (!_abortParse) {
+ _position._playTime = endTime;
+ _position._playTick = (_position._playTime - _position._lastEventTime) / _psecPerTick + _position._lastEventTick;
}
}
@@ -263,20 +263,20 @@ void MidiParser::allNotesOff() {
// Turn off all active notes
for (i = 0; i < 128; ++i) {
for (j = 0; j < 16; ++j) {
- if (_active_notes[i] & (1 << j)) {
+ if (_activeNotes[i] & (1 << j)) {
sendToDriver(0x80 | j, i, 0);
}
}
}
// Turn off all hanging notes
- for (i = 0; i < ARRAYSIZE(_hanging_notes); i++) {
- if (_hanging_notes[i].time_left) {
- sendToDriver(0x80 | _hanging_notes[i].channel, _hanging_notes[i].note, 0);
- _hanging_notes[i].time_left = 0;
+ for (i = 0; i < ARRAYSIZE(_hangingNotes); i++) {
+ if (_hangingNotes[i].timeLeft) {
+ sendToDriver(0x80 | _hangingNotes[i].channel, _hangingNotes[i].note, 0);
+ _hangingNotes[i].timeLeft = 0;
}
}
- _hanging_notes_count = 0;
+ _hangingNotesCount = 0;
// To be sure, send an "All Note Off" event (but not all MIDI devices
// support this...).
@@ -287,7 +287,7 @@ void MidiParser::allNotesOff() {
sendToDriver(0xB0 | i, 0x40, 0); // Also send a sustain off event (bug #3116608)
}
- memset(_active_notes, 0, sizeof(_active_notes));
+ memset(_activeNotes, 0, sizeof(_activeNotes));
}
void MidiParser::resetTracking() {
@@ -295,7 +295,7 @@ void MidiParser::resetTracking() {
}
bool MidiParser::setTrack(int track) {
- if (track < 0 || track >= _num_tracks)
+ if (track < 0 || track >= _numTracks)
return false;
// We allow restarting the track via setTrack when
// it isn't playing anymore. This allows us to reuse
@@ -308,7 +308,7 @@ bool MidiParser::setTrack(int track) {
// TODO: Check if any engine has problem with this
// handling, if so we need to find a better way to handle
// track restarts. (KYRA relies on this working)
- else if (track == _active_track && isPlaying())
+ else if (track == _activeTrack && isPlaying())
return true;
if (_smartJump)
@@ -317,10 +317,10 @@ bool MidiParser::setTrack(int track) {
allNotesOff();
resetTracking();
- memset(_active_notes, 0, sizeof(_active_notes));
- _active_track = track;
- _position._play_pos = _tracks[track];
- parseNextEvent(_next_event);
+ memset(_activeNotes, 0, sizeof(_activeNotes));
+ _activeTrack = track;
+ _position._playPos = _tracks[track];
+ parseNextEvent(_nextEvent);
return true;
}
@@ -332,29 +332,29 @@ void MidiParser::stopPlaying() {
void MidiParser::hangAllActiveNotes() {
// Search for note off events until we have
// accounted for every active note.
- uint16 temp_active[128];
- memcpy(temp_active, _active_notes, sizeof (temp_active));
+ uint16 tempActive[128];
+ memcpy(tempActive, _activeNotes, sizeof (tempActive));
- uint32 advance_tick = _position._last_event_tick;
+ uint32 advanceTick = _position._lastEventTick;
while (true) {
int i;
for (i = 0; i < 128; ++i)
- if (temp_active[i] != 0)
+ if (tempActive[i] != 0)
break;
if (i == 128)
break;
- parseNextEvent(_next_event);
- advance_tick += _next_event.delta;
- if (_next_event.command() == 0x8) {
- if (temp_active[_next_event.basic.param1] & (1 << _next_event.channel())) {
- hangingNote(_next_event.channel(), _next_event.basic.param1, (advance_tick - _position._last_event_tick) * _psec_per_tick, false);
- temp_active[_next_event.basic.param1] &= ~(1 << _next_event.channel());
+ parseNextEvent(_nextEvent);
+ advanceTick += _nextEvent.delta;
+ if (_nextEvent.command() == 0x8) {
+ if (tempActive[_nextEvent.basic.param1] & (1 << _nextEvent.channel())) {
+ hangingNote(_nextEvent.channel(), _nextEvent.basic.param1, (advanceTick - _position._lastEventTick) * _psecPerTick, false);
+ tempActive[_nextEvent.basic.param1] &= ~(1 << _nextEvent.channel());
}
- } else if (_next_event.event == 0xFF && _next_event.ext.type == 0x2F) {
+ } else if (_nextEvent.event == 0xFF && _nextEvent.ext.type == 0x2F) {
// warning("MidiParser::hangAllActiveNotes(): Hit End of Track with active notes left");
for (i = 0; i < 128; ++i) {
for (int j = 0; j < 16; ++j) {
- if (temp_active[i] & (1 << j)) {
+ if (tempActive[i] & (1 << j)) {
activeNote(j, i, false);
sendToDriver(0x80 | j, i, 0);
}
@@ -366,33 +366,33 @@ void MidiParser::hangAllActiveNotes() {
}
bool MidiParser::jumpToTick(uint32 tick, bool fireEvents, bool stopNotes, bool dontSendNoteOn) {
- if (_active_track >= _num_tracks)
+ if (_activeTrack >= _numTracks)
return false;
Tracker currentPos(_position);
- EventInfo currentEvent(_next_event);
+ EventInfo currentEvent(_nextEvent);
resetTracking();
- _position._play_pos = _tracks[_active_track];
- parseNextEvent(_next_event);
+ _position._playPos = _tracks[_activeTrack];
+ parseNextEvent(_nextEvent);
if (tick > 0) {
while (true) {
- EventInfo &info = _next_event;
- if (_position._last_event_tick + info.delta >= tick) {
- _position._play_time += (tick - _position._last_event_tick) * _psec_per_tick;
- _position._play_tick = tick;
+ EventInfo &info = _nextEvent;
+ if (_position._lastEventTick + info.delta >= tick) {
+ _position._playTime += (tick - _position._lastEventTick) * _psecPerTick;
+ _position._playTick = tick;
break;
}
- _position._last_event_tick += info.delta;
- _position._last_event_time += info.delta * _psec_per_tick;
- _position._play_tick = _position._last_event_tick;
- _position._play_time = _position._last_event_time;
+ _position._lastEventTick += info.delta;
+ _position._lastEventTime += info.delta * _psecPerTick;
+ _position._playTick = _position._lastEventTick;
+ _position._playTime = _position._lastEventTime;
if (info.event == 0xFF) {
if (info.ext.type == 0x2F) { // End of track
_position = currentPos;
- _next_event = currentEvent;
+ _nextEvent = currentEvent;
return false;
} else {
if (info.ext.type == 0x51 && info.length >= 3) // Tempo
@@ -419,36 +419,36 @@ bool MidiParser::jumpToTick(uint32 tick, bool fireEvents, bool stopNotes, bool d
}
}
- parseNextEvent(_next_event);
+ parseNextEvent(_nextEvent);
}
}
if (stopNotes) {
- if (!_smartJump || !currentPos._play_pos) {
+ if (!_smartJump || !currentPos._playPos) {
allNotesOff();
} else {
- EventInfo targetEvent(_next_event);
+ EventInfo targetEvent(_nextEvent);
Tracker targetPosition(_position);
_position = currentPos;
- _next_event = currentEvent;
+ _nextEvent = currentEvent;
hangAllActiveNotes();
- _next_event = targetEvent;
+ _nextEvent = targetEvent;
_position = targetPosition;
}
}
- _abort_parse = true;
+ _abortParse = true;
return true;
}
void MidiParser::unloadMusic() {
resetTracking();
allNotesOff();
- _num_tracks = 0;
- _active_track = 255;
- _abort_parse = true;
+ _numTracks = 0;
+ _activeTrack = 255;
+ _abortParse = true;
if (_centerPitchWheelOnUnload) {
// Center the pitch wheels in preparation for the next piece of
diff --git a/audio/midiparser.h b/audio/midiparser.h
index c935969e72..a4dbf174e1 100644
--- a/audio/midiparser.h
+++ b/audio/midiparser.h
@@ -49,33 +49,33 @@ class MidiDriver_BASE;
* each Tracker location.
*/
struct Tracker {
- byte * _play_pos; ///< A pointer to the next event to be parsed
- uint32 _play_time; ///< Current time in microseconds; may be in between event times
- uint32 _play_tick; ///< Current MIDI tick; may be in between event ticks
- uint32 _last_event_time; ///< The time, in microseconds, of the last event that was parsed
- uint32 _last_event_tick; ///< The tick at which the last parsed event occurs
- byte _running_status; ///< Cached MIDI command, for MIDI streams that rely on implied event codes
+ byte * _playPos; ///< A pointer to the next event to be parsed
+ uint32 _playTime; ///< Current time in microseconds; may be in between event times
+ uint32 _playTick; ///< Current MIDI tick; may be in between event ticks
+ uint32 _lastEventTime; ///< The time, in microseconds, of the last event that was parsed
+ uint32 _lastEventTick; ///< The tick at which the last parsed event occurs
+ byte _runningStatus; ///< Cached MIDI command, for MIDI streams that rely on implied event codes
Tracker() { clear(); }
/// Copy constructor for each duplication of Tracker information.
Tracker(const Tracker &copy) :
- _play_pos(copy._play_pos),
- _play_time(copy._play_time),
- _play_tick(copy._play_tick),
- _last_event_time(copy._last_event_time),
- _last_event_tick(copy._last_event_tick),
- _running_status(copy._running_status)
+ _playPos(copy._playPos),
+ _playTime(copy._playTime),
+ _playTick(copy._playTick),
+ _lastEventTime(copy._lastEventTime),
+ _lastEventTick(copy._lastEventTick),
+ _runningStatus(copy._runningStatus)
{ }
/// Clears all data; used by the constructor for initialization.
void clear() {
- _play_pos = 0;
- _play_time = 0;
- _play_tick = 0;
- _last_event_time = 0;
- _last_event_tick = 0;
- _running_status = 0;
+ _playPos = 0;
+ _playTime = 0;
+ _playTick = 0;
+ _lastEventTime = 0;
+ _lastEventTick = 0;
+ _runningStatus = 0;
}
};
@@ -119,8 +119,8 @@ struct EventInfo {
struct NoteTimer {
byte channel; ///< The MIDI channel on which the note was played
byte note; ///< The note number for the active note
- uint32 time_left; ///< The time, in microseconds, remaining before the note should be turned off
- NoteTimer() : channel(0), note(0), time_left(0) {}
+ uint32 timeLeft; ///< The time, in microseconds, remaining before the note should be turned off
+ NoteTimer() : channel(0), note(0), timeLeft(0) {}
};
@@ -264,29 +264,29 @@ struct NoteTimer {
*/
class MidiParser {
protected:
- uint16 _active_notes[128]; ///< Each uint16 is a bit mask for channels that have that note on.
- NoteTimer _hanging_notes[32]; ///< Maintains expiration info for up to 32 notes.
+ uint16 _activeNotes[128]; ///< Each uint16 is a bit mask for channels that have that note on.
+ NoteTimer _hangingNotes[32]; ///< Maintains expiration info for up to 32 notes.
///< Used for "Smart Jump" and MIDI formats that do not include explicit Note Off events.
- byte _hanging_notes_count; ///< Count of hanging notes, used to optimize expiration.
+ byte _hangingNotesCount; ///< Count of hanging notes, used to optimize expiration.
MidiDriver_BASE *_driver; ///< The device to which all events will be transmitted.
- uint32 _timer_rate; ///< The time in microseconds between onTimer() calls. Obtained from the MidiDriver.
+ uint32 _timerRate; ///< The time in microseconds between onTimer() calls. Obtained from the MidiDriver.
uint32 _ppqn; ///< Pulses Per Quarter Note. (We refer to "pulses" as "ticks".)
uint32 _tempo; ///< Microseconds per quarter note.
- uint32 _psec_per_tick; ///< Microseconds per tick (_tempo / _ppqn).
+ uint32 _psecPerTick; ///< Microseconds per tick (_tempo / _ppqn).
bool _autoLoop; ///< For lightweight clients that don't provide their own flow control.
bool _smartJump; ///< Support smart expiration of hanging notes when jumping
bool _centerPitchWheelOnUnload; ///< Center the pitch wheels when unloading a song
bool _sendSustainOffOnNotesOff; ///< Send a sustain off on a notes off event, stopping hanging notes
byte *_tracks[120]; ///< Multi-track MIDI formats are supported, up to 120 tracks.
- byte _num_tracks; ///< Count of total tracks for multi-track MIDI formats. 1 for single-track formats.
- byte _active_track; ///< Keeps track of the currently active track, in multi-track formats.
+ byte _numTracks; ///< Count of total tracks for multi-track MIDI formats. 1 for single-track formats.
+ byte _activeTrack; ///< Keeps track of the currently active track, in multi-track formats.
Tracker _position; ///< The current time/position in the active track.
- EventInfo _next_event; ///< The next event to transmit. Events are preparsed
+ EventInfo _nextEvent; ///< The next event to transmit. Events are preparsed
///< so each event is parsed only once; this permits
///< simulated events in certain formats.
- bool _abort_parse; ///< If a jump or other operation interrupts parsing, flag to abort.
+ bool _abortParse; ///< If a jump or other operation interrupts parsing, flag to abort.
protected:
static uint32 readVLQ(byte * &data);
@@ -295,7 +295,7 @@ protected:
virtual void parseNextEvent(EventInfo &info) = 0;
void activeNote(byte channel, byte note, bool active);
- void hangingNote(byte channel, byte note, uint32 ticks_left, bool recycle = true);
+ void hangingNote(byte channel, byte note, uint32 ticksLeft, bool recycle = true);
void hangAllActiveNotes();
virtual void sendToDriver(uint32 b);
@@ -377,18 +377,18 @@ public:
virtual void property(int prop, int value);
void setMidiDriver(MidiDriver_BASE *driver) { _driver = driver; }
- void setTimerRate(uint32 rate) { _timer_rate = rate; }
+ void setTimerRate(uint32 rate) { _timerRate = rate; }
void setTempo(uint32 tempo);
void onTimer();
- bool isPlaying() const { return (_position._play_pos != 0); }
+ bool isPlaying() const { return (_position._playPos != 0); }
void stopPlaying();
bool setTrack(int track);
bool jumpToTick(uint32 tick, bool fireEvents = false, bool stopNotes = true, bool dontSendNoteOn = false);
uint32 getPPQN() { return _ppqn; }
- virtual uint32 getTick() { return _position._play_tick; }
+ virtual uint32 getTick() { return _position._playTick; }
static void defaultXMidiCallback(byte eventData, void *refCon);
diff --git a/audio/midiparser_smf.cpp b/audio/midiparser_smf.cpp
index e883471b54..4b0913cbfe 100644
--- a/audio/midiparser_smf.cpp
+++ b/audio/midiparser_smf.cpp
@@ -45,8 +45,8 @@ public:
};
-static const byte command_lengths[8] = { 3, 3, 3, 3, 2, 2, 3, 0 };
-static const byte special_lengths[16] = { 0, 2, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 };
+static const byte commandLengths[8] = { 3, 3, 3, 3, 2, 2, 3, 0 };
+static const byte specialLengths[16] = { 0, 2, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 };
MidiParser_SMF::~MidiParser_SMF() {
free(_buffer);
@@ -62,8 +62,8 @@ void MidiParser_SMF::property(int prop, int value) {
}
void MidiParser_SMF::parseNextEvent(EventInfo &info) {
- info.start = _position._play_pos;
- info.delta = readVLQ(_position._play_pos);
+ info.start = _position._playPos;
+ info.delta = readVLQ(_position._playPos);
// Process the next info. If mpMalformedPitchBends
// was set, we must skip over any pitch bend events
@@ -71,19 +71,19 @@ void MidiParser_SMF::parseNextEvent(EventInfo &info) {
// real pitch bend events, they're just two-byte
// prefixes before the real info.
do {
- if ((_position._play_pos[0] & 0xF0) >= 0x80)
- info.event = *(_position._play_pos++);
+ if ((_position._playPos[0] & 0xF0) >= 0x80)
+ info.event = *(_position._playPos++);
else
- info.event = _position._running_status;
- } while (_malformedPitchBends && (info.event & 0xF0) == 0xE0 && _position._play_pos++);
+ info.event = _position._runningStatus;
+ } while (_malformedPitchBends && (info.event & 0xF0) == 0xE0 && _position._playPos++);
if (info.event < 0x80)
return;
- _position._running_status = info.event;
+ _position._runningStatus = info.event;
switch (info.command()) {
case 0x9: // Note On
- info.basic.param1 = *(_position._play_pos++);
- info.basic.param2 = *(_position._play_pos++);
+ info.basic.param1 = *(_position._playPos++);
+ info.basic.param2 = *(_position._playPos++);
if (info.basic.param2 == 0)
info.event = info.channel() | 0x80;
info.length = 0;
@@ -91,7 +91,7 @@ void MidiParser_SMF::parseNextEvent(EventInfo &info) {
case 0xC:
case 0xD:
- info.basic.param1 = *(_position._play_pos++);
+ info.basic.param1 = *(_position._playPos++);
info.basic.param2 = 0;
break;
@@ -99,20 +99,20 @@ void MidiParser_SMF::parseNextEvent(EventInfo &info) {
case 0xA:
case 0xB:
case 0xE:
- info.basic.param1 = *(_position._play_pos++);
- info.basic.param2 = *(_position._play_pos++);
+ info.basic.param1 = *(_position._playPos++);
+ info.basic.param2 = *(_position._playPos++);
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._play_pos++);
- info.basic.param2 = *(_position._play_pos++);
+ info.basic.param1 = *(_position._playPos++);
+ info.basic.param2 = *(_position._playPos++);
break;
case 0x3: // Song Select
- info.basic.param1 = *(_position._play_pos++);
+ info.basic.param1 = *(_position._playPos++);
info.basic.param2 = 0;
break;
@@ -126,16 +126,16 @@ void MidiParser_SMF::parseNextEvent(EventInfo &info) {
break;
case 0x0: // SysEx
- info.length = readVLQ(_position._play_pos);
- info.ext.data = _position._play_pos;
- _position._play_pos += info.length;
+ info.length = readVLQ(_position._playPos);
+ info.ext.data = _position._playPos;
+ _position._playPos += info.length;
break;
case 0xF: // META event
- info.ext.type = *(_position._play_pos++);
- info.length = readVLQ(_position._play_pos);
- info.ext.data = _position._play_pos;
- _position._play_pos += info.length;
+ info.ext.type = *(_position._playPos++);
+ info.length = readVLQ(_position._playPos);
+ info.ext.data = _position._playPos;
+ _position._playPos += info.length;
break;
default:
@@ -146,8 +146,8 @@ void MidiParser_SMF::parseNextEvent(EventInfo &info) {
bool MidiParser_SMF::loadMusic(byte *data, uint32 size) {
uint32 len;
- byte midi_type;
- uint32 total_size;
+ byte midiType;
+ uint32 totalSize;
bool isGMF;
unloadMusic();
@@ -171,10 +171,10 @@ bool MidiParser_SMF::loadMusic(byte *data, uint32 size) {
// Verify that this MIDI either is a Type 2
// or has only 1 track. We do not support
// multitrack Type 1 files.
- _num_tracks = pos[2] << 8 | pos[3];
- midi_type = pos[1];
- if (midi_type > 2 /*|| (midi_type < 2 && _num_tracks > 1)*/) {
- warning("No support for a Type %d MIDI with %d tracks", (int)midi_type, (int)_num_tracks);
+ _numTracks = pos[2] << 8 | pos[3];
+ midiType = pos[1];
+ if (midiType > 2 /*|| (midiType < 2 && _numTracks > 1)*/) {
+ warning("No support for a Type %d MIDI with %d tracks", (int)midiType, (int)_numTracks);
return false;
}
_ppqn = pos[4] << 8 | pos[5];
@@ -183,8 +183,8 @@ bool MidiParser_SMF::loadMusic(byte *data, uint32 size) {
// Older GMD/MUS file with no header info.
// Assume 1 track, 192 PPQN, and no MTrk headers.
isGMF = true;
- midi_type = 0;
- _num_tracks = 1;
+ midiType = 0;
+ _numTracks = 1;
_ppqn = 192;
pos += 7; // 'GMD\x1' + 3 bytes of useless (translate: unknown) information
} else {
@@ -193,14 +193,14 @@ bool MidiParser_SMF::loadMusic(byte *data, uint32 size) {
}
// Now we identify and store the location for each track.
- if (_num_tracks > ARRAYSIZE(_tracks)) {
- warning("Can only handle %d tracks but was handed %d", (int)ARRAYSIZE(_tracks), (int)_num_tracks);
+ if (_numTracks > ARRAYSIZE(_tracks)) {
+ warning("Can only handle %d tracks but was handed %d", (int)ARRAYSIZE(_tracks), (int)_numTracks);
return false;
}
- total_size = 0;
- int tracks_read = 0;
- while (tracks_read < _num_tracks) {
+ totalSize = 0;
+ int tracksRead = 0;
+ while (tracksRead < _numTracks) {
if (memcmp(pos, "MTrk", 4) && !isGMF) {
warning("Position: %p ('%c')", pos, *pos);
warning("Hit invalid block '%c%c%c%c' while scanning for track locations", pos[0], pos[1], pos[2], pos[3]);
@@ -208,11 +208,11 @@ bool MidiParser_SMF::loadMusic(byte *data, uint32 size) {
}
// If needed, skip the MTrk and length bytes
- _tracks[tracks_read] = pos + (isGMF ? 0 : 8);
+ _tracks[tracksRead] = pos + (isGMF ? 0 : 8);
if (!isGMF) {
pos += 4;
len = read4high(pos);
- total_size += len;
+ totalSize += len;
pos += len;
} else {
// An SMF End of Track meta event must be placed
@@ -222,7 +222,7 @@ bool MidiParser_SMF::loadMusic(byte *data, uint32 size) {
data[size++] = 0x00;
data[size++] = 0x00;
}
- ++tracks_read;
+ ++tracksRead;
}
// If this is a Type 1 MIDI, we need to now compress
@@ -230,13 +230,13 @@ bool MidiParser_SMF::loadMusic(byte *data, uint32 size) {
free(_buffer);
_buffer = 0;
- if (midi_type == 1) {
+ if (midiType == 1) {
// FIXME: Doubled the buffer size to prevent crashes with the
// Inherit the Earth MIDIs. Jamieson630 said something about a
// better fix, but this will have to do in the meantime.
_buffer = (byte *)malloc(size * 2);
compressToType0();
- _num_tracks = 1;
+ _numTracks = 1;
_tracks[0] = _buffer;
}
@@ -253,48 +253,48 @@ void MidiParser_SMF::compressToType0() {
// We assume that _buffer has been allocated
// to sufficient size for this operation.
- // using 0xFF since it could write track_pos[0 to _num_tracks] here
+ // using 0xFF since it could write trackPos[0 to _numTracks] here
// this would cause some illegal writes and could lead to segfaults
// (it crashed for some midis for me, they're not used in any game
// scummvm supports though). *Maybe* handle this in another way,
// it's at the moment only to be sure, that nothing goes wrong.
- byte *track_pos[0xFF];
- byte running_status[0xFF];
- uint32 track_timer[0xFF];
+ byte *trackPos[0xFF];
+ byte runningStatus[0xFF];
+ uint32 trackTimer[0xFF];
uint32 delta;
int i;
- for (i = 0; i < _num_tracks; ++i) {
- running_status[i] = 0;
- track_pos[i] = _tracks[i];
- track_timer[i] = readVLQ(track_pos[i]);
- running_status[i] = 0;
+ for (i = 0; i < _numTracks; ++i) {
+ runningStatus[i] = 0;
+ trackPos[i] = _tracks[i];
+ trackTimer[i] = readVLQ(trackPos[i]);
+ runningStatus[i] = 0;
}
- int best_i;
+ int bestTrack;
uint32 length;
byte *output = _buffer;
byte *pos, *pos2;
byte event;
- uint32 copy_bytes;
+ uint32 copyBytes;
bool write;
- byte active_tracks = (byte)_num_tracks;
+ byte activeTracks = (byte)_numTracks;
- while (active_tracks) {
+ while (activeTracks) {
write = true;
- best_i = 255;
- for (i = 0; i < _num_tracks; ++i) {
- if (track_pos[i] && (best_i == 255 || track_timer[i] < track_timer[best_i]))
- best_i = i;
+ bestTrack = 255;
+ for (i = 0; i < _numTracks; ++i) {
+ if (trackPos[i] && (bestTrack == 255 || trackTimer[i] < trackTimer[bestTrack]))
+ bestTrack = i;
}
- if (best_i == 255) {
+ if (bestTrack == 255) {
warning("Premature end of tracks");
break;
}
// Initial VLQ delta computation
delta = 0;
- length = track_timer[best_i];
+ length = trackTimer[bestTrack];
for (i = 0; length; ++i) {
delta = (delta << 8) | (length & 0x7F) | (i ? 0x80 : 0);
length >>= 7;
@@ -302,55 +302,55 @@ void MidiParser_SMF::compressToType0() {
// Process MIDI event.
bool implicitEvent = false;
- copy_bytes = 0;
- pos = track_pos[best_i];
+ copyBytes = 0;
+ pos = trackPos[bestTrack];
do {
event = *(pos++);
if (event < 0x80) {
- event = running_status[best_i];
+ event = runningStatus[bestTrack];
implicitEvent = true;
}
} while (_malformedPitchBends && (event & 0xF0) == 0xE0 && pos++);
- running_status[best_i] = event;
+ runningStatus[bestTrack] = event;
- if (command_lengths[(event >> 4) - 8] > 0) {
- copy_bytes = command_lengths[(event >> 4) - 8];
- } else if (special_lengths[(event & 0x0F)] > 0) {
- copy_bytes = special_lengths[(event & 0x0F)];
+ if (commandLengths[(event >> 4) - 8] > 0) {
+ copyBytes = commandLengths[(event >> 4) - 8];
+ } else if (specialLengths[(event & 0x0F)] > 0) {
+ copyBytes = specialLengths[(event & 0x0F)];
} else if (event == 0xF0) {
// SysEx
pos2 = pos;
length = readVLQ(pos);
- copy_bytes = 1 + (pos - pos2) + length;
+ copyBytes = 1 + (pos - pos2) + length;
} else if (event == 0xFF) {
// META
event = *(pos++);
- if (event == 0x2F && active_tracks > 1) {
- track_pos[best_i] = 0;
+ if (event == 0x2F && activeTracks > 1) {
+ trackPos[bestTrack] = 0;
write = false;
} else {
pos2 = pos;
length = readVLQ(pos);
- copy_bytes = 2 + (pos - pos2) + length;
+ copyBytes = 2 + (pos - pos2) + length;
}
if (event == 0x2F)
- --active_tracks;
+ --activeTracks;
} else {
warning("Bad MIDI command %02X", (int)event);
- track_pos[best_i] = 0;
+ trackPos[bestTrack] = 0;
}
// Update all tracks' deltas
if (write) {
- for (i = 0; i < _num_tracks; ++i) {
- if (track_pos[i] && i != best_i)
- track_timer[i] -= track_timer[best_i];
+ for (i = 0; i < _numTracks; ++i) {
+ if (trackPos[i] && i != bestTrack)
+ trackTimer[i] -= trackTimer[bestTrack];
}
}
- if (track_pos[best_i]) {
+ if (trackPos[bestTrack]) {
if (write) {
- track_timer[best_i] = 0;
+ trackTimer[bestTrack] = 0;
// Write VLQ delta
while (delta & 0x80) {
@@ -361,17 +361,17 @@ void MidiParser_SMF::compressToType0() {
// Write MIDI data
if (!implicitEvent)
- ++track_pos[best_i];
- --copy_bytes;
- *output++ = running_status[best_i];
- memcpy(output, track_pos[best_i], copy_bytes);
- output += copy_bytes;
+ ++trackPos[bestTrack];
+ --copyBytes;
+ *output++ = runningStatus[bestTrack];
+ memcpy(output, trackPos[bestTrack], copyBytes);
+ output += copyBytes;
}
// Fetch new VLQ delta for winning track
- track_pos[best_i] += copy_bytes;
- if (active_tracks)
- track_timer[best_i] += readVLQ(track_pos[best_i]);
+ trackPos[bestTrack] += copyBytes;
+ if (activeTracks)
+ trackTimer[bestTrack] += readVLQ(trackPos[bestTrack]);
}
}
diff --git a/audio/midiparser_xmidi.cpp b/audio/midiparser_xmidi.cpp
index 85491faaf8..11690b0214 100644
--- a/audio/midiparser_xmidi.cpp
+++ b/audio/midiparser_xmidi.cpp
@@ -32,9 +32,6 @@
*/
class MidiParser_XMIDI : public MidiParser {
protected:
- NoteTimer _notes_cache[32];
- uint32 _inserted_delta; // Track simulated deltas for note-off events
-
struct Loop {
byte *pos;
byte repeat;
@@ -48,11 +45,10 @@ protected:
protected:
uint32 readVLQ2(byte * &data);
- void resetTracking();
void parseNextEvent(EventInfo &info);
public:
- MidiParser_XMIDI(XMidiCallbackProc proc, void *data) : _inserted_delta(0), _callbackProc(proc), _callbackData(data) {}
+ MidiParser_XMIDI(XMidiCallbackProc proc, void *data) : _callbackProc(proc), _callbackData(data) {}
~MidiParser_XMIDI() { }
bool loadMusic(byte *data, uint32 size);
@@ -69,17 +65,16 @@ uint32 MidiParser_XMIDI::readVLQ2(byte * &pos) {
}
void MidiParser_XMIDI::parseNextEvent(EventInfo &info) {
- info.start = _position._play_pos;
- info.delta = readVLQ2(_position._play_pos) - _inserted_delta;
+ info.start = _position._playPos;
+ info.delta = readVLQ2(_position._playPos);
// Process the next event.
- _inserted_delta = 0;
- info.event = *(_position._play_pos++);
+ info.event = *(_position._playPos++);
switch (info.event >> 4) {
case 0x9: // Note On
- info.basic.param1 = *(_position._play_pos++);
- info.basic.param2 = *(_position._play_pos++);
- info.length = readVLQ(_position._play_pos);
+ info.basic.param1 = *(_position._playPos++);
+ info.basic.param2 = *(_position._playPos++);
+ info.length = readVLQ(_position._playPos);
if (info.basic.param2 == 0) {
info.event = info.channel() | 0x80;
info.length = 0;
@@ -88,20 +83,20 @@ void MidiParser_XMIDI::parseNextEvent(EventInfo &info) {
case 0xC:
case 0xD:
- info.basic.param1 = *(_position._play_pos++);
+ info.basic.param1 = *(_position._playPos++);
info.basic.param2 = 0;
break;
case 0x8:
case 0xA:
case 0xE:
- info.basic.param1 = *(_position._play_pos++);
- info.basic.param2 = *(_position._play_pos++);
+ info.basic.param1 = *(_position._playPos++);
+ info.basic.param2 = *(_position._playPos++);
break;
case 0xB:
- info.basic.param1 = *(_position._play_pos++);
- info.basic.param2 = *(_position._play_pos++);
+ info.basic.param1 = *(_position._playPos++);
+ info.basic.param2 = *(_position._playPos++);
// This isn't a full XMIDI implementation, but it should
// hopefully be "good enough" for most things.
@@ -109,7 +104,7 @@ void MidiParser_XMIDI::parseNextEvent(EventInfo &info) {
switch (info.basic.param1) {
// Simplified XMIDI looping.
case 0x74: { // XMIDI_CONTROLLER_FOR_LOOP
- byte *pos = _position._play_pos;
+ byte *pos = _position._playPos;
if (_loopCount < ARRAYSIZE(_loop) - 1)
_loopCount++;
else
@@ -131,9 +126,9 @@ void MidiParser_XMIDI::parseNextEvent(EventInfo &info) {
if (--_loop[_loopCount].repeat == 0)
_loopCount--;
else
- _position._play_pos = _loop[_loopCount].pos;
+ _position._playPos = _loop[_loopCount].pos;
} else {
- _position._play_pos = _loop[_loopCount].pos;
+ _position._playPos = _loop[_loopCount].pos;
}
}
}
@@ -169,12 +164,12 @@ void MidiParser_XMIDI::parseNextEvent(EventInfo &info) {
case 0xF: // Meta or SysEx event
switch (info.event & 0x0F) {
case 0x2: // Song Position Pointer
- info.basic.param1 = *(_position._play_pos++);
- info.basic.param2 = *(_position._play_pos++);
+ info.basic.param1 = *(_position._playPos++);
+ info.basic.param2 = *(_position._playPos++);
break;
case 0x3: // Song Select
- info.basic.param1 = *(_position._play_pos++);
+ info.basic.param1 = *(_position._playPos++);
info.basic.param2 = 0;
break;
@@ -188,16 +183,16 @@ void MidiParser_XMIDI::parseNextEvent(EventInfo &info) {
break;
case 0x0: // SysEx
- info.length = readVLQ(_position._play_pos);
- info.ext.data = _position._play_pos;
- _position._play_pos += info.length;
+ info.length = readVLQ(_position._playPos);
+ info.ext.data = _position._playPos;
+ _position._playPos += info.length;
break;
case 0xF: // META event
- info.ext.type = *(_position._play_pos++);
- info.length = readVLQ(_position._play_pos);
- info.ext.data = _position._play_pos;
- _position._play_pos += info.length;
+ info.ext.type = *(_position._playPos++);
+ info.length = readVLQ(_position._playPos);
+ info.ext.data = _position._playPos;
+ _position._playPos += info.length;
if (info.ext.type == 0x51 && info.length == 3) {
// Tempo event. We want to make these constant 500,000.
info.ext.data[0] = 0x07;
@@ -216,7 +211,7 @@ bool MidiParser_XMIDI::loadMusic(byte *data, uint32 size) {
uint32 i = 0;
byte *start;
uint32 len;
- uint32 chunk_len;
+ uint32 chunkLen;
char buf[32];
_loopCount = -1;
@@ -235,7 +230,7 @@ bool MidiParser_XMIDI::loadMusic(byte *data, uint32 size) {
if (!memcmp(pos, "XMID", 4)) {
warning("XMIDI doesn't have XDIR");
pos += 4;
- _num_tracks = 1;
+ _numTracks = 1;
} else if (memcmp(pos, "XDIR", 4)) {
// Not an XMIDI that we recognize
warning("Expected 'XDIR' but found '%c%c%c%c'", pos[0], pos[1], pos[2], pos[3]);
@@ -243,7 +238,7 @@ bool MidiParser_XMIDI::loadMusic(byte *data, uint32 size) {
} else {
// Seems Valid
pos += 4;
- _num_tracks = 0;
+ _numTracks = 0;
for (i = 4; i < len; i++) {
// Read 4 bytes of type
@@ -251,34 +246,34 @@ bool MidiParser_XMIDI::loadMusic(byte *data, uint32 size) {
pos += 4;
// Read length of chunk
- chunk_len = read4high(pos);
+ chunkLen = read4high(pos);
// Add eight bytes
i += 8;
if (memcmp(buf, "INFO", 4) == 0) {
// Must be at least 2 bytes long
- if (chunk_len < 2) {
- warning("Invalid chunk length %d for 'INFO' block", (int)chunk_len);
+ if (chunkLen < 2) {
+ warning("Invalid chunk length %d for 'INFO' block", (int)chunkLen);
return false;
}
- _num_tracks = (byte)read2low(pos);
+ _numTracks = (byte)read2low(pos);
- if (chunk_len > 2) {
- warning("Chunk length %d is greater than 2", (int)chunk_len);
- //pos += chunk_len - 2;
+ if (chunkLen > 2) {
+ warning("Chunk length %d is greater than 2", (int)chunkLen);
+ //pos += chunkLen - 2;
}
break;
}
// Must align
- pos += (chunk_len + 1) & ~1;
- i += (chunk_len + 1) & ~1;
+ pos += (chunkLen + 1) & ~1;
+ i += (chunkLen + 1) & ~1;
}
// Didn't get to fill the header
- if (_num_tracks == 0) {
+ if (_numTracks == 0) {
warning("Didn't find a valid track count");
return false;
}
@@ -308,13 +303,13 @@ bool MidiParser_XMIDI::loadMusic(byte *data, uint32 size) {
// Ok it's an XMIDI.
// We're going to identify and store the location for each track.
- if (_num_tracks > ARRAYSIZE(_tracks)) {
- warning("Can only handle %d tracks but was handed %d", (int)ARRAYSIZE(_tracks), (int)_num_tracks);
+ if (_numTracks > ARRAYSIZE(_tracks)) {
+ warning("Can only handle %d tracks but was handed %d", (int)ARRAYSIZE(_tracks), (int)_numTracks);
return false;
}
- int tracks_read = 0;
- while (tracks_read < _num_tracks) {
+ int tracksRead = 0;
+ while (tracksRead < _numTracks) {
if (!memcmp(pos, "FORM", 4)) {
// Skip this plus the 4 bytes after it.
pos += 8;
@@ -330,11 +325,11 @@ bool MidiParser_XMIDI::loadMusic(byte *data, uint32 size) {
pos += (len + 1) & ~1;
} else if (!memcmp(pos, "EVNT", 4)) {
// Ahh! What we're looking for at last.
- _tracks[tracks_read] = pos + 8; // Skip the EVNT and length bytes
+ _tracks[tracksRead] = pos + 8; // Skip the EVNT and length bytes
pos += 4;
len = read4high(pos);
pos += (len + 1) & ~1;
- ++tracks_read;
+ ++tracksRead;
} else {
warning("Hit invalid block '%c%c%c%c' while scanning for track locations", pos[0], pos[1], pos[2], pos[3]);
return false;
@@ -349,7 +344,6 @@ bool MidiParser_XMIDI::loadMusic(byte *data, uint32 size) {
_ppqn = 60;
resetTracking();
setTempo(500000);
- _inserted_delta = 0;
setTrack(0);
return true;
}
@@ -357,11 +351,6 @@ bool MidiParser_XMIDI::loadMusic(byte *data, uint32 size) {
return false;
}
-void MidiParser_XMIDI::resetTracking() {
- MidiParser::resetTracking();
- _inserted_delta = 0;
-}
-
void MidiParser::defaultXMidiCallback(byte eventData, void *data) {
warning("MidiParser: defaultXMidiCallback(%d)", eventData);
}
diff --git a/audio/softsynth/mt32/Part.cpp b/audio/softsynth/mt32/Part.cpp
index c9bd86b54a..75912f38a8 100644
--- a/audio/softsynth/mt32/Part.cpp
+++ b/audio/softsynth/mt32/Part.cpp
@@ -411,7 +411,7 @@ void RhythmPart::noteOn(unsigned int midiKey, unsigned int velocity) {
// According to info from Mok, keyShift does not appear to affect anything on rhythm part on LAPC-I, but may do on MT-32 - needs investigation
synth->printDebug(" Patch: (timbreGroup %u), (timbreNum %u), (keyShift %u), fineTune %u, benderRange %u, assignMode %u, (reverbSwitch %u)", patchTemp->patch.timbreGroup, patchTemp->patch.timbreNum, patchTemp->patch.keyShift, patchTemp->patch.fineTune, patchTemp->patch.benderRange, patchTemp->patch.assignMode, patchTemp->patch.reverbSwitch);
synth->printDebug(" PatchTemp: outputLevel %u, (panpot %u)", patchTemp->outputLevel, patchTemp->panpot);
- synth->printDebug(" RhythmTemp: timbre %u, outputLevel %u, panpot %u, reverbSwitch %u", rhythmTemp[drumNum].timbre, rhythmTemp[drumNum].outputLevel, rhythmTemp[drumNum].panpot, rhythmTemp[drumNum].reverbSwitch);
+ synth->printDebug(" RhythmTemp: timbre %u, outputLevel %u, panpot %u, reverbSwitch %u", rhythmTemp[drumNum].timbre, rhythmTemp[drumNum].outputLevel, rhythmTemp[drumNum].panpot, rhythmTemp[drumNum].reverbSwitch);
#endif
#endif
playPoly(drumCache[drumNum], &rhythmTemp[drumNum], midiKey, key, velocity);
diff --git a/audio/softsynth/mt32/Partial.h b/audio/softsynth/mt32/Partial.h
index 95218c858c..5e250769ec 100644
--- a/audio/softsynth/mt32/Partial.h
+++ b/audio/softsynth/mt32/Partial.h
@@ -37,7 +37,7 @@ private:
const int debugPartialNum; // Only used for debugging
// Number of the sample currently being rendered by generateSamples(), or 0 if no run is in progress
// This is only kept available for debugging purposes.
- unsigned long sampleNum;
+ unsigned long sampleNum;
int ownerPart; // -1 if unassigned
int mixType;
diff --git a/audio/softsynth/mt32/PartialManager.cpp b/audio/softsynth/mt32/PartialManager.cpp
index 42a3eaa179..0a6be826d6 100644
--- a/audio/softsynth/mt32/PartialManager.cpp
+++ b/audio/softsynth/mt32/PartialManager.cpp
@@ -148,7 +148,7 @@ bool PartialManager::abortFirstPolyPreferHeldWhereReserveExceeded(int minPart) {
bool PartialManager::freePartials(unsigned int needed, int partNum) {
// CONFIRMED: Barring bugs, this matches the real LAPC-I according to information from Mok.
- // BUG: There's a bug in the LAPC-I implementation:
+ // BUG: There's a bug in the LAPC-I implementation:
// When allocating for rhythm part, or when allocating for a part that is using fewer partials than it has reserved,
// held and playing polys on the rhythm part can potentially be aborted before releasing polys on the rhythm part.
// This bug isn't present on MT-32.
diff --git a/audio/softsynth/mt32/Synth.cpp b/audio/softsynth/mt32/Synth.cpp
index 0861053b5c..7a1b5c2275 100644
--- a/audio/softsynth/mt32/Synth.cpp
+++ b/audio/softsynth/mt32/Synth.cpp
@@ -1156,7 +1156,7 @@ void Synth::writeMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u le
DT(partial[x].tva.envLevel[0]); \
DT(partial[x].tva.envLevel[1]); \
DT(partial[x].tva.envLevel[2]); \
- DT(partial[x].tva.envLevel[3]);
+ DT(partial[x].tva.envLevel[3]);
DTP(0);
DTP(1);
diff --git a/audio/softsynth/mt32/TVA.cpp b/audio/softsynth/mt32/TVA.cpp
index c3be6db591..f3e3f7bbc7 100644
--- a/audio/softsynth/mt32/TVA.cpp
+++ b/audio/softsynth/mt32/TVA.cpp
@@ -274,7 +274,7 @@ void TVA::nextPhase() {
}
int newTarget;
- int newIncrement;
+ int newIncrement = 0;
int envPointIndex = phase;
if (!allLevelsZeroFromNowOn) {
diff --git a/audio/softsynth/mt32/TVF.cpp b/audio/softsynth/mt32/TVF.cpp
index 58f72e5a9b..80b592ea67 100644
--- a/audio/softsynth/mt32/TVF.cpp
+++ b/audio/softsynth/mt32/TVF.cpp
@@ -64,11 +64,11 @@ static int calcBaseCutoff(const TimbreParam::PartialParam *partialParam, Bit32u
int biasPoint = partialParam->tvf.biasPoint;
if ((biasPoint & 0x40) == 0) {
// biasPoint range here: 0 to 63
- int bias = biasPoint + 33 - key; // bias range here: -75 to 84
+ int bias = biasPoint + 33 - key; // bias range here: -75 to 84
if (bias > 0) {
bias = -bias; // bias range here: -1 to -84
baseCutoff += bias * biasLevelToBiasMult[partialParam->tvf.biasLevel]; // Calculation range: -7140 to 7140
- // baseCutoff range now: -10164 to 10164
+ // baseCutoff range now: -10164 to 10164
}
} else {
// biasPoint range here: 64 to 127
diff --git a/audio/softsynth/mt32/freeverb.cpp b/audio/softsynth/mt32/freeverb.cpp
index de8f2632cb..181b878596 100644
--- a/audio/softsynth/mt32/freeverb.cpp
+++ b/audio/softsynth/mt32/freeverb.cpp
@@ -202,7 +202,7 @@ void revmodel::process(const float *inputL, const float *inputR, float *outputL,
// Calculate output REPLACING anything already there
*outputL = outL*wet1 + outR*wet2;
*outputR = outR*wet1 + outL*wet2;
-
+
inputL++;
inputR++;
outputL++;
diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp
index f94171646a..0ca5bbb059 100644
--- a/backends/events/sdl/sdl-events.cpp
+++ b/backends/events/sdl/sdl-events.cpp
@@ -191,6 +191,8 @@ void SdlEventSource::SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event) {
#endif
if (mod & KMOD_CTRL)
event.kbd.flags |= Common::KBD_CTRL;
+ if (mod & KMOD_META)
+ event.kbd.flags |= Common::KBD_META;
// Sticky flags
if (mod & KMOD_NUM)
diff --git a/backends/events/sdl/sdl-events.h b/backends/events/sdl/sdl-events.h
index 2ba88c702b..ca4835126f 100644
--- a/backends/events/sdl/sdl-events.h
+++ b/backends/events/sdl/sdl-events.h
@@ -116,7 +116,7 @@ protected:
//@}
/**
- * Assigns the mouse coords to the mouse event. Furthermore notify the
+ * Assigns the mouse coords to the mouse event. Furthermore notify the
* graphics manager about the position change.
*/
virtual void processMouseEvent(Common::Event &event, int x, int y);
diff --git a/backends/events/webossdl/webossdl-events.h b/backends/events/webossdl/webossdl-events.h
index 99ed3105f8..1ba5c6fcbf 100644
--- a/backends/events/webossdl/webossdl-events.h
+++ b/backends/events/webossdl/webossdl-events.h
@@ -73,10 +73,10 @@ protected:
// The current mouse position on the screen.
int _curX, _curY;
-
+
// The current screen dimensions
int _screenX, _screenY;
-
+
// The drag distance for linear gestures
int _swipeDistX, _swipeDistY;
@@ -107,7 +107,7 @@ protected:
virtual bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event);
virtual bool handleMouseMotion(SDL_Event &ev, Common::Event &event);
virtual bool pollEvent(Common::Event &event);
-
+
// Utility functions
void calculateDimensions();
};
diff --git a/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp b/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp
index f515343d3c..bd87c9fafd 100644
--- a/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp
+++ b/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp
@@ -479,7 +479,7 @@ void DINGUXSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable)
case OSystem::kFeatureCursorPalette:
_cursorPaletteDisabled = !enable;
blitCursor();
- break;
+ break;
default:
break;
}
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index 67041ae17b..fed02ef22e 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -665,7 +665,7 @@ void OpenGLSdlGraphicsManager::notifyResize(const uint width, const uint height)
void OpenGLSdlGraphicsManager::transformMouseCoordinates(Common::Point &point) {
adjustMousePosition(point.x, point.y);
}
-
+
void OpenGLSdlGraphicsManager::notifyMousePos(Common::Point mouse) {
setMousePosition(mouse.x, mouse.y);
}
diff --git a/backends/midi/coreaudio.cpp b/backends/midi/coreaudio.cpp
index 43c801287d..94262d0d92 100644
--- a/backends/midi/coreaudio.cpp
+++ b/backends/midi/coreaudio.cpp
@@ -172,10 +172,15 @@ int MidiDriver_CORE::open() {
// Load custom soundfont, if specified
if (ConfMan.hasKey("soundfont")) {
- FSRef fsref;
- FSSpec fsSpec;
const char *soundfont = ConfMan.get("soundfont").c_str();
+ // TODO: We should really check whether the file contains an
+ // actual soundfont...
+
+#if USE_DEPRECATED_COREAUDIO_API
+ // Before 10.5, we need to use kMusicDeviceProperty_SoundBankFSSpec
+ FSRef fsref;
+ FSSpec fsSpec;
err = FSPathMakeRef ((const byte *)soundfont, &fsref, NULL);
if (err == noErr) {
@@ -183,8 +188,6 @@ int MidiDriver_CORE::open() {
}
if (err == noErr) {
- // TODO: We should really check here whether the file contains an
- // actual soundfont...
err = AudioUnitSetProperty (
_synth,
kMusicDeviceProperty_SoundBankFSSpec, kAudioUnitScope_Global,
@@ -192,9 +195,27 @@ int MidiDriver_CORE::open() {
&fsSpec, sizeof(fsSpec)
);
}
+#else
+ // kMusicDeviceProperty_SoundBankFSSpec is present on 10.6+, but broken
+ // kMusicDeviceProperty_SoundBankURL was added in 10.5 as a replacement
+ CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *)soundfont, strlen(soundfont), false);
+
+ if (url) {
+ err = AudioUnitSetProperty (
+ _synth,
+ kMusicDeviceProperty_SoundBankURL, kAudioUnitScope_Global,
+ 0,
+ &url, sizeof(url)
+ );
+
+ CFRelease(url);
+ } else {
+ warning("Failed to allocate CFURLRef from '%s'", soundfont);
+ }
+#endif
if (err != noErr)
- warning("Failed loading custom sound font '%s' (error %ld)\n", soundfont, (long)err);
+ error("Failed loading custom sound font '%s' (error %ld)", soundfont, (long)err);
}
#ifdef COREAUDIO_DISABLE_REVERB
diff --git a/backends/midi/sndio.cpp b/backends/midi/sndio.cpp
index 21c9ea4fec..a065a658e1 100644
--- a/backends/midi/sndio.cpp
+++ b/backends/midi/sndio.cpp
@@ -81,7 +81,7 @@ void MidiDriver_Sndio::send(uint32 b) {
if (!hdl)
return;
- buf[0] = b & 0xff;
+ buf[0] = b & 0xff;
buf[1] = (b >> 8) & 0xff;
buf[2] = (b >> 16) & 0xff;
buf[3] = (b >> 24) & 0xff;
@@ -101,7 +101,7 @@ void MidiDriver_Sndio::send(uint32 b) {
void MidiDriver_Sndio::sysEx(const byte *msg, uint16 length) {
if (!hdl)
return;
-
+
unsigned char buf[266];
assert(length + 2 <= ARRAYSIZE(buf));
diff --git a/backends/mixer/sdl13/sdl13-mixer.cpp b/backends/mixer/sdl13/sdl13-mixer.cpp
index 84777c8bab..24d3434fde 100644
--- a/backends/mixer/sdl13/sdl13-mixer.cpp
+++ b/backends/mixer/sdl13/sdl13-mixer.cpp
@@ -69,13 +69,13 @@ void Sdl13MixerManager::init() {
warning("Could not open audio device: %s", SDL_GetError());
_mixer = new Audio::MixerImpl(g_system, desired.freq);
- assert(_mixer);
+ assert(_mixer);
_mixer->setReady(false);
} else {
debug(1, "Output sample rate: %d Hz", _obtained.freq);
_mixer = new Audio::MixerImpl(g_system, _obtained.freq);
- assert(_mixer);
+ assert(_mixer);
_mixer->setReady(true);
startAudio();
diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h
index 4b13ca4b0f..5f2f40b726 100644
--- a/backends/platform/android/android.h
+++ b/backends/platform/android/android.h
@@ -234,7 +234,7 @@ private:
int _fingersDown;
void clipMouse(Common::Point &p);
- void scaleMouse(Common::Point &p, int x, int y, bool deductDrawRect = true);
+ void scaleMouse(Common::Point &p, int x, int y, bool deductDrawRect = true, bool touchpadMode = false);
void updateEventScale();
void disableCursorPalette();
diff --git a/backends/platform/android/android.mk b/backends/platform/android/android.mk
index 9292a16595..0651fc796e 100644
--- a/backends/platform/android/android.mk
+++ b/backends/platform/android/android.mk
@@ -10,6 +10,7 @@ JAVA_FILES = \
ScummVMApplication.java \
ScummVMActivity.java \
EditableSurfaceView.java \
+ MouseHelper.java \
Unpacker.java
JAVA_FILES_PLUGIN = \
@@ -47,13 +48,7 @@ APKBUILDER = $(ANDROID_SDK)/tools/apkbuilder
JAVAC ?= javac
JAVACFLAGS = -source 1.5 -target 1.5
-# This is a bit silly. I want to compile against the 1.6 android.jar,
-# to make the compiler check that I don't use something that requires
-# a newer Android. However, in order to use android:installLocation,
-# we need to give aapt a version >=8 android.jar - even though the
-# result will work ok on 1.5+.
-ANDROID_JAR = $(ANDROID_SDK)/platforms/android-4/android.jar
-ANDROID_JAR8 = $(ANDROID_SDK)/platforms/android-8/android.jar
+ANDROID_JAR = $(ANDROID_SDK)/platforms/android-14/android.jar
PATH_BUILD = build.tmp
PATH_BUILD_ASSETS = $(PATH_BUILD)/assets
@@ -92,9 +87,9 @@ $(FILE_MANIFEST): $(FILE_MANIFEST_SRC)
@$(MKDIR) -p $(@D)
sed "s/@ANDROID_VERSIONCODE@/$(ANDROID_VERSIONCODE)/" < $< > $@
-$(SRC_GEN): $(FILE_MANIFEST) $(filter %.xml,$(RESOURCES)) $(ANDROID_JAR8)
+$(SRC_GEN): $(FILE_MANIFEST) $(filter %.xml,$(RESOURCES)) $(ANDROID_JAR)
@$(MKDIR) -p $(PATH_GEN_TOP)
- $(AAPT) package -m -J $(PATH_GEN_TOP) -M $< -S $(PATH_RESOURCES) -I $(ANDROID_JAR8)
+ $(AAPT) package -m -J $(PATH_GEN_TOP) -M $< -S $(PATH_RESOURCES) -I $(ANDROID_JAR)
$(PATH_CLASSES_MAIN)/%.class: $(PATH_GEN)/%.java $(SRC_GEN)
@$(MKDIR) -p $(@D)
@@ -127,7 +122,7 @@ $(PATH_STAGE_PREFIX).%/res/drawable/scummvm.png: $(PATH_RESOURCES)/drawable/scum
@$(MKDIR) -p $(@D)
$(CP) $< $@
-$(FILE_RESOURCES_MAIN): $(FILE_MANIFEST) $(RESOURCES) $(ANDROID_JAR8) $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA)
+$(FILE_RESOURCES_MAIN): $(FILE_MANIFEST) $(RESOURCES) $(ANDROID_JAR) $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA)
$(INSTALL) -d $(PATH_BUILD_ASSETS)
$(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(PATH_BUILD_ASSETS)/
work_dir=`pwd`; \
@@ -141,10 +136,10 @@ $(FILE_RESOURCES_MAIN): $(FILE_MANIFEST) $(RESOURCES) $(ANDROID_JAR8) $(DIST_FIL
zip -r ../`basename $$i` *; \
done
@$(RM) -rf $(PATH_BUILD_ASSETS)/tmp
- $(AAPT) package -f -0 zip -M $< -S $(PATH_RESOURCES) -A $(PATH_BUILD_ASSETS) -I $(ANDROID_JAR8) -F $@
+ $(AAPT) package -f -0 zip -M $< -S $(PATH_RESOURCES) -A $(PATH_BUILD_ASSETS) -I $(ANDROID_JAR) -F $@
-$(PATH_BUILD)/%/$(FILE_RESOURCES): $(PATH_BUILD)/%/AndroidManifest.xml $(PATH_STAGE_PREFIX).%/res/values/strings.xml $(PATH_STAGE_PREFIX).%/res/drawable/scummvm.png plugins/lib%.so $(ANDROID_JAR8)
- $(AAPT) package -f -M $< -S $(PATH_STAGE_PREFIX).$*/res -I $(ANDROID_JAR8) -F $@
+$(PATH_BUILD)/%/$(FILE_RESOURCES): $(PATH_BUILD)/%/AndroidManifest.xml $(PATH_STAGE_PREFIX).%/res/values/strings.xml $(PATH_STAGE_PREFIX).%/res/drawable/scummvm.png plugins/lib%.so $(ANDROID_JAR)
+ $(AAPT) package -f -M $< -S $(PATH_STAGE_PREFIX).$*/res -I $(ANDROID_JAR) -F $@
# Package installer won't delete old libscummvm.so on upgrade so
# replace it with a zero size file
diff --git a/backends/platform/android/events.cpp b/backends/platform/android/events.cpp
index 21d2344fa7..db1261e432 100644
--- a/backends/platform/android/events.cpp
+++ b/backends/platform/android/events.cpp
@@ -59,6 +59,11 @@ enum {
JE_DOUBLE_TAP = 6,
JE_MULTI = 7,
JE_BALL = 8,
+ JE_LMB_DOWN = 9,
+ JE_LMB_UP = 10,
+ JE_RMB_DOWN = 11,
+ JE_RMB_UP = 12,
+ JE_MOUSE_MOVE = 13,
JE_QUIT = 0x1000
};
@@ -272,7 +277,7 @@ void OSystem_Android::clipMouse(Common::Point &p) {
}
void OSystem_Android::scaleMouse(Common::Point &p, int x, int y,
- bool deductDrawRect) {
+ bool deductDrawRect, bool touchpadMode) {
const GLESBaseTexture *tex;
if (_show_overlay)
@@ -282,7 +287,7 @@ void OSystem_Android::scaleMouse(Common::Point &p, int x, int y,
const Common::Rect &r = tex->getDrawRect();
- if (_touchpad_mode) {
+ if (touchpadMode) {
x = x * 100 / _touchpad_scale;
y = y * 100 / _touchpad_scale;
}
@@ -327,11 +332,16 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
}
switch (arg2) {
+
+ // special case. we'll only get it's up event
case JKEYCODE_BACK:
e.kbd.keycode = Common::KEYCODE_ESCAPE;
e.kbd.ascii = Common::ASCII_ESCAPE;
lockMutex(_event_queue_lock);
+ e.type = Common::EVENT_KEYDOWN;
+ _event_queue.push(e);
+ e.type = Common::EVENT_KEYUP;
_event_queue.push(e);
unlockMutex(_event_queue_lock);
@@ -554,7 +564,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
}
scaleMouse(e.mouse, arg3 - _touch_pt_scroll.x,
- arg4 - _touch_pt_scroll.y, false);
+ arg4 - _touch_pt_scroll.y, false, true);
e.mouse += _touch_pt_down;
clipMouse(e.mouse);
} else {
@@ -652,7 +662,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
if (_touchpad_mode) {
scaleMouse(e.mouse, arg1 - _touch_pt_dt.x,
- arg2 - _touch_pt_dt.y, false);
+ arg2 - _touch_pt_dt.y, false, true);
e.mouse += _touch_pt_down;
clipMouse(e.mouse);
@@ -757,6 +767,66 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
return;
+ case JE_MOUSE_MOVE:
+ e.type = Common::EVENT_MOUSEMOVE;
+
+ scaleMouse(e.mouse, arg1, arg2);
+ clipMouse(e.mouse);
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
+ case JE_LMB_DOWN:
+ e.type = Common::EVENT_LBUTTONDOWN;
+
+ scaleMouse(e.mouse, arg1, arg2);
+ clipMouse(e.mouse);
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
+ case JE_LMB_UP:
+ e.type = Common::EVENT_LBUTTONUP;
+
+ scaleMouse(e.mouse, arg1, arg2);
+ clipMouse(e.mouse);
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
+ case JE_RMB_DOWN:
+ e.type = Common::EVENT_RBUTTONDOWN;
+
+ scaleMouse(e.mouse, arg1, arg2);
+ clipMouse(e.mouse);
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
+ case JE_RMB_UP:
+ e.type = Common::EVENT_RBUTTONUP;
+
+ scaleMouse(e.mouse, arg1, arg2);
+ clipMouse(e.mouse);
+
+ lockMutex(_event_queue_lock);
+ _event_queue.push(e);
+ unlockMutex(_event_queue_lock);
+
+ return;
+
case JE_QUIT:
e.type = Common::EVENT_QUIT;
diff --git a/backends/platform/android/org/scummvm/scummvm/MouseHelper.java b/backends/platform/android/org/scummvm/scummvm/MouseHelper.java
new file mode 100644
index 0000000000..999815593f
--- /dev/null
+++ b/backends/platform/android/org/scummvm/scummvm/MouseHelper.java
@@ -0,0 +1,129 @@
+package org.scummvm.scummvm;
+
+import android.view.InputDevice;
+import android.view.MotionEvent;
+import android.view.SurfaceView;
+import android.view.View;
+
+/**
+ * Contains helper methods for mouse/hover events that were introduced in Android 4.0.
+ */
+public class MouseHelper {
+ private View.OnHoverListener _listener;
+ private ScummVM _scummvm;
+ private long _rmbGuardTime;
+ private boolean _rmbPressed;
+ private boolean _lmbPressed;
+
+ /**
+ * Class initialization fails when this throws an exception.
+ * Checking hover availability is done on static class initialization for Android 1.6 compatibility.
+ */
+ static {
+ try {
+ Class.forName("android.view.View$OnHoverListener");
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ /**
+ * Calling this forces class initialization
+ */
+ public static void checkHoverAvailable() {}
+
+ public MouseHelper(ScummVM scummvm) {
+ _scummvm = scummvm;
+ _listener = createListener();
+ }
+
+ private View.OnHoverListener createListener() {
+ return new View.OnHoverListener() {
+ @Override
+ public boolean onHover(View view, MotionEvent e) {
+ return onMouseEvent(e, true);
+ }
+ };
+ }
+
+ public void attach(SurfaceView main_surface) {
+ main_surface.setOnHoverListener(_listener);
+ }
+
+ public static boolean isMouse(MotionEvent e) {
+ if (e == null) {
+ return false;
+ }
+
+ InputDevice device = e.getDevice();
+
+ if (device == null) {
+ return false;
+ }
+
+ int sources = device.getSources();
+
+ return ((sources & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) ||
+ ((sources & InputDevice.SOURCE_STYLUS) == InputDevice.SOURCE_STYLUS) ||
+ ((sources & InputDevice.SOURCE_TOUCHPAD) == InputDevice.SOURCE_TOUCHPAD);
+ }
+
+ public boolean onMouseEvent(MotionEvent e, boolean hover) {
+ _scummvm.pushEvent(ScummVMEvents.JE_MOUSE_MOVE, (int)e.getX(), (int)e.getY(), 0, 0, 0);
+
+ int buttonState = e.getButtonState();
+
+ boolean lmbDown = (buttonState & MotionEvent.BUTTON_PRIMARY) == MotionEvent.BUTTON_PRIMARY;
+
+ if (!hover && e.getAction() != MotionEvent.ACTION_UP && buttonState == 0) {
+ // On some device types, ButtonState is 0 even when tapping on the touchpad or using the stylus on the screen etc.
+ lmbDown = true;
+ }
+
+ if (lmbDown) {
+ if (!_lmbPressed) {
+ // left mouse button was pressed just now
+ _scummvm.pushEvent(ScummVMEvents.JE_LMB_DOWN, (int)e.getX(), (int)e.getY(), e.getButtonState(), 0, 0);
+ }
+
+ _lmbPressed = true;
+ } else {
+ if (_lmbPressed) {
+ // left mouse button was released just now
+ _scummvm.pushEvent(ScummVMEvents.JE_LMB_UP, (int)e.getX(), (int)e.getY(), e.getButtonState(), 0, 0);
+ }
+
+ _lmbPressed = false;
+ }
+
+ boolean rmbDown = (buttonState & MotionEvent.BUTTON_SECONDARY) == MotionEvent.BUTTON_SECONDARY;
+ if (rmbDown) {
+ if (!_rmbPressed) {
+ // right mouse button was pressed just now
+ _scummvm.pushEvent(ScummVMEvents.JE_RMB_DOWN, (int)e.getX(), (int)e.getY(), e.getButtonState(), 0, 0);
+ }
+
+ _rmbPressed = true;
+ } else {
+ if (_rmbPressed) {
+ // right mouse button was released just now
+ _scummvm.pushEvent(ScummVMEvents.JE_RMB_UP, (int)e.getX(), (int)e.getY(), e.getButtonState(), 0, 0);
+ _rmbGuardTime = System.currentTimeMillis();
+ }
+
+ _rmbPressed = false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Checks whether right mouse button is pressed or was pressed just previously. This is used to prevent sending
+ * extra back key on right mouse click which is the default behaviour in some platforms.
+ *
+ * @return true if right mouse button is (or was in the last 200ms) pressed
+ */
+ public boolean getRmbGuard() {
+ return _rmbPressed || _rmbGuardTime + 200 > System.currentTimeMillis();
+ }
+}
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
index fbd6513761..34c6df3a3a 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
@@ -18,6 +18,18 @@ import java.io.File;
public class ScummVMActivity extends Activity {
+ /* Establish whether the hover events are available */
+ private static boolean _hoverAvailable;
+
+ static {
+ try {
+ MouseHelper.checkHoverAvailable(); // this throws exception if we're on too old version
+ _hoverAvailable = true;
+ } catch (Throwable t) {
+ _hoverAvailable = false;
+ }
+ }
+
private class MyScummVM extends ScummVM {
private boolean usingSmallScreen() {
// Multiple screen sizes came in with Android 1.6. Have
@@ -94,6 +106,7 @@ public class ScummVMActivity extends Activity {
private MyScummVM _scummvm;
private ScummVMEvents _events;
+ private MouseHelper _mouseHelper;
private Thread _scummvm_thread;
@Override
@@ -151,7 +164,13 @@ public class ScummVMActivity extends Activity {
"--savepath=" + savePath
});
- _events = new ScummVMEvents(this, _scummvm);
+ Log.d(ScummVM.LOG_TAG, "Hover available: " + _hoverAvailable);
+ if (_hoverAvailable) {
+ _mouseHelper = new MouseHelper(_scummvm);
+ _mouseHelper.attach(main_surface);
+ }
+
+ _events = new ScummVMEvents(this, _scummvm, _mouseHelper);
main_surface.setOnKeyListener(_events);
main_surface.setOnTouchListener(_events);
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java b/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java
index 86227b9352..5f51ffac6c 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java
@@ -2,7 +2,6 @@ package org.scummvm.scummvm;
import android.os.Handler;
import android.os.Message;
-import android.util.Log;
import android.content.Context;
import android.view.KeyEvent;
import android.view.KeyCharacterMap;
@@ -27,16 +26,23 @@ public class ScummVMEvents implements
public static final int JE_DOUBLE_TAP = 6;
public static final int JE_MULTI = 7;
public static final int JE_BALL = 8;
+ public static final int JE_LMB_DOWN = 9;
+ public static final int JE_LMB_UP = 10;
+ 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_QUIT = 0x1000;
final protected Context _context;
final protected ScummVM _scummvm;
final protected GestureDetector _gd;
final protected int _longPress;
+ final protected MouseHelper _mouseHelper;
- public ScummVMEvents(Context context, ScummVM scummvm) {
+ public ScummVMEvents(Context context, ScummVM scummvm, MouseHelper mouseHelper) {
_context = context;
_scummvm = scummvm;
+ _mouseHelper = mouseHelper;
_gd = new GestureDetector(context, this);
_gd.setOnDoubleTapListener(this);
@@ -64,7 +70,7 @@ public class ScummVMEvents implements
public void handleMessage(Message msg) {
if (msg.what == MSG_MENU_LONG_PRESS) {
InputMethodManager imm = (InputMethodManager)
- _context.getSystemService(_context.INPUT_METHOD_SERVICE);
+ _context.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null)
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
@@ -73,9 +79,30 @@ public class ScummVMEvents implements
};
// OnKeyListener
+ @Override
final public boolean onKey(View v, int keyCode, KeyEvent e) {
final int action = e.getAction();
+ if (keyCode == 238) {
+ // this (undocumented) event is sent when ACTION_HOVER_ENTER or ACTION_HOVER_EXIT occurs
+ return false;
+ }
+
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ if (action != KeyEvent.ACTION_UP) {
+ // only send event from back button on up event, since down event is sent on right mouse click and
+ // cannot be caught (thus rmb click would send escape key first)
+ return true;
+ }
+
+ if (_mouseHelper != null) {
+ if (_mouseHelper.getRmbGuard()) {
+ // right mouse button was just clicked which sends an extra back button press
+ return true;
+ }
+ }
+ }
+
if (e.isSystem()) {
// filter what we handle
switch (keyCode) {
@@ -160,7 +187,16 @@ public class ScummVMEvents implements
}
// OnTouchListener
+ @Override
final public boolean onTouch(View v, MotionEvent e) {
+ if (_mouseHelper != null) {
+ boolean isMouse = MouseHelper.isMouse(e);
+ if (isMouse) {
+ // mouse button is pressed
+ return _mouseHelper.onMouseEvent(e, false);
+ }
+ }
+
final int action = e.getAction();
// constants from APIv5:
@@ -177,11 +213,13 @@ public class ScummVMEvents implements
}
// OnGestureListener
+ @Override
final public boolean onDown(MotionEvent e) {
_scummvm.pushEvent(JE_DOWN, (int)e.getX(), (int)e.getY(), 0, 0, 0);
return true;
}
+ @Override
final public boolean onFling(MotionEvent e1, MotionEvent e2,
float velocityX, float velocityY) {
//Log.d(ScummVM.LOG_TAG, String.format("onFling: %s -> %s (%.3f %.3f)",
@@ -191,10 +229,12 @@ public class ScummVMEvents implements
return true;
}
+ @Override
final public void onLongPress(MotionEvent e) {
// disabled, interferes with drag&drop
}
+ @Override
final public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
_scummvm.pushEvent(JE_SCROLL, (int)e1.getX(), (int)e1.getY(),
@@ -203,9 +243,11 @@ public class ScummVMEvents implements
return true;
}
+ @Override
final public void onShowPress(MotionEvent e) {
}
+ @Override
final public boolean onSingleTapUp(MotionEvent e) {
_scummvm.pushEvent(JE_TAP, (int)e.getX(), (int)e.getY(),
(int)(e.getEventTime() - e.getDownTime()), 0, 0);
@@ -214,10 +256,12 @@ public class ScummVMEvents implements
}
// OnDoubleTapListener
+ @Override
final public boolean onDoubleTap(MotionEvent e) {
return true;
}
+ @Override
final public boolean onDoubleTapEvent(MotionEvent e) {
_scummvm.pushEvent(JE_DOUBLE_TAP, (int)e.getX(), (int)e.getY(),
e.getAction(), 0, 0);
@@ -225,6 +269,7 @@ public class ScummVMEvents implements
return true;
}
+ @Override
final public boolean onSingleTapConfirmed(MotionEvent e) {
return true;
}
diff --git a/backends/platform/bada/application.cpp b/backends/platform/bada/application.cpp
index ba8e544983..e761649245 100644
--- a/backends/platform/bada/application.cpp
+++ b/backends/platform/bada/application.cpp
@@ -103,7 +103,7 @@ void BadaScummVM::pauseGame(bool pause) {
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/sscanf.cpp b/backends/platform/bada/sscanf.cpp
index b5e5b88cb5..aa846698f6 100644
--- a/backends/platform/bada/sscanf.cpp
+++ b/backends/platform/bada/sscanf.cpp
@@ -56,7 +56,7 @@ bool scanInt(const char **in, va_list *ap, int max) {
bool err = false;
if (end == *in || (max > 0 && (end - *in) > max)) {
- err = true;
+ err = true;
} else {
*arg = (int)n;
*in = end;
diff --git a/backends/platform/iphone/iphone_video.mm b/backends/platform/iphone/iphone_video.mm
index 7877bc6430..0bfae30fc7 100644
--- a/backends/platform/iphone/iphone_video.mm
+++ b/backends/platform/iphone/iphone_video.mm
@@ -161,9 +161,9 @@ const char *iPhone_getDocumentsDir() {
- (id)initWithFrame:(struct CGRect)frame {
self = [super initWithFrame: frame];
- if ([[UIScreen mainScreen] respondsToSelector: NSSelectorFromString(@"scale")]) {
- if ([self respondsToSelector: NSSelectorFromString(@"contentScaleFactor")]) {
- //self.contentScaleFactor = [[UIScreen mainScreen] scale];
+ if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
+ if ([self respondsToSelector:@selector(setContentScaleFactor:)]) {
+ [self setContentScaleFactor:[[UIScreen mainScreen] scale]];
}
}
@@ -268,6 +268,11 @@ const char *iPhone_getDocumentsDir() {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); printOpenGLError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); printOpenGLError();
+ // We use GL_CLAMP_TO_EDGE here to avoid artifacts when linear filtering
+ // is used. If we would not use this for example the cursor in Loom would
+ // have a line/border artifact on the right side of the covered rect.
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); printOpenGLError();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); printOpenGLError();
}
- (void)setGraphicsMode {
@@ -476,7 +481,7 @@ const char *iPhone_getDocumentsDir() {
else if (_videoContext.screenWidth == 640 && _videoContext.screenHeight == 400)
adjustedHeight = 480;
}
-
+
float overlayPortraitRatio;
if (_orientation == UIDeviceOrientationLandscapeLeft || _orientation == UIDeviceOrientationLandscapeRight) {
diff --git a/backends/platform/iphone/osys_video.mm b/backends/platform/iphone/osys_video.mm
index aa1856490f..ebe435cb25 100644
--- a/backends/platform/iphone/osys_video.mm
+++ b/backends/platform/iphone/osys_video.mm
@@ -353,7 +353,7 @@ void OSystem_IPHONE::copyRectToOverlay(const void *buf, int pitch, int x, int y,
}
byte *dst = (byte *)_videoContext->overlayTexture.getBasePtr(x, y);
- do {
+ do {
memcpy(dst, src, w * sizeof(uint16));
src += pitch;
dst += _videoContext->overlayTexture.pitch;
@@ -435,7 +435,7 @@ void OSystem_IPHONE::setCursorPalette(const byte *colors, uint start, uint num)
for (uint i = start; i < start + num; ++i, colors += 3)
_mouseCursorPalette[i] = Graphics::RGBToColor<Graphics::ColorMasks<5551> >(colors[0], colors[1], colors[2]);
-
+
// FIXME: This is just stupid, our client code seems to assume that this
// automatically enables the cursor palette.
_mouseCursorPaletteEnabled = true;
diff --git a/backends/platform/maemo/debian/rules b/backends/platform/maemo/debian/rules
index 43a34399a3..c713403876 100755
--- a/backends/platform/maemo/debian/rules
+++ b/backends/platform/maemo/debian/rules
@@ -47,7 +47,7 @@ install: build
install -m0644 gui/themes/scummclassic.zip gui/themes/scummmodern.zip debian/scummvm/opt/scummvm/share
install -m0644 backends/vkeybd/packs/vkeybd_default.zip debian/scummvm/opt/scummvm/share
# for optified version we can also add engine datafiles
- install -m0644 dists/engine-data/drascula.dat dists/engine-data/hugo.dat dists/engine-data/kyra.dat dists/engine-data/lure.dat dists/engine-data/queen.tbl dists/engine-data/sky.cpt dists/engine-data/teenagent.dat dists/engine-data/toon.dat debian/scummvm/opt/scummvm/share
+ install -m0644 dists/engine-data/drascula.dat dists/engine-data/hugo.dat dists/engine-data/kyra.dat dists/engine-data/lure.dat dists/engine-data/queen.tbl dists/engine-data/sky.cpt dists/engine-data/teenagent.dat dists/engine-data/tony.dat dists/engine-data/toon.dat debian/scummvm/opt/scummvm/share
install -m0644 -d debian/scummvm/usr/share/doc/scummvm
install -m0644 AUTHORS COPYING COPYING.BSD COPYING.FREEFONT COPYING.LGPL COPYRIGHT NEWS README debian/scummvm/usr/share/doc/scummvm
diff --git a/backends/platform/sdl/macosx/macosx.cpp b/backends/platform/sdl/macosx/macosx.cpp
index 639bd980f6..fb76c111f2 100644
--- a/backends/platform/sdl/macosx/macosx.cpp
+++ b/backends/platform/sdl/macosx/macosx.cpp
@@ -156,7 +156,7 @@ Common::String OSystem_MacOSX::getSystemLanguage() const {
}
CFRelease(preferredLocalizations);
}
-
+
}
// Falback to POSIX implementation
return OSystem_POSIX::getSystemLanguage();
diff --git a/backends/platform/sdl/macosx/macosx.h b/backends/platform/sdl/macosx/macosx.h
index 4837e643b3..d9cb28b973 100644
--- a/backends/platform/sdl/macosx/macosx.h
+++ b/backends/platform/sdl/macosx/macosx.h
@@ -32,7 +32,7 @@ public:
virtual bool hasFeature(Feature f);
virtual bool displayLogFile();
-
+
virtual Common::String getSystemLanguage() const;
virtual void initBackend();
diff --git a/backends/platform/sdl/main.cpp b/backends/platform/sdl/main.cpp
deleted file mode 100644
index 040028079d..0000000000
--- a/backends/platform/sdl/main.cpp
+++ /dev/null
@@ -1,66 +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"
-
-// Several SDL based ports use a custom main, and hence do not want to compile
-// of this file. The following "#if" ensures that.
-#if !defined(POSIX) && \
- !defined(WIN32) && \
- !defined(MAEMO) && \
- !defined(__SYMBIAN32__) && \
- !defined(_WIN32_WCE) && \
- !defined(__amigaos4__) && \
- !defined(DINGUX) && \
- !defined(CAANOO) && \
- !defined(LINUXMOTO) && \
- !defined(SAMSUNGTV) && \
- !defined(PLAYSTATION3) && \
- !defined(OPENPANDORA)
-
-#include "backends/platform/sdl/sdl.h"
-#include "backends/plugins/sdl/sdl-provider.h"
-#include "base/main.h"
-
-int main(int argc, char *argv[]) {
-
- // Create our OSystem instance
- g_system = new OSystem_SDL();
- assert(g_system);
-
- // Pre initialize the backend
- ((OSystem_SDL *)g_system)->init();
-
-#ifdef DYNAMIC_MODULES
- PluginManager::instance().addPluginProvider(new SDLPluginProvider());
-#endif
-
- // Invoke the actual ScummVM main entry point:
- int res = scummvm_main(argc, argv);
-
- // Free OSystem
- delete (OSystem_SDL *)g_system;
-
- return res;
-}
-
-#endif
diff --git a/backends/platform/sdl/module.mk b/backends/platform/sdl/module.mk
index 98a8265301..a17a326889 100644
--- a/backends/platform/sdl/module.mk
+++ b/backends/platform/sdl/module.mk
@@ -1,7 +1,6 @@
MODULE := backends/platform/sdl
MODULE_OBJS := \
- main.o \
sdl.o
ifdef POSIX
diff --git a/backends/taskbar/win32/mingw-compat.h b/backends/taskbar/win32/mingw-compat.h
index 55105407c6..f6151936f1 100644
--- a/backends/taskbar/win32/mingw-compat.h
+++ b/backends/taskbar/win32/mingw-compat.h
@@ -70,7 +70,7 @@ DECLARE_INTERFACE_(IPropertyStore, IUnknown) {
STDMETHOD (GetValue) (REFPROPERTYKEY key, PROPVARIANT *pv) PURE;
STDMETHOD (SetValue) (REFPROPERTYKEY key, REFPROPVARIANT propvar) PURE;
STDMETHOD (Commit) (void) PURE;
-
+
private:
~IPropertyStore();
};
@@ -137,7 +137,7 @@ DECLARE_INTERFACE_(ITaskbarList3, IUnknown) {
STDMETHOD (SetOverlayIcon) (THIS_ HWND hwnd, HICON hIcon, LPCWSTR pszDescription) PURE;
STDMETHOD (SetThumbnailTooltip) (THIS_ HWND hwnd, LPCWSTR pszTip) PURE;
STDMETHOD (SetThumbnailClip) (THIS_ HWND hwnd, RECT *prcClip) PURE;
-
+
private:
~ITaskbarList3();
};
diff --git a/backends/timer/bada/timer.cpp b/backends/timer/bada/timer.cpp
index b7daf02b49..e41ecd4864 100644
--- a/backends/timer/bada/timer.cpp
+++ b/backends/timer/bada/timer.cpp
@@ -49,7 +49,7 @@ bool TimerSlot::OnStart() {
AppLog("failed to start timer");
return false;
}
-
+
AppLog("started timer %d", _interval);
return true;
}
@@ -57,7 +57,7 @@ bool TimerSlot::OnStart() {
void TimerSlot::OnStop() {
AppLog("timer stopped");
if (_timer) {
- _timer->Cancel();
+ _timer->Cancel();
delete _timer;
_timer = NULL;
}
diff --git a/backends/timer/bada/timer.h b/backends/timer/bada/timer.h
index f6ae4517c7..826064d7ff 100644
--- a/backends/timer/bada/timer.h
+++ b/backends/timer/bada/timer.h
@@ -51,7 +51,7 @@ public:
BadaTimerManager();
~BadaTimerManager();
- bool installTimerProc(TimerProc proc, int32 interval, void *refCon,
+ bool installTimerProc(TimerProc proc, int32 interval, void *refCon,
const Common::String &id);
void removeTimerProc(TimerProc proc);
diff --git a/backends/timer/default/default-timer.cpp b/backends/timer/default/default-timer.cpp
index 9cd803f148..9f56d58b12 100644
--- a/backends/timer/default/default-timer.cpp
+++ b/backends/timer/default/default-timer.cpp
@@ -156,7 +156,7 @@ void DefaultTimerManager::removeTimerProc(TimerProc callback) {
}
// We need to remove all names referencing the timer proc here.
- //
+ //
// Else we run into troubles, when the client code removes and readds timer
// callbacks.
//
diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 5ad23313dc..44007c494a 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -238,7 +238,7 @@ void registerDefaults() {
ConfMan.registerDefault("record_time_file_name", "record.time");
ConfMan.registerDefault("gui_saveload_chooser", "grid");
-
+ ConfMan.registerDefault("gui_saveload_last_pos", "0");
}
//
diff --git a/base/main.cpp b/base/main.cpp
index 25e1b881cc..355a65f883 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -57,6 +57,7 @@
#include "graphics/cursorman.h"
#include "graphics/fontman.h"
+#include "graphics/yuv_to_rgb.h"
#ifdef USE_FREETYPE2
#include "graphics/fonts/ttf.h"
#endif
@@ -511,6 +512,8 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
#ifdef USE_FREETYPE2
Graphics::shutdownTTF();
#endif
+ EngineManager::destroy();
+ Graphics::YUVToRGBManager::destroy();
return 0;
}
diff --git a/common/array.h b/common/array.h
index a2c3023362..ca89523a0b 100644
--- a/common/array.h
+++ b/common/array.h
@@ -332,7 +332,7 @@ protected:
// Copy a part of the new data to the position inside the
// initialized space.
copy(first, first + (_size - idx), pos);
-
+
// Copy a part of the new data to the position inside the
// uninitialized space.
uninitialized_copy(first + (_size - idx), last, _storage + _size);
diff --git a/common/coroutines.cpp b/common/coroutines.cpp
index 7209ea3024..849b881177 100644
--- a/common/coroutines.cpp
+++ b/common/coroutines.cpp
@@ -717,12 +717,12 @@ void CoroutineScheduler::pulseEvent(uint32 pidEvent) {
EVENT *evt = getEvent(pidEvent);
if (!evt)
return;
-
+
// Set the event as signalled and pulsing
evt->signalled = true;
evt->pulsing = true;
- // If there's an active process, and it's not the first in the queue, then reschedule all
+ // If there's an active process, and it's not the first in the queue, then reschedule all
// the other prcoesses in the queue to run again this frame
if (pCurrent && pCurrent != active->pNext)
rescheduleAll();
diff --git a/common/cosinetables.cpp b/common/cosinetables.cpp
index bf158e904f..fe8f454e14 100644
--- a/common/cosinetables.cpp
+++ b/common/cosinetables.cpp
@@ -36,7 +36,7 @@ CosineTable::CosineTable(int bitPrecision) {
double freq = 2 * M_PI / m;
_table = new float[m];
- // Table contains cos(2*pi*x/n) for 0<=x<=n/4,
+ // Table contains cos(2*pi*x/n) for 0<=x<=n/4,
// followed by its reverse
for (int i = 0; i <= m / 4; i++)
_table[i] = cos(i * freq);
diff --git a/common/gui_options.h b/common/gui_options.h
index 9da19b1c3e..447fff43ed 100644
--- a/common/gui_options.h
+++ b/common/gui_options.h
@@ -55,7 +55,7 @@
#define GUIO_RENDERPC9821 "\037"
#define GUIO_RENDERPC9801 "\040"
-// Special GUIO flags for the AdvancedDetector's caching of game specific
+// Special GUIO flags for the AdvancedDetector's caching of game specific
// options.
#define GUIO_GAMEOPTIONS1 "\041"
#define GUIO_GAMEOPTIONS2 "\042"
diff --git a/common/keyboard.h b/common/keyboard.h
index f9e94e6656..3262a15c3f 100644
--- a/common/keyboard.h
+++ b/common/keyboard.h
@@ -224,12 +224,13 @@ enum {
KBD_CTRL = 1 << 0,
KBD_ALT = 1 << 1,
KBD_SHIFT = 1 << 2,
- KBD_NON_STICKY = (KBD_CTRL|KBD_ALT|KBD_SHIFT),
+ KBD_META = 1 << 3,
+ KBD_NON_STICKY = (KBD_CTRL|KBD_ALT|KBD_SHIFT|KBD_META),
// Sticky modifier flags
- KBD_NUM = 1 << 3,
- KBD_CAPS = 1 << 4,
- KBD_SCRL = 1 << 5,
+ KBD_NUM = 1 << 4,
+ KBD_CAPS = 1 << 5,
+ KBD_SCRL = 1 << 6,
KBD_STICKY = (KBD_NUM|KBD_CAPS|KBD_SCRL)
};
diff --git a/common/macresman.cpp b/common/macresman.cpp
index 14bdfa7080..f2f020c6de 100644
--- a/common/macresman.cpp
+++ b/common/macresman.cpp
@@ -124,7 +124,7 @@ bool MacResManager::open(String filename) {
File *file = new File();
// First, let's try to see if the Mac converted name exists
- if (file->open("._" + filename) && loadFromAppleDouble(*file)) {
+ if (file->open(constructAppleDoubleName(filename)) && loadFromAppleDouble(*file)) {
_baseFileName = filename;
return true;
}
@@ -185,7 +185,7 @@ bool MacResManager::open(FSNode path, String filename) {
#endif
// First, let's try to see if the Mac converted name exists
- FSNode fsNode = path.getChild("._" + filename);
+ FSNode fsNode = path.getChild(constructAppleDoubleName(filename));
if (fsNode.exists() && !fsNode.isDirectory()) {
SeekableReadStream *stream = fsNode.createReadStream();
if (loadFromAppleDouble(*stream)) {
@@ -253,7 +253,7 @@ bool MacResManager::exists(const String &filename) {
return true;
// Check if we have an AppleDouble file
- if (tempFile.open("._" + filename) && tempFile.readUint32BE() == 0x00051607)
+ if (tempFile.open(constructAppleDoubleName(filename)) && tempFile.readUint32BE() == 0x00051607)
return true;
return false;
@@ -574,4 +574,20 @@ void MacResManager::readMap() {
}
}
+Common::String MacResManager::constructAppleDoubleName(Common::String name) {
+ // Insert "._" before the last portion of a path name
+ for (int i = name.size() - 1; i >= 0; i--) {
+ if (i == 0) {
+ name.insertChar('_', 0);
+ name.insertChar('.', 0);
+ } else if (name[i] == '/') {
+ name.insertChar('_', i + 1);
+ name.insertChar('.', i + 1);
+ break;
+ }
+ }
+
+ return name;
+}
+
} // End of namespace Common
diff --git a/common/macresman.h b/common/macresman.h
index 6820106925..ed74da9cc6 100644
--- a/common/macresman.h
+++ b/common/macresman.h
@@ -25,6 +25,7 @@
* Macintosh resource fork manager used in engines:
* - groovie
* - mohawk
+ * - pegasus
* - sci
* - scumm
*/
@@ -175,6 +176,8 @@ private:
bool loadFromMacBinary(SeekableReadStream &stream);
bool loadFromAppleDouble(SeekableReadStream &stream);
+ static Common::String constructAppleDoubleName(Common::String name);
+
enum {
kResForkNone = 0,
kResForkRaw,
diff --git a/common/memstream.h b/common/memstream.h
index 69fe6ec18e..497a178ab9 100644
--- a/common/memstream.h
+++ b/common/memstream.h
@@ -92,13 +92,17 @@ private:
byte *_ptr;
const uint32 _bufSize;
uint32 _pos;
+ bool _err;
public:
- MemoryWriteStream(byte *buf, uint32 len) : _ptr(buf), _bufSize(len), _pos(0) {}
+ MemoryWriteStream(byte *buf, uint32 len) : _ptr(buf), _bufSize(len), _pos(0), _err(false) {}
uint32 write(const void *dataPtr, uint32 dataSize) {
// Write at most as many bytes as are still available...
- if (dataSize > _bufSize - _pos)
+ if (dataSize > _bufSize - _pos) {
dataSize = _bufSize - _pos;
+ // We couldn't write all the data => set error indicator
+ _err = true;
+ }
memcpy(_ptr, dataPtr, dataSize);
_ptr += dataSize;
_pos += dataSize;
@@ -107,6 +111,9 @@ public:
uint32 pos() const { return _pos; }
uint32 size() const { return _bufSize; }
+
+ virtual bool err() const { return _err; }
+ virtual void clearErr() { _err = false; }
};
/**
diff --git a/common/quicktime.h b/common/quicktime.h
index 08ca35ad51..641718e13a 100644
--- a/common/quicktime.h
+++ b/common/quicktime.h
@@ -168,7 +168,7 @@ protected:
Rational _scaleFactorX;
Rational _scaleFactorY;
Array<Track *> _tracks;
-
+
void init();
private:
diff --git a/common/rational.h b/common/rational.h
index 45aa6a7a20..8270d2194e 100644
--- a/common/rational.h
+++ b/common/rational.h
@@ -80,6 +80,9 @@ public:
double toDouble() const;
frac_t toFrac() const;
+ int getNumerator() const { return _num; }
+ int getDenominator() const { return _denom; }
+
void debugPrint(int debuglevel = 0, const char *caption = "Rational:") const;
private:
diff --git a/common/rect.h b/common/rect.h
index 2bd3affafe..8d1243f7e4 100644
--- a/common/rect.h
+++ b/common/rect.h
@@ -170,6 +170,20 @@ struct Rect {
}
/**
+ * Find the intersecting rectangle between this rectangle and the given rectangle
+ *
+ * @param r the intersecting rectangle
+ *
+ * @return the intersection of the rectangles or an empty rectangle if not intersecting
+ */
+ Rect findIntersectingRect(const Rect &r) const {
+ if (!intersects(r))
+ return Rect();
+
+ return Rect(MAX(r.left, left), MAX(r.top, top), MIN(r.right, right), MIN(r.bottom, bottom));
+ }
+
+ /**
* Extend this rectangle so that it contains r
*
* @param r the rectangle to extend by
diff --git a/common/savefile.h b/common/savefile.h
index da787289ee..19536da54f 100644
--- a/common/savefile.h
+++ b/common/savefile.h
@@ -109,12 +109,12 @@ public:
*
* Saved games are compressed by default, and engines are expected to
* always write compressed saves.
- *
+ *
* A notable exception is if uncompressed files are needed for
* compatibility with games not supported by ScummVM, such as character
* exports from the Quest for Glory series. QfG5 is a 3D game and won't be
* supported by ScummVM.
- *
+ *
* @param name the name of the savefile
* @param compress toggles whether to compress the resulting save file
* (default) or not.
diff --git a/common/sinetables.cpp b/common/sinetables.cpp
index a4467383cc..a6ec99469d 100644
--- a/common/sinetables.cpp
+++ b/common/sinetables.cpp
@@ -36,7 +36,7 @@ SineTable::SineTable(int bitPrecision) {
double freq = 2 * M_PI / m;
_table = new float[m];
- // Table contains sin(2*pi*x/n) for 0<=x<=n/4,
+ // 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[i] = sin(i * freq);
diff --git a/common/zlib.h b/common/zlib.h
index b2d321d502..6a840f5fdc 100644
--- a/common/zlib.h
+++ b/common/zlib.h
@@ -114,7 +114,7 @@ bool inflateZlibInstallShield(byte *dst, uint dstLen, const byte *src, uint srcL
* returned).
*
* @param toBeWrapped the stream to be wrapped (if it is in gzip-format)
- * @param knownSize a supplied length of the compressed data (if not available directly)
+ * @param knownSize a supplied length of the compressed data (if not available directly)
*/
SeekableReadStream *wrapCompressedReadStream(SeekableReadStream *toBeWrapped, uint32 knownSize = 0);
diff --git a/configure b/configure
index df2c2107c8..336c79e332 100755
--- a/configure
+++ b/configure
@@ -62,7 +62,7 @@ get_var() {
eval echo \$${1}
}
-# Add an engine: id name build subengines dependencies
+# Add an engine: id name build subengines base-games dependencies
add_engine() {
_engines="${_engines} ${1}"
if test "${3}" = "no" ; then
@@ -72,9 +72,11 @@ add_engine() {
set_var _engine_${1}_build "${3}"
set_var _engine_${1}_build_default "${3}"
set_var _engine_${1}_subengines "${4}"
- set_var _engine_${1}_deps "${5}"
+ set_var _engine_${1}_base "${5}"
+ set_var _engine_${1}_deps "${6}"
for sub in ${4}; do
set_var _engine_${sub}_sub "yes"
+ set_var _engine_${sub}_parent "${1}"
done
}
@@ -94,7 +96,7 @@ _srcdir=`dirname $0`
#
# Default settings
#
-# Default lib behaviour yes/no/auto
+# Default lib behavior yes/no/auto
_vorbis=auto
_tremor=auto
_tremolo=no
@@ -117,7 +119,7 @@ _freetype2=auto
_taskbar=yes
_updates=no
_libunity=auto
-# Default option behaviour yes/no
+# Default option behavior yes/no
_debug_build=auto
_release_build=auto
_optimizations=auto
@@ -509,6 +511,11 @@ get_engine_dependencies() {
get_var _engine_$1_deps
}
+# Get the base engine game support description
+get_engine_base() {
+ get_var _engine_$1_base
+}
+
# Ask if this is a subengine
get_engine_sub() {
sub=`get_var _engine_$1_sub`
@@ -518,6 +525,11 @@ get_engine_sub() {
echo $sub
}
+# Get a subengine's parent (undefined for non-subengines)
+get_subengine_parent() {
+ get_var _engine_$1_parent
+}
+
# Enable *all* engines
engine_enable_all() {
for engine in $_engines; do
@@ -545,9 +557,15 @@ engine_enable() {
engine=`echo $eng | sed 's/-/_/g'`
# Filter the parameter for the subengines
- if test "`get_engine_sub ${engine}`" != "no" -a "$opt" != "yes" ; then
- subengine_option_error ${engine}
- return
+ if test "`get_engine_sub ${engine}`" != "no" ; then
+ if test "$opt" != "yes" ; then
+ subengine_option_error ${engine}
+ return
+ fi
+ parent=`get_subengine_parent ${engine}`
+ if test `get_engine_build ${parent}` = "no" ; then
+ set_var _engine_${parent}_build "yes"
+ fi
fi
if test "$opt" = "static" -o "$opt" = "dynamic" -o "$opt" = "yes" ; then
@@ -583,7 +601,7 @@ check_engine_deps() {
unmet_deps=""
# Check whether the engine is enabled
- if test `get_engine_build $1` = yes ; then
+ if test `get_engine_build $1` != "no" ; then
# Collect unmet dependencies
for dep in `get_engine_dependencies $1`; do
if test `get_feature_state $dep` = "no"; then
@@ -642,27 +660,37 @@ prepare_engine_build_strings() {
# Get the string about building an engine
get_engine_build_string() {
+ engine=$1
+ request_status=$2
engine_string=""
engine_build=`get_engine_build $1`
- engine_build_default=`get_engine_build_default $1`
+ engine_build_default=`get_engine_build_default $engine`
show=no
+ # Convert static/dynamic to yes to ease the check of subengines
+ if test $engine_build = no; then
+ subengine_filter=no
+ else
+ subengine_filter=yes
+ fi
+
# Check if the current engine should be shown for the current status
- if test $engine_build = $2 ; then
+ if test $engine_build = $request_status ; then
show=yes
else
# Test for disabled sub-engines
- if test $2 = no ; then
- for subeng in `get_engine_subengines $1` ; do
+ if test $request_status = no ; then
+ for subeng in `get_engine_subengines $engine` ; do
if test `get_engine_build $subeng` = no ; then
- engine_build=no
+ # In this case we to display _disabled_ subengines
+ subengine_filter=no
show=yes
fi
done
fi
# Test for enabled wip sub-engines
- if test $2 = wip ; then
- for subeng in `get_engine_subengines $1` ; do
+ if test $request_status = wip ; then
+ for subeng in `get_engine_subengines $engine` ; do
if test `get_engine_build $subeng` != no -a `get_engine_build_default $subeng` = no ; then
show=yes
fi
@@ -670,85 +698,82 @@ get_engine_build_string() {
fi
fi
- # Convert static/dynamic to yes to ease the check of subengines
- if test $engine_build != no ; then
- engine_build=yes
- fi
# Check if it is a wip engine
- if test "$2" = "wip" -a "$engine_build" != "no" -a "$engine_build_default" = no; then
+ if test "$request_status" = "wip" -a "$engine_build" != "no" -a "$engine_build_default" = no; then
show=yes
fi
# The engine should be shown, build the string
if test $show = yes ; then
- build_string_func=get_${1}_build_string
- if ( type $build_string_func | grep function ) 2> /dev/null > /dev/null ; then
- engine_string=`$build_string_func $1 $engine_build $2`
- else
- engine_string=`get_subengines_build_string $1 $engine_build "" $2`
- fi
-
- engine_string="`get_engine_name $1` $engine_string"
+ engine_string=`get_subengines_build_string $engine $subengine_filter $request_status`
+ engine_string="`get_engine_name $engine` $engine_string"
fi
- echo $engine_string
+ echo "$engine_string"
}
# Get the string about building subengines
get_subengines_build_string() {
- all=yes
parent_engine=$1
- subengine_string=$3
- parent_status=$4
+ subengine_filter=$2
+ request_status=$3
parent_engine_build_default=`get_engine_build_default $parent_engine`
+ subengine_string=""
- for subeng in `get_engine_subengines $parent_engine` ; do
- subengine_build=`get_engine_build $subeng`
- subengine_build_default=`get_engine_build_default $subeng`
- if test \( $subengine_build = $2 -a "$parent_status" != wip \) -o \( "$parent_status" = wip -a $subengine_build != no -a "$subengine_build_default" = no \) ; then
- subengine_string="$subengine_string [`get_engine_name $subeng`]"
- else
- all=no
- fi
+ # If the base engine isn't built at all, no need to list subengines
+ # in any of the possible categories.
+ if test `get_engine_build $parent_engine` = no; then
+ return
+ fi
- # handle engines that are on by default and have a single subengine that is off by default
- if test "$parent_status" = wip ; then
- if test $parent_engine_build_default = yes -a subengine ; then
- all=no
- fi
+ all=yes
+ # If there are no subengines, never display "[all games]" (for brevity).
+ if test -z "`get_engine_subengines $parent_engine`"; then
+ all=no
+ fi
+ # If the base engine does not fit the category we're displaying here
+ # (WIP or Skipped), we should never show "[all games]"
+ if test "$request_status" = wip; then
+ if test $parent_engine_build_default = yes; then
+ all=no
fi
+ fi
+ if test "$request_status" = no; then
+ # If we're here, the parent engine is built, so no need to check that.
+ all=no
+ fi
- done
- if test $2 != no ; then
- if test -n "$subengine_string" ; then
- if test $all = yes ; then
- subengine_string="[all games]"
- fi
- fi
+ # In the static/dynamic categories, also display the engine's base games.
+ if test -n "`get_engine_subengines $parent_engine`" -a $request_status != no -a $request_status != wip; then
+ subengine_string="[`get_engine_base $parent_engine`]"
fi
- echo $subengine_string
-}
+ for subeng in `get_engine_subengines $parent_engine` ; do
+ subengine_build=`get_engine_build $subeng`
+ subengine_build_default=`get_engine_build_default $subeng`
-# Engine specific build strings
-get_scumm_build_string() {
- if test `get_engine_build $1` != no ; then
- if test $2 != no -a "$3" != wip ; then
- base="[v0-v6 games]"
+ # Display this subengine if it matches the filter, unless it is
+ # a stable subengine in the WIP request.
+ if test $subengine_build = $subengine_filter -a \! \( "$request_status" = wip -a "$subengine_build_default" = yes \) ; then
+ s="[`get_engine_name $subeng`]"
+ if test -n "$subengine_string"; then
+ subengine_string="$subengine_string $s"
+ else
+ subengine_string="$s"
+ fi
+ else
+ all=no
fi
- get_subengines_build_string $1 $2 "$base" $3
- fi
-}
+ done
-get_saga_build_string() {
- if test `get_engine_build $1` != no ; then
- if test $2 != no -a "$3" != wip; then
- base="[ITE]"
- fi
- get_subengines_build_string $1 $2 "$base" $3
+ # Summarize the full list, where applicable
+ if test $all = yes ; then
+ subengine_string="[all games]"
fi
+
+ echo "$subengine_string"
}
#
@@ -2500,10 +2525,13 @@ if test -n "$_host"; then
# Use -O3 on the OpenPandora for non-debug builds.
_optimization_level=-O3
fi
+ define_in_config_if_yes yes 'USE_ARM_NEON_ASPECT_CORRECTOR'
CXXFLAGS="$CXXFLAGS -march=armv7-a"
CXXFLAGS="$CXXFLAGS -mtune=cortex-a8"
+ CXXFLAGS="$CXXFLAGS -mfloat-abi=softfp"
CXXFLAGS="$CXXFLAGS -mfpu=neon"
- ASFLAGS="$ASFLAGS -mfloat-abi=soft"
+ CXXFLAGS="$CXXFLAGS -fsingle-precision-constant"
+ ASFLAGS="$ASFLAGS -mfloat-abi=softfp"
_backend="openpandora"
_build_hq_scalers=yes
_vkeybd=no
@@ -2952,7 +2980,7 @@ PLUGIN_LDFLAGS += -Wl,-T$(srcdir)/backends/plugins/ds/plugin.ld -mthumb-interwo
freebsd*)
_plugin_prefix="lib"
_plugin_suffix=".so"
- CXXFLAGS="$CXXFLAGS -fpic"
+ CXXFLAGS="$CXXFLAGS -fPIC"
_mak_plugins='
PLUGIN_EXTRA_DEPS =
PLUGIN_LDFLAGS += -shared
@@ -2996,7 +3024,7 @@ POST_OBJS_FLAGS := -Wl,-no-whole-archive
linux*)
_plugin_prefix="lib"
_plugin_suffix=".so"
- CXXFLAGS="$CXXFLAGS -fpic"
+ CXXFLAGS="$CXXFLAGS -fPIC"
LIBS="$LIBS -ldl"
_mak_plugins='
PLUGIN_EXTRA_DEPS =
@@ -3956,9 +3984,6 @@ for engine in $_engines; do
isbuilt=STATIC_PLUGIN
fi
fi
-
- # Prepare the information to be shown
- prepare_engine_build_strings $engine
else
# It's a subengine, just say yes or no
if test "`get_engine_build $engine`" = "no" ; then
@@ -3977,6 +4002,14 @@ for engine in $_engines; do
fi
done
+# Prepare the information to be shown
+for engine in $_engines; do
+ if test "`get_engine_sub $engine`" = "no" ; then
+ # It's a main engine
+ prepare_engine_build_strings $engine
+ fi
+done
+
#
# Detection of WIP/unstable engines
#
@@ -4004,28 +4037,28 @@ fi
echo
if test -n "$_engines_built_static" ; then
echo "Engines (builtin):"
- echo $_engines_built_static | sed 's/@/\
+ echo "$_engines_built_static" | sed 's/@/\
/g
s/#/ /g'
fi
if test -n "$_engines_built_dynamic" ; then
echo "Engines (plugins):"
- echo $_engines_built_dynamic | sed 's/@/\
+ echo "$_engines_built_dynamic" | sed 's/@/\
/g
s/#/ /g'
fi
if test -n "$_engines_skipped" ; then
echo "Engines Skipped:"
- echo $_engines_skipped | sed 's/@/\
+ echo "$_engines_skipped" | sed 's/@/\
/g
s/#/ /g'
fi
if test -n "$_engines_built_wip" ; then
echo "WARNING: This ScummVM build contains the following UNSTABLE engines:"
- echo $_engines_built_wip | sed 's/@/\
+ echo "$_engines_built_wip" | sed 's/@/\
/g
s/#/ /g'
fi
diff --git a/devtools/create_project/config.h b/devtools/create_project/config.h
index 20c1391cef..de4703a47d 100644
--- a/devtools/create_project/config.h
+++ b/devtools/create_project/config.h
@@ -28,7 +28,10 @@
#define LIBS_DEFINE "SCUMMVM_LIBS" // Name of the include environment variable
#define REVISION_DEFINE "SCUMMVM_INTERNAL_REVISION"
-//#define ADDITIONAL_LIBRARY ""
-#define NEEDS_RTTI 0
+#define ENABLE_LANGUAGE_EXTENSIONS "" // Comma separated list of projects that need language extensions
+#define DISABLE_EDIT_AND_CONTINUE "tinsel,tony" // Comma separated list of projects that need Edit&Continue to be disabled for co-routine support (the main project is automatically added)
+
+//#define ADDITIONAL_LIBRARY "" // Add a single library to the list of externally linked libraries
+#define NEEDS_RTTI 0 // Enable RTTI globally
#endif // TOOLS_CREATE_PROJECT_CONFIG_H
diff --git a/devtools/create_project/create_project.cpp b/devtools/create_project/create_project.cpp
index 8499fec400..a8e09ff5eb 100644
--- a/devtools/create_project/create_project.cpp
+++ b/devtools/create_project/create_project.cpp
@@ -97,30 +97,6 @@ struct FSNode {
};
typedef std::list<FSNode> FileList;
-
-typedef StringList TokenList;
-
-/**
- * Takes a given input line and creates a list of tokens out of it.
- *
- * A token in this context is separated by whitespaces. A special case
- * are quotation marks though. A string inside quotation marks is treated
- * as single token, even when it contains whitespaces.
- *
- * Thus for example the input:
- * foo bar "1 2 3 4" ScummVM
- * will create a list with the following entries:
- * "foo", "bar", "1 2 3 4", "ScummVM"
- * As you can see the quotation marks will get *removed* too.
- *
- * You can also use this with non-whitespace by passing another separator
- * character (e.g. ',').
- *
- * @param input The text to be tokenized.
- * @param separator The token separator.
- * @return A list of tokens.
- */
-TokenList tokenize(const std::string &input, char separator = ' ');
} // End of anonymous namespace
enum ProjectType {
@@ -526,7 +502,7 @@ int main(int argc, char *argv[]) {
projectWarnings["agos"].push_back("4511");
projectWarnings["dreamweb"].push_back("4355");
-
+
projectWarnings["lure"].push_back("4189");
projectWarnings["lure"].push_back("4355");
@@ -787,6 +763,7 @@ bool parseEngine(const std::string &line, EngineDesc &engine) {
return true;
}
+} // End of anonymous namespace
TokenList tokenize(const std::string &input, char separator) {
TokenList result;
@@ -819,7 +796,6 @@ TokenList tokenize(const std::string &input, char separator) {
return result;
}
-} // End of anonymous namespace
namespace {
const Feature s_features[] = {
diff --git a/devtools/create_project/create_project.h b/devtools/create_project/create_project.h
index b4eda8f8d2..de77793ee7 100644
--- a/devtools/create_project/create_project.h
+++ b/devtools/create_project/create_project.h
@@ -31,6 +31,30 @@
typedef std::list<std::string> StringList;
+typedef StringList TokenList;
+
+/**
+ * Takes a given input line and creates a list of tokens out of it.
+ *
+ * A token in this context is separated by whitespaces. A special case
+ * are quotation marks though. A string inside quotation marks is treated
+ * as single token, even when it contains whitespaces.
+ *
+ * Thus for example the input:
+ * foo bar "1 2 3 4" ScummVM
+ * will create a list with the following entries:
+ * "foo", "bar", "1 2 3 4", "ScummVM"
+ * As you can see the quotation marks will get *removed* too.
+ *
+ * You can also use this with non-whitespace by passing another separator
+ * character (e.g. ',').
+ *
+ * @param input The text to be tokenized.
+ * @param separator The token separator.
+ * @return A list of tokens.
+ */
+TokenList tokenize(const std::string &input, char separator = ' ');
+
/**
* Structure to describe a game engine to be built into ScummVM.
*
diff --git a/devtools/create_project/msbuild.cpp b/devtools/create_project/msbuild.cpp
index c797770955..0f77d91852 100644
--- a/devtools/create_project/msbuild.cpp
+++ b/devtools/create_project/msbuild.cpp
@@ -241,9 +241,11 @@ void MSBuildProvider::outputProjectSettings(std::ofstream &project, const std::s
// 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 && name != "sword25" && name != "scummvm" && name != "grim" && warningsIterator == _projectWarnings.end())
+ if (!setup.devTools && name != setup.projectName && !enableLanguageExtensions && !disableEditAndContinue && warningsIterator == _projectWarnings.end())
return;
std::string warnings = "";
@@ -254,16 +256,17 @@ void MSBuildProvider::outputProjectSettings(std::ofstream &project, const std::s
project << "\t<ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='" << configuration << "|" << (isWin32 ? "Win32" : "x64") << "'\">\n"
"\t\t<ClCompile>\n";
- // Compile configuration
- if (setup.devTools || name == setup.projectName || name == "sword25" || name == "grim") {
+ // Language Extensions
+ if (setup.devTools || name == setup.projectName || enableLanguageExtensions)
project << "\t\t\t<DisableLanguageExtensions>false</DisableLanguageExtensions>\n";
- if (name == setup.projectName && !isRelease)
- project << "\t\t\t<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\n";
- } else {
- if (warningsIterator != _projectWarnings.end())
- project << "\t\t\t<DisableSpecificWarnings>" << warnings << ";%(DisableSpecificWarnings)</DisableSpecificWarnings>\n";
- }
+ // Edit and Continue
+ if ((name == setup.projectName || disableEditAndContinue) && !isRelease)
+ project << "\t\t\t<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\n";
+
+ // Warnings
+ if (warningsIterator != _projectWarnings.end())
+ project << "\t\t\t<DisableSpecificWarnings>" << warnings << ";%(DisableSpecificWarnings)</DisableSpecificWarnings>\n";
project << "\t\t</ClCompile>\n";
diff --git a/devtools/create_project/msvc.cpp b/devtools/create_project/msvc.cpp
index 96eaf643d1..b8d2401af9 100644
--- a/devtools/create_project/msvc.cpp
+++ b/devtools/create_project/msvc.cpp
@@ -33,6 +33,9 @@ namespace CreateProjectTool {
//////////////////////////////////////////////////////////////////////////
MSVCProvider::MSVCProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, const int version)
: ProjectProvider(global_warnings, project_warnings, version) {
+
+ _enableLanguageExtensions = tokenize(ENABLE_LANGUAGE_EXTENSIONS, ',');
+ _disableEditAndContinue = tokenize(DISABLE_EDIT_AND_CONTINUE, ',');
}
void MSVCProvider::createWorkspace(const BuildSetup &setup) {
@@ -75,10 +78,10 @@ void MSVCProvider::createWorkspace(const BuildSetup &setup) {
solution << "Global\n"
"\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n"
"\t\tDebug|Win32 = Debug|Win32\n"
- "\t\tAnalysis|Win32 = Analysis|Win32\n"
+ "\t\tAnalysis|Win32 = Analysis|Win32\n"
"\t\tRelease|Win32 = Release|Win32\n"
"\t\tDebug|x64 = Debug|x64\n"
- "\t\tAnalysis|x64 = Analysis|x64\n"
+ "\t\tAnalysis|x64 = Analysis|x64\n"
"\t\tRelease|x64 = Release|x64\n"
"\tEndGlobalSection\n"
"\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n";
@@ -86,14 +89,14 @@ void MSVCProvider::createWorkspace(const BuildSetup &setup) {
for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) {
solution << "\t\t{" << i->second << "}.Debug|Win32.ActiveCfg = Debug|Win32\n"
"\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 << "}.Analysis|Win32.ActiveCfg = Analysis|Win32\n"
+ "\t\t{" << i->second << "}.Analysis|Win32.Build.0 = Analysis|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 << "}.Analysis|x64.ActiveCfg = Analysis|x64\n"
+ "\t\t{" << i->second << "}.Analysis|x64.Build.0 = Analysis|x64\n"
"\t\t{" << i->second << "}.Release|x64.ActiveCfg = Release|x64\n"
"\t\t{" << i->second << "}.Release|x64.Build.0 = Release|x64\n";
}
@@ -139,7 +142,7 @@ void MSVCProvider::createGlobalProp(const BuildSetup &setup) {
StringList x64EngineDefines = getEngineDefines(setup.engines);
x64Defines.splice(x64Defines.end(), x64EngineDefines);
- // HACK: This definitly should not be here, but otherwise we would not define SDL_BACKEND for x64.
+ // HACK: This definitely should not be here, but otherwise we would not define SDL_BACKEND for x64.
x64Defines.push_back("WIN32");
x64Defines.push_back("SDL_BACKEND");
@@ -168,7 +171,7 @@ std::string MSVCProvider::getPostBuildEvent(bool isWin32, bool createInstaller)
cmdLine += (isWin32) ? "x86" : "x64";
- cmdLine += " %SCUMMVM_LIBS% ";
+ cmdLine += " %" LIBS_DEFINE "% ";
// Specify if installer needs to be built or not
cmdLine += (createInstaller ? "1" : "0");
diff --git a/devtools/create_project/msvc.h b/devtools/create_project/msvc.h
index 0a994667fa..5a854b596a 100644
--- a/devtools/create_project/msvc.h
+++ b/devtools/create_project/msvc.h
@@ -32,6 +32,8 @@ public:
MSVCProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, const int version);
protected:
+ StringList _enableLanguageExtensions;
+ StringList _disableEditAndContinue;
void createWorkspace(const BuildSetup &setup);
diff --git a/devtools/create_project/scripts/postbuild.cmd b/devtools/create_project/scripts/postbuild.cmd
index d78119d058..8b70ec3dd8 100644
--- a/devtools/create_project/scripts/postbuild.cmd
+++ b/devtools/create_project/scripts/postbuild.cmd
@@ -24,8 +24,10 @@ echo Copying data files
echo.
xcopy /F /Y "%~4/lib/%~3/SDL.dll" "%~2" 1>NUL 2>&1
-xcopy /F /Y "%~4/lib/%~3/freetype6.dll" "%~2" 1>NUL 2>&1
+xcopy /F /Y "%~4/lib/%~3/freetype6.dll" "%~2" 1>NUL 2>&1
xcopy /F /Y "%~1/backends/vkeybd/packs/vkeybd_default.zip" "%~2" 1>NUL 2>&1
+xcopy /F /Y "%~1/gui/themes/translations.dat" "%~2" 1>NUL 2>&1
+
if "%~5"=="0" goto done
diff --git a/devtools/create_project/visualstudio.cpp b/devtools/create_project/visualstudio.cpp
index c301e78ad1..de2df96d78 100644
--- a/devtools/create_project/visualstudio.cpp
+++ b/devtools/create_project/visualstudio.cpp
@@ -103,6 +103,9 @@ void VisualStudioProvider::createProjectFile(const std::string &name, const std:
outputConfiguration(project, setup, libraries, "Release", "x64", "64", false);
} else {
+ bool enableLanguageExtensions = find(_enableLanguageExtensions.begin(), _enableLanguageExtensions.end(), name) != _enableLanguageExtensions.end();
+ bool disableEditAndContinue = find(_disableEditAndContinue.begin(), _disableEditAndContinue.end(), name) != _disableEditAndContinue.end();
+
std::string warnings = "";
if (warningsIterator != _projectWarnings.end())
for (StringList::const_iterator i = warningsIterator->second.begin(); i != warningsIterator->second.end(); ++i)
@@ -110,9 +113,8 @@ void VisualStudioProvider::createProjectFile(const std::string &name, const std:
std::string toolConfig;
toolConfig = (!warnings.empty() ? "DisableSpecificWarnings=\"" + warnings + "\"" : "");
- toolConfig += (name == setup.projectName ? "DebugInformationFormat=\"3\" " : "");
- toolConfig += (name == "sword25" ? "DisableLanguageExtensions=\"false\" " : "");
- toolConfig += (name == "grim" ? "DisableLanguageExtensions=\"false\" " : "");
+ toolConfig += (disableEditAndContinue ? "DebugInformationFormat=\"3\" " : "");
+ toolConfig += (enableLanguageExtensions ? "DisableLanguageExtensions=\"false\" " : "");
// Win32
outputConfiguration(setup, project, toolConfig, "Debug", "Win32", "");
diff --git a/devtools/create_project/xcode.cpp b/devtools/create_project/xcode.cpp
index 62dd417d8c..a9b8e7a752 100644
--- a/devtools/create_project/xcode.cpp
+++ b/devtools/create_project/xcode.cpp
@@ -206,7 +206,7 @@ void XCodeProvider::writeFileListToProject(const FileNode &dir, std::ofstream &p
// Create group
std::string name = getLastPathComponent(dir.name);
Object *group = new Object(this, "PBXGroup_" + name , "PBXGroup", "PBXGroup", "", name);
-
+
// List of children
Property children;
children.hasOrder = true;
@@ -225,7 +225,7 @@ void XCodeProvider::writeFileListToProject(const FileNode &dir, std::ofstream &p
ADD_SETTING_ORDER_NOVALUE(children, getHash(id), node->name, order++);
ADD_BUILD_FILE(id, node->name, node->name + " in Sources");
ADD_FILE_REFERENCE(node->name, property);
-
+
// Process child nodes
if (!node->children.empty())
writeFileListToProject(*node, projectFile, indentation + 1, duplicate, objPrefix + node->name + '_', filePrefix + node->name + '/');
diff --git a/devtools/create_teenagent/create_teenagent.cpp b/devtools/create_teenagent/create_teenagent.cpp
index fc2ba4da0e..79c61900f3 100644
--- a/devtools/create_teenagent/create_teenagent.cpp
+++ b/devtools/create_teenagent/create_teenagent.cpp
@@ -32,78 +32,110 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
-#include "md5.h"
+#include "util.h"
+#include "static_tables.h"
-static void print_hex(FILE * f, const uint8 * data, size_t len) {
- for (size_t i = 0; i < len; ++i) {
- fprintf(f, "%02x", data[i]);
- }
-}
-
-static void extract(FILE * fout, FILE *fin, size_t pos, size_t size, const char *what) {
- char buf[0x10000];
- assert(size < sizeof(buf));
+int main(int argc, char *argv[]) {
+ const char *dat_name = "teenagent.dat";
- if (fseek(fin, pos, SEEK_SET) != 0) {
- perror(what);
+ FILE *fout = fopen(dat_name, "wb");
+ if (fout == NULL) {
+ perror("opening output file");
exit(1);
}
- if (fread(buf, size, 1, fin) != 1) {
- perror(what);
+ if (fwrite(cseg, CSEG_SIZE, 1, fout) != 1) {
+ perror("Writing code segment");
exit(1);
}
- if (fwrite(buf, size, 1, fout) != 1) {
- perror(what);
+ if (fwrite(dsegStartBlock, DSEG_STARTBLK_SIZE, 1, fout) != 1) {
+ perror("Writing data segment start block");
exit(1);
}
-}
-int main(int argc, char *argv[]) {
- if (argc < 2) {
- fprintf(stderr, "usage: %s: Teenagnt.exe (unpacked one)\n", argv[0]);
- exit(1);
+ // Write out message string block
+ for (uint i = 0; i < (sizeof(messages)/sizeof(char*)); i++) {
+ if (i == 0) {
+ // Write out reject message pointer block
+ uint16 off = DSEG_STARTBLK_SIZE + (4 * 2);
+ writeUint16LE(fout, off);
+ off += strlen(messages[0]) + 2;
+ writeUint16LE(fout, off);
+ off += strlen(messages[1]) + 2;
+ writeUint16LE(fout, off);
+ off += strlen(messages[2]) + 2;
+ writeUint16LE(fout, off);
+ }
+
+ if (i == 327) {
+ // Write out book color pointer block
+ uint16 off = DSEG_STARTBLK_SIZE + (4 * 2);
+ for (uint k = 0; k < 327; k++)
+ off += strlen(messages[k]) + 2;
+ off += (6 * 2);
+ writeUint16LE(fout, off);
+ off += strlen(messages[327]) + 2;
+ writeUint16LE(fout, off);
+ off += strlen(messages[328]) + 2;
+ writeUint16LE(fout, off);
+ off += strlen(messages[329]) + 2;
+ writeUint16LE(fout, off);
+ off += strlen(messages[330]) + 2;
+ writeUint16LE(fout, off);
+ off += strlen(messages[331]) + 2;
+ writeUint16LE(fout, off);
+ }
+ for (uint j = 0; j < strlen(messages[i]); j++) {
+ if (messages[i][j] == '\n')
+ writeByte(fout, '\0');
+ else
+ writeByte(fout, messages[i][j]);
+ }
+ writeByte(fout, '\0');
+ writeByte(fout, '\0');
}
- const char * fname = argv[1];
- uint8 digest[16];
- if (!md5_file(fname, digest, 0)) {
- fprintf(stderr, "cannot calculate md5 for %s", fname);
+ if (fwrite(dsegEndBlock, DSEG_ENDBLK_SIZE, 1, fout) != 1) {
+ perror("Writing data segment end block");
exit(1);
}
- const uint8 ethalon[16] = {
- 0x51, 0xb6, 0xd6, 0x47, 0x21, 0xf7, 0xc4, 0xb4,
- 0x98, 0xbf, 0xc0, 0xf3, 0x23, 0x01, 0x3e, 0x36,
- };
-
- if (memcmp(digest, ethalon, 16) != 0) {
- fprintf(stderr, "cannot extract data, your md5: ");
- print_hex(stderr, digest, 16);
- fprintf(stderr, ", need md5: ");
- print_hex(stderr, ethalon, 16);
- fprintf(stderr, ", sorry\n");
- exit(1);
- }
- FILE *fin = fopen(fname, "rb");
- if (fin == NULL) {
- perror("opening input file");
- exit(1);
- }
-
- const char * dat_name = "teenagent.dat";
- FILE *fout = fopen(dat_name, "wb");
- if (fout == NULL) {
- perror("opening output file");
- exit(1);
+ // Write out dialog string block
+ static const char nulls[6] = "\0\0\0\0\0";
+ for (uint i = 0; i < (sizeof(dialogs)/sizeof(char**)); i++) {
+ //printf("Writing Dialog #%d\n", i);
+ bool dialogEnd = false;
+ uint j = 0;
+ while (!dialogEnd) {
+ uint nullCount = 0;
+ if (strcmp(dialogs[i][j], NEW_LINE) == 0) {
+ nullCount = 1;
+ } else if (strcmp(dialogs[i][j], DISPLAY_MESSAGE) == 0) {
+ nullCount = 2;
+ } else if (strcmp(dialogs[i][j], CHANGE_CHARACTER) == 0) {
+ nullCount = 3;
+ } else if (strcmp(dialogs[i][j], END_DIALOG) == 0) {
+ nullCount = 4;
+ dialogEnd = true;
+ } else { // Deals with normal dialogue and ANIM_WAIT cases
+ if (fwrite(dialogs[i][j], 1, strlen(dialogs[i][j]), fout) != strlen(dialogs[i][j])) {
+ perror("Writing dialog string");
+ exit(1);
+ }
+ }
+
+ if (nullCount != 0 && nullCount < 5) {
+ if (fwrite(nulls, 1, nullCount, fout) != nullCount) {
+ perror("Writing dialog string nulls");
+ exit(1);
+ }
+ }
+
+ j++;
+ }
}
- //0x0200, 0xb5b0, 0x1c890
- extract(fout, fin, 0x00200, 0xb3b0, "extracting code segment");
- extract(fout, fin, 0x0b5b0, 0xe790, "extracting data segment");
- extract(fout, fin, 0x1c890, 0x8be2, "extracting second data segment");
- fclose(fin);
fclose(fout);
return 0;
diff --git a/devtools/create_teenagent/md5.cpp b/devtools/create_teenagent/md5.cpp
deleted file mode 100644
index 9f90122981..0000000000
--- a/devtools/create_teenagent/md5.cpp
+++ /dev/null
@@ -1,264 +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.
- *
- */
-
-// 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;
-}
diff --git a/devtools/create_teenagent/module.mk b/devtools/create_teenagent/module.mk
index a9d102addb..7d01a2ba85 100644
--- a/devtools/create_teenagent/module.mk
+++ b/devtools/create_teenagent/module.mk
@@ -3,7 +3,7 @@ MODULE := devtools/create_teenagent
MODULE_OBJS := \
create_teenagent.o \
- md5.o
+ util.o
# Set the name of the executable
TOOL_EXECUTABLE := create_teenagent
diff --git a/devtools/create_teenagent/static_tables.h b/devtools/create_teenagent/static_tables.h
new file mode 100644
index 0000000000..6e7fdfe91c
--- /dev/null
+++ b/devtools/create_teenagent/static_tables.h
@@ -0,0 +1,16317 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 STATIC_TABLES_H
+#define STATIC_TABLES_H
+
+// Static data tables for Teenagent engine
+
+// Unpacked Executable MD5sum - 51b6d64721f7c4b498bfc0f323013e36
+
+// Code Segment
+// starts at offset 0x0200 in original executable
+#define CSEG_SIZE 46000 // 0xb3b0
+
+const static uint8 cseg[CSEG_SIZE] = {
+ 0xb8, 0x3b, 0x0b, 0x8e, 0xd8, 0x8e, 0xc0, 0xe9,
+ 0xd2, 0x00, 0x9c, 0xfa, 0x60, 0x1e, 0x06, 0xb8,
+ 0x3b, 0x0b, 0x8e, 0xd8, 0xeb, 0x0e, 0xa0, 0x48,
+ 0x32, 0xb4, 0x03, 0xff, 0x1e, 0x4a, 0x32, 0xb8,
+ 0x3b, 0x0b, 0x8e, 0xd8, 0x8e, 0xc0, 0xbb, 0x86,
+ 0x32, 0xff, 0x07, 0x75, 0x03, 0xff, 0x47, 0x02,
+ 0x33, 0xc0, 0xe8, 0xce, 0xa4, 0xff, 0x0e, 0x7f,
+ 0x32, 0x75, 0x14, 0xa1, 0x81, 0x32, 0xa3, 0x7f,
+ 0x32, 0x33, 0xc0, 0x8e, 0xd8, 0xbb, 0x6c, 0x04,
+ 0xff, 0x07, 0x75, 0x03, 0xff, 0x47, 0x02, 0xb0,
+ 0x20, 0xe6, 0x20, 0x07, 0x1f, 0x61, 0xfb, 0x9d,
+ 0xcf, 0x9c, 0xfa, 0x60, 0x1e, 0x06, 0xb8, 0x3b,
+ 0x0b, 0x8e, 0xd8, 0xeb, 0x15, 0x80, 0x3e, 0x47,
+ 0x32, 0x00, 0x74, 0x0e, 0xa0, 0x48, 0x32, 0xb4,
+ 0x03, 0xff, 0x1e, 0x4a, 0x32, 0xb8, 0x3b, 0x0b,
+ 0x8e, 0xd8, 0x8e, 0xc0, 0xfe, 0x0e, 0x83, 0x32,
+ 0x75, 0x14, 0xc6, 0x06, 0x83, 0x32, 0x6e, 0xbb,
+ 0x86, 0x32, 0xff, 0x07, 0x75, 0x03, 0xff, 0x47,
+ 0x02, 0x33, 0xc0, 0xe8, 0x6d, 0xa4, 0xff, 0x0e,
+ 0x7f, 0x32, 0x75, 0x14, 0xa1, 0x81, 0x32, 0xa3,
+ 0x7f, 0x32, 0x33, 0xc0, 0x8e, 0xd8, 0xbb, 0x6c,
+ 0x04, 0xff, 0x07, 0x75, 0x03, 0xff, 0x47, 0x02,
+ 0xb0, 0x20, 0xe6, 0x20, 0x07, 0x1f, 0x61, 0xfb,
+ 0x9d, 0xcf, 0x9c, 0x50, 0xe4, 0x60, 0x2e, 0xa2,
+ 0xd7, 0x00, 0xe4, 0x61, 0x8a, 0xe0, 0x0c, 0x80,
+ 0xe6, 0x61, 0x86, 0xe0, 0xe6, 0x61, 0xeb, 0x00,
+ 0xb0, 0x20, 0xe6, 0x20, 0x58, 0x9d, 0xcf, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xb4, 0x2c, 0xcd, 0x21,
+ 0xbb, 0x5f, 0xb1, 0x2e, 0x89, 0x0f, 0x2e, 0x89,
+ 0x57, 0x02, 0xe8, 0xfc, 0xa3, 0xe8, 0xb1, 0xb0,
+ 0xe8, 0xce, 0xaf, 0xe8, 0xee, 0xb0, 0xe8, 0x18,
+ 0xa8, 0xe8, 0x4d, 0xb2, 0xe8, 0xde, 0xa4, 0xb9,
+ 0x01, 0x00, 0xe8, 0x46, 0xb0, 0xfa, 0xb8, 0x88,
+ 0xc0, 0xbb, 0x14, 0x00, 0x2e, 0x89, 0x07, 0xbb,
+ 0x63, 0x00, 0x2e, 0x89, 0x07, 0xfb, 0xe8, 0x38,
+ 0x0a, 0xe8, 0x49, 0x0a, 0xe8, 0x6f, 0x0a, 0xe8,
+ 0x79, 0x0a, 0xe8, 0x9a, 0x0a, 0xe8, 0xb5, 0x0a,
+ 0xb8, 0x3b, 0x0b, 0xa3, 0xac, 0x00, 0xb8, 0x3a,
+ 0x01, 0xa3, 0xaa, 0x00, 0xb9, 0x07, 0x00, 0xba,
+ 0x54, 0x00, 0xe8, 0x33, 0xae, 0xa1, 0xbf, 0x32,
+ 0xa3, 0xac, 0x00, 0x33, 0xc0, 0xa3, 0xaa, 0x00,
+ 0xb9, 0x01, 0x00, 0xba, 0x54, 0x00, 0xe8, 0x1f,
+ 0xae, 0xe8, 0x82, 0x05, 0xe8, 0xf5, 0x00, 0xb9,
+ 0x04, 0x00, 0xe8, 0xee, 0xaf, 0xb8, 0x88, 0x00,
+ 0xbb, 0x99, 0x00, 0xbf, 0x8b, 0x00, 0xbe, 0x9c,
+ 0x00, 0xb5, 0x03, 0xb1, 0x0b, 0xc7, 0x06, 0xf3,
+ 0xb4, 0x0a, 0x00, 0xe8, 0x6d, 0xaa, 0xe8, 0x86,
+ 0xa4, 0xe8, 0x04, 0x07, 0xe8, 0xa0, 0x1e, 0xe8,
+ 0x03, 0x2a, 0xe8, 0x94, 0x33, 0xe8, 0xc8, 0x34,
+ 0xe8, 0x22, 0x33, 0xe8, 0x57, 0x33, 0xe8, 0xe5,
+ 0x1d, 0xe8, 0x12, 0x27, 0xe8, 0x0d, 0xa5, 0xb3,
+ 0x01, 0x72, 0x07, 0xe8, 0x35, 0xa5, 0xb3, 0x00,
+ 0x73, 0xd7, 0xe8, 0xf6, 0xa1, 0xeb, 0xd2, 0xb8,
+ 0x03, 0x00, 0xcd, 0x10, 0xb4, 0x02, 0xff, 0x1e,
+ 0x4a, 0x32, 0xb8, 0x3b, 0x0b, 0x8e, 0xd8, 0x8e,
+ 0xc0, 0xe9, 0xd8, 0xb1, 0xe8, 0x86, 0x9a, 0xe8,
+ 0x77, 0x00, 0xe8, 0x8f, 0x9a, 0xbb, 0x88, 0xe4,
+ 0x33, 0xf6, 0x33, 0xff, 0x06, 0xa1, 0xb1, 0x32,
+ 0x8e, 0xc0, 0x53, 0xe8, 0x26, 0x00, 0xe8, 0x19,
+ 0x00, 0x5b, 0x53, 0xe8, 0xca, 0xa2, 0xbe, 0x40,
+ 0x01, 0x2b, 0xf0, 0xd1, 0xee, 0x5b, 0xe8, 0x6c,
+ 0xa2, 0x43, 0x8a, 0x07, 0x0a, 0xc0, 0x75, 0xe2,
+ 0x07, 0xc3, 0xa1, 0xb1, 0x32, 0xb9, 0xe0, 0x06,
+ 0xe8, 0x05, 0xab, 0xc3, 0x1e, 0x06, 0x8c, 0xc0,
+ 0x8e, 0xd8, 0xb8, 0x00, 0xa0, 0x8e, 0xc0, 0x33,
+ 0xf6, 0xbf, 0xbf, 0xf8, 0xb9, 0x0b, 0x00, 0x51,
+ 0xb9, 0xa0, 0x00, 0x57, 0xf3, 0xa5, 0x56, 0xe8,
+ 0x08, 0x00, 0x5e, 0x5f, 0x59, 0xe2, 0xf0, 0x07,
+ 0x1f, 0xc3, 0xe8, 0xeb, 0xa4, 0xe8, 0xe8, 0xa4,
+ 0x1e, 0x8c, 0xc0, 0x8e, 0xd8, 0x33, 0xff, 0xbe,
+ 0x40, 0x01, 0xb9, 0x00, 0x7d, 0xf3, 0xa5, 0x1f,
+ 0xc3, 0xb8, 0x00, 0xa0, 0xb9, 0x00, 0x7d, 0xe8,
+ 0xbe, 0xaa, 0xa1, 0xb1, 0x32, 0xb9, 0x00, 0x7d,
+ 0xe8, 0xb5, 0xaa, 0xc3, 0xe8, 0x7c, 0x03, 0xe8,
+ 0x6c, 0x03, 0xc7, 0x06, 0xf3, 0xb4, 0x29, 0x00,
+ 0xb8, 0x8b, 0x00, 0xbb, 0x9c, 0x00, 0x8b, 0xf8,
+ 0x8b, 0xf3, 0xb5, 0x03, 0xb1, 0x0b, 0xe8, 0x8c,
+ 0xa9, 0xe8, 0xfc, 0xa9, 0xe8, 0x5c, 0x03, 0xe8,
+ 0x4c, 0x03, 0xe8, 0x97, 0xaa, 0xe8, 0x46, 0x03,
+ 0xb8, 0xc8, 0x00, 0xe8, 0xbc, 0x1c, 0xe8, 0x3d,
+ 0x03, 0xb9, 0x29, 0x00, 0xb0, 0x0c, 0xb4, 0x04,
+ 0xe8, 0x72, 0xa7, 0xbb, 0x47, 0x33, 0xc7, 0x47,
+ 0x02, 0x90, 0x03, 0xb0, 0x02, 0xe8, 0xca, 0x17,
+ 0xe8, 0x23, 0x03, 0xe8, 0x4a, 0x3d, 0xc6, 0x07,
+ 0x6c, 0xe8, 0xfe, 0xab, 0xb9, 0x3e, 0x00, 0xb0,
+ 0x08, 0xb4, 0x04, 0xe8, 0x4f, 0xa7, 0xb9, 0x3a,
+ 0x00, 0xb0, 0x28, 0xb4, 0x0a, 0xe8, 0x4e, 0xa7,
+ 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x02, 0x91, 0x03,
+ 0xb0, 0x02, 0xe8, 0x9d, 0x17, 0xe8, 0xf6, 0x02,
+ 0xe8, 0x1d, 0x3d, 0xc6, 0x47, 0x01, 0x6d, 0xe8,
+ 0xd0, 0xab, 0xc6, 0x06, 0x45, 0x33, 0xe7, 0xc6,
+ 0x06, 0x46, 0x33, 0xd7, 0xb0, 0x02, 0xb4, 0x01,
+ 0xbe, 0x92, 0x03, 0xbf, 0x93, 0x03, 0xbb, 0x8e,
+ 0x74, 0xe8, 0x82, 0x11, 0xe8, 0xcf, 0x02, 0xbb,
+ 0xc2, 0xe3, 0xe8, 0xe9, 0x02, 0xbb, 0x47, 0x33,
+ 0xc7, 0x47, 0x02, 0x94, 0x03, 0xc7, 0x06, 0xf3,
+ 0xb4, 0x2a, 0x00, 0xe8, 0x06, 0xaa, 0xe8, 0xb5,
+ 0x02, 0xb9, 0x0f, 0x00, 0xb0, 0x14, 0xb4, 0x03,
+ 0xe8, 0xea, 0xa6, 0xbb, 0x47, 0x33, 0xc7, 0x47,
+ 0x02, 0x94, 0x03, 0xb0, 0x02, 0xe8, 0x42, 0x17,
+ 0xe8, 0x9b, 0x02, 0xb9, 0x28, 0x00, 0xb0, 0x12,
+ 0xb4, 0x0e, 0xe8, 0xd0, 0xa6, 0xb0, 0x16, 0xe8,
+ 0xd4, 0xa6, 0xb0, 0x1b, 0xe8, 0xd6, 0xa6, 0xb0,
+ 0x1d, 0xe8, 0xd8, 0xa6, 0xb0, 0x1f, 0xe8, 0xda,
+ 0xa6, 0xb0, 0x21, 0xe8, 0xe3, 0xa6, 0xb0, 0x23,
+ 0xe8, 0xe5, 0xa6, 0xb0, 0x25, 0xe8, 0xe7, 0xa6,
+ 0xb9, 0x1d, 0x00, 0xb0, 0x2c, 0xe8, 0xe6, 0xa6,
+ 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x96, 0x03, 0xc7,
+ 0x47, 0x02, 0x95, 0x03, 0xb0, 0x01, 0xe8, 0xf9,
+ 0x16, 0xe8, 0x52, 0x02, 0xbb, 0xe6, 0xe3, 0xe8,
+ 0x6c, 0x02, 0xb9, 0x03, 0x00, 0xe8, 0xd3, 0xad,
+ 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x98, 0x03, 0xc7,
+ 0x47, 0x02, 0x9c, 0x03, 0xc7, 0x06, 0xf3, 0xb4,
+ 0x28, 0x00, 0xe8, 0x7f, 0xa9, 0xe8, 0x2e, 0x02,
+ 0xc6, 0x06, 0x45, 0x33, 0xe7, 0xc6, 0x06, 0x46,
+ 0x33, 0xeb, 0xb0, 0x01, 0xb4, 0x02, 0xbe, 0x98,
+ 0x03, 0xbf, 0x9c, 0x03, 0xbb, 0x0d, 0x75, 0xe8,
+ 0xc4, 0x10, 0xe8, 0x11, 0x02, 0xb9, 0x1a, 0x00,
+ 0xb0, 0x32, 0xb4, 0x0a, 0xe8, 0x46, 0xa6, 0xbb,
+ 0x47, 0x33, 0xc7, 0x07, 0x9d, 0x03, 0xc7, 0x47,
+ 0x02, 0x9e, 0x03, 0xb0, 0x01, 0xe8, 0x9a, 0x16,
+ 0xe8, 0xf3, 0x01, 0xc6, 0x06, 0x45, 0x33, 0xeb,
+ 0xb0, 0x02, 0xb4, 0x01, 0xbe, 0x9f, 0x03, 0xbf,
+ 0x98, 0x03, 0xbb, 0xa6, 0x78, 0xe8, 0x8e, 0x10,
+ 0xe8, 0xdb, 0x01, 0xbb, 0xff, 0xe3, 0xe8, 0xf5,
+ 0x01, 0xb9, 0x0b, 0x00, 0xe8, 0x5c, 0xad, 0xc7,
+ 0x06, 0xf3, 0xb4, 0x27, 0x00, 0xe8, 0x14, 0xa9,
+ 0xe8, 0xc3, 0x01, 0xb8, 0xc8, 0x00, 0xe8, 0x39,
+ 0x1b, 0xe8, 0xba, 0x01, 0xb9, 0x51, 0x00, 0xb0,
+ 0x02, 0xb4, 0x0e, 0xe8, 0xef, 0xa5, 0xb0, 0x05,
+ 0xb4, 0x0b, 0xe8, 0xf1, 0xa5, 0xb0, 0x08, 0xb4,
+ 0x08, 0xe8, 0xf1, 0xa5, 0xb0, 0x0b, 0xb4, 0x06,
+ 0xe8, 0xf1, 0xa5, 0xb0, 0x0e, 0xb4, 0x05, 0xe8,
+ 0xf1, 0xa5, 0xb0, 0x10, 0xb4, 0x03, 0xe8, 0xf1,
+ 0xa5, 0xb0, 0x10, 0xe8, 0xf3, 0xa5, 0xb0, 0x12,
+ 0xe8, 0xf5, 0xa5, 0xb0, 0x14, 0xe8, 0xf7, 0xa5,
+ 0xb0, 0x15, 0xe8, 0xf9, 0xa5, 0xbb, 0x47, 0x33,
+ 0xc7, 0x47, 0x02, 0xa0, 0x03, 0xb0, 0x02, 0xe8,
+ 0x10, 0x16, 0xe8, 0x49, 0xa6, 0xe8, 0x66, 0x01,
+ 0xe8, 0x8d, 0x3b, 0xc6, 0x07, 0x70, 0xe8, 0x41,
+ 0xaa, 0xe8, 0xf1, 0x1a, 0xe8, 0x57, 0x01, 0xc6,
+ 0x06, 0x45, 0x33, 0xd1, 0xb0, 0x01, 0xbe, 0xa1,
+ 0x03, 0xbb, 0xe1, 0x78, 0xe8, 0x80, 0x11, 0xe8,
+ 0x44, 0x01, 0xe8, 0xd8, 0x1a, 0xe8, 0x3e, 0x01,
+ 0xc6, 0x06, 0xdc, 0x1c, 0x02, 0xc7, 0x06, 0xaf,
+ 0x64, 0x3f, 0x01, 0xc7, 0x06, 0xb1, 0x64, 0x96,
+ 0x00, 0xbe, 0x3f, 0x00, 0xbf, 0x96, 0x00, 0xc6,
+ 0x06, 0xc3, 0x64, 0x01, 0xe8, 0x8c, 0x31, 0xe8,
+ 0x1c, 0x01, 0xc6, 0x06, 0x35, 0x33, 0x12, 0xc6,
+ 0x06, 0x36, 0x33, 0x24, 0xb8, 0xa8, 0x5d, 0xa3,
+ 0x37, 0x33, 0xb8, 0x84, 0x4d, 0xa3, 0x39, 0x33,
+ 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x53, 0x03, 0xb9,
+ 0xa2, 0x03, 0xe8, 0xaa, 0x16, 0xe8, 0xf6, 0x00,
+ 0xb9, 0x18, 0x00, 0xb0, 0x0b, 0xb4, 0x02, 0xe8,
+ 0x2b, 0xa5, 0xb9, 0xa3, 0x03, 0xe8, 0x1a, 0x16,
+ 0xe8, 0xb8, 0xa6, 0xe8, 0xe0, 0x00, 0xbb, 0x2f,
+ 0xe4, 0xe8, 0xfa, 0x00, 0xb9, 0x03, 0x00, 0xe8,
+ 0x61, 0xac, 0xc7, 0x06, 0xaf, 0x64, 0x32, 0x00,
+ 0xc7, 0x06, 0xb1, 0x64, 0xba, 0x00, 0xc6, 0x06,
+ 0xcc, 0x64, 0x01, 0xc6, 0x06, 0xdc, 0x64, 0x00,
+ 0xc6, 0x06, 0xcb, 0x64, 0x00, 0xe8, 0x71, 0x39,
+ 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x97, 0x03, 0xc7,
+ 0x06, 0xf3, 0xb4, 0x28, 0x00, 0xe8, 0xd0, 0x3a,
+ 0xc6, 0x07, 0x71, 0xe8, 0xf7, 0xa7, 0xe8, 0x9d,
+ 0x00, 0xc6, 0x06, 0x45, 0x33, 0xe7, 0xb0, 0x01,
+ 0xbe, 0x97, 0x03, 0xbb, 0xf1, 0x78, 0xe8, 0xc6,
+ 0x10, 0xe8, 0x8a, 0x00, 0xbe, 0xc6, 0x00, 0xbf,
+ 0xba, 0x00, 0xc6, 0x06, 0xc3, 0x64, 0x01, 0xe8,
+ 0xe9, 0x30, 0xe8, 0x79, 0x00, 0xe8, 0x8f, 0x11,
+ 0xbb, 0x58, 0x79, 0xe8, 0x77, 0x0c, 0xb9, 0xa4,
+ 0x03, 0xe8, 0xc3, 0x15, 0xe8, 0x67, 0x00, 0xe8,
+ 0x7d, 0x11, 0xbb, 0x07, 0x7e, 0xe8, 0x65, 0x0c,
+ 0xb9, 0xa4, 0x03, 0xe8, 0xb1, 0x15, 0xe8, 0x55,
+ 0x00, 0xe8, 0x6b, 0x11, 0xbb, 0x1a, 0x7e, 0xe8,
+ 0x53, 0x0c, 0xb9, 0xa4, 0x03, 0xe8, 0x9f, 0x15,
+ 0xe8, 0x43, 0x00, 0xe8, 0x7c, 0x11, 0xbb, 0x2c,
+ 0x7e, 0xe8, 0x41, 0x0c, 0xb9, 0xa5, 0x03, 0xe8,
+ 0x8d, 0x15, 0xe8, 0x31, 0x00, 0xe8, 0x47, 0x11,
+ 0xbb, 0x70, 0x7e, 0xe8, 0x2f, 0x0c, 0xbe, 0xae,
+ 0x00, 0xbf, 0xba, 0x00, 0xc6, 0x06, 0xc3, 0x64,
+ 0x01, 0xe8, 0x87, 0x30, 0xbb, 0x47, 0x33, 0xc7,
+ 0x07, 0x53, 0x03, 0xb9, 0xa6, 0x03, 0xe8, 0x66,
+ 0x15, 0xe8, 0x91, 0x96, 0xe8, 0x14, 0x00, 0xb8,
+ 0x64, 0x00, 0xe8, 0x9f, 0x19, 0xc3, 0x2e, 0x80,
+ 0x3e, 0xd7, 0x00, 0x01, 0x75, 0x04, 0x58, 0xe8,
+ 0xd4, 0xa4, 0xc3, 0x06, 0xa1, 0xb3, 0x32, 0x8e,
+ 0xc0, 0xbf, 0x00, 0xfa, 0xb9, 0x80, 0x01, 0x33,
+ 0xc0, 0xfc, 0xf3, 0xab, 0x07, 0xc3, 0x53, 0xe8,
+ 0x63, 0x96, 0xe8, 0x54, 0xfc, 0xa1, 0xb5, 0x32,
+ 0xa3, 0xac, 0x00, 0x33, 0xc0, 0xa3, 0xaa, 0x00,
+ 0xb9, 0x08, 0x00, 0xba, 0x54, 0x00, 0xe8, 0x77,
+ 0xa9, 0x5b, 0x8b, 0x17, 0x83, 0xc3, 0x02, 0x52,
+ 0x8a, 0x07, 0x32, 0xe4, 0xf7, 0x26, 0xb6, 0x00,
+ 0x8b, 0xf0, 0x53, 0xe8, 0x9b, 0x00, 0x5b, 0x5a,
+ 0x2d, 0x40, 0x01, 0xf7, 0xd8, 0xd1, 0xe8, 0x03,
+ 0xf0, 0x43, 0xe8, 0x25, 0x00, 0x43, 0x80, 0x3f,
+ 0x00, 0x75, 0xdc, 0xe8, 0x2e, 0x96, 0xbb, 0x92,
+ 0x32, 0xb9, 0x90, 0x01, 0xe8, 0xb4, 0xa2, 0xbb,
+ 0x92, 0x32, 0xe8, 0xc1, 0xa2, 0x72, 0x0a, 0xe8,
+ 0x99, 0xa0, 0x72, 0x05, 0xe8, 0x65, 0xa0, 0x73,
+ 0xee, 0xc3, 0x1e, 0x06, 0xb8, 0x00, 0xa0, 0x8e,
+ 0xc0, 0xa1, 0xb5, 0x32, 0x8e, 0xd8, 0xe8, 0x03,
+ 0x00, 0x07, 0x1f, 0xc3, 0x1e, 0xb8, 0x3b, 0x0b,
+ 0x8e, 0xd8, 0x8a, 0x0f, 0x1f, 0x0a, 0xc9, 0x74,
+ 0x47, 0x80, 0xe9, 0x1f, 0xb5, 0x00, 0xbf, 0xfe,
+ 0xff, 0xd1, 0xe1, 0x03, 0xf9, 0x8b, 0x3d, 0x8b,
+ 0x0d, 0x83, 0xc7, 0x02, 0x51, 0x56, 0x51, 0x56,
+ 0x8a, 0x05, 0x0a, 0xc0, 0x74, 0x0d, 0xfe, 0xc8,
+ 0x0a, 0xc0, 0x8a, 0xc2, 0x74, 0x02, 0x8a, 0xc6,
+ 0x26, 0x88, 0x04, 0x47, 0x46, 0xfe, 0xcd, 0x75,
+ 0xe7, 0x5e, 0x59, 0x81, 0xc6, 0x40, 0x01, 0xfe,
+ 0xc9, 0x75, 0xdb, 0x5e, 0x59, 0x8a, 0xc5, 0xb4,
+ 0x00, 0x03, 0xf0, 0x46, 0x46, 0x43, 0xeb, 0xac,
+ 0xc3, 0x33, 0xc0, 0x8a, 0x0f, 0x0a, 0xc9, 0x74,
+ 0x24, 0x42, 0x80, 0xe9, 0x1f, 0xb5, 0x00, 0xbf,
+ 0xfe, 0xff, 0xd1, 0xe1, 0x03, 0xf9, 0x1e, 0x8b,
+ 0x16, 0xb5, 0x32, 0x8e, 0xda, 0x8b, 0x3d, 0x8b,
+ 0x0d, 0x1f, 0x8a, 0xcd, 0xb5, 0x00, 0x03, 0xc1,
+ 0x40, 0x40, 0x43, 0xeb, 0xd6, 0xc3, 0xe8, 0x60,
+ 0xfb, 0xa1, 0xb5, 0x32, 0xa3, 0xac, 0x00, 0x33,
+ 0xc0, 0xa3, 0xaa, 0x00, 0xb9, 0x06, 0x00, 0xba,
+ 0x54, 0x00, 0xe8, 0x83, 0xa8, 0xa1, 0xb3, 0x32,
+ 0xa3, 0xac, 0x00, 0xb8, 0x00, 0xfa, 0xa3, 0xaa,
+ 0x00, 0xb9, 0x05, 0x00, 0xba, 0x54, 0x00, 0xe8,
+ 0x6e, 0xa8, 0x8b, 0x16, 0xb3, 0x32, 0xbe, 0x00,
+ 0xfa, 0xb0, 0x40, 0xe8, 0x14, 0xa0, 0xa1, 0xb3,
+ 0x32, 0xa3, 0xac, 0x00, 0x2e, 0xa3, 0x53, 0x08,
+ 0xb8, 0x00, 0x1e, 0xa3, 0xaa, 0x00, 0xb9, 0x09,
+ 0x00, 0xba, 0x54, 0x00, 0xe8, 0x49, 0xa8, 0x1e,
+ 0x06, 0x8b, 0x2e, 0xb5, 0x32, 0xa1, 0xb1, 0x32,
+ 0x8e, 0xc0, 0x8e, 0xd8, 0xfc, 0xb9, 0x58, 0x02,
+ 0xe8, 0x0f, 0x00, 0x07, 0x1f, 0x8b, 0x16, 0xb3,
+ 0x32, 0xbe, 0x00, 0xfa, 0xb0, 0xc0, 0xe8, 0xd9,
+ 0x9f, 0xc3, 0x2e, 0x80, 0x3e, 0xd7, 0x00, 0x00,
+ 0x75, 0x07, 0x51, 0xe8, 0x04, 0x00, 0x59, 0xe2,
+ 0xf1, 0xc3, 0xb8, 0xa0, 0x00, 0xbf, 0x00, 0x00,
+ 0x03, 0xf8, 0x03, 0xf8, 0x8b, 0xf7, 0x03, 0xf0,
+ 0xb9, 0x90, 0x10, 0xf3, 0xa5, 0x83, 0xc7, 0x00,
+ 0xb9, 0x11, 0x00, 0x51, 0x57, 0xb8, 0x9f, 0x00,
+ 0xe8, 0xe8, 0xa9, 0x03, 0xf8, 0xb8, 0xb9, 0x00,
+ 0xe8, 0xe0, 0xa9, 0x04, 0x05, 0x8a, 0xe0, 0x89,
+ 0x05, 0x5f, 0x59, 0xe2, 0xe6, 0xb9, 0x01, 0x00,
+ 0xbe, 0x01, 0x00, 0x8b, 0xc6, 0xbb, 0xa0, 0x00,
+ 0xf7, 0xe3, 0x8b, 0xf8, 0x03, 0xf9, 0x33, 0xc0,
+ 0x33, 0xdb, 0x8a, 0x9d, 0x5f, 0xff, 0x8a, 0x85,
+ 0x60, 0xff, 0x03, 0xd8, 0x8a, 0x85, 0x61, 0xff,
+ 0x03, 0xd8, 0x8a, 0x45, 0xff, 0x03, 0xd8, 0x8a,
+ 0x45, 0x01, 0x03, 0xd8, 0x8a, 0x85, 0x9f, 0x00,
+ 0x03, 0xd8, 0x8a, 0x85, 0xa0, 0x00, 0x03, 0xd8,
+ 0x8a, 0x85, 0xa1, 0x00, 0x03, 0xd8, 0xc1, 0xeb,
+ 0x03, 0x88, 0x9d, 0x00, 0x23, 0x41, 0x81, 0xf9,
+ 0xa0, 0x00, 0x72, 0xb7, 0xb9, 0x01, 0x00, 0x46,
+ 0x83, 0xfe, 0x38, 0x72, 0xae, 0xbf, 0x00, 0x00,
+ 0xbe, 0x00, 0x23, 0xb9, 0x80, 0x11, 0xf3, 0xa5,
+ 0x06, 0xb8, 0x00, 0xa0, 0x8e, 0xc0, 0x33, 0xdb,
+ 0xbe, 0x00, 0x00, 0xbf, 0xc0, 0x6c, 0xb9, 0x2c,
+ 0x00, 0xb8, 0x40, 0x01, 0xf7, 0xe1, 0x03, 0xf8,
+ 0xd1, 0xe9, 0x8b, 0xd1, 0x83, 0xea, 0x04, 0xb8,
+ 0xa0, 0x00, 0xf7, 0xe2, 0x03, 0xf0, 0xb8, 0x38,
+ 0x00, 0x2b, 0xc1, 0x8b, 0xc8, 0xe8, 0xf0, 0x9e,
+ 0x56, 0xe8, 0x0b, 0x00, 0x5e, 0xe8, 0x07, 0x00,
+ 0xe2, 0xf6, 0xe8, 0x28, 0x00, 0x07, 0xc3, 0xba,
+ 0xa0, 0x00, 0x8a, 0x04, 0x1e, 0x8e, 0xdd, 0x80,
+ 0x3f, 0x01, 0x75, 0x03, 0x26, 0x88, 0x05, 0x43,
+ 0x47, 0x80, 0x3f, 0x01, 0x1f, 0x75, 0x03, 0x26,
+ 0x88, 0x05, 0x43, 0x47, 0x46, 0x4a, 0x75, 0xe2,
+ 0xc3, 0x80, 0x66, 0x00, 0x00, 0x2e, 0x81, 0x2e,
+ 0x51, 0x08, 0x80, 0x02, 0x73, 0x08, 0x2e, 0x81,
+ 0x06, 0x51, 0x08, 0x80, 0x02, 0xc3, 0x2e, 0x8b,
+ 0x36, 0x51, 0x08, 0x1e, 0x2e, 0xa1, 0x53, 0x08,
+ 0x8e, 0xd8, 0x33, 0xff, 0xfc, 0xb9, 0x80, 0x66,
+ 0x2b, 0xce, 0xd1, 0xe9, 0xf3, 0xa5, 0x1f, 0xc3,
+ 0x80, 0x3e, 0x95, 0x60, 0x01, 0x74, 0x0a, 0xe8,
+ 0x32, 0x00, 0x80, 0x3e, 0x95, 0x60, 0x01, 0x75,
+ 0x2a, 0xc6, 0x06, 0x95, 0x60, 0x00, 0xe8, 0xa1,
+ 0x18, 0xe8, 0xf8, 0x06, 0xe8, 0x35, 0x00, 0xe8,
+ 0x05, 0xa0, 0xc6, 0x06, 0xdc, 0x1c, 0x03, 0xc6,
+ 0x06, 0xda, 0x1c, 0x00, 0xe8, 0xc7, 0x1f, 0xe8,
+ 0x5e, 0x9e, 0xe8, 0x27, 0xa0, 0xc7, 0x06, 0x52,
+ 0x72, 0x00, 0x00, 0xc3, 0x2e, 0xa0, 0xd7, 0x00,
+ 0x3c, 0x3b, 0x72, 0x0a, 0x3c, 0x44, 0x77, 0x06,
+ 0xc6, 0x06, 0x95, 0x60, 0x01, 0xc3, 0xc6, 0x06,
+ 0x95, 0x60, 0x00, 0xc3, 0xc7, 0x06, 0x96, 0x60,
+ 0x00, 0x00, 0xc6, 0x06, 0x98, 0x60, 0x00, 0xbb,
+ 0x99, 0x60, 0xe8, 0x0e, 0x00, 0x72, 0x01, 0xc3,
+ 0xe8, 0x2d, 0x01, 0x80, 0x3e, 0x98, 0x60, 0x01,
+ 0x75, 0xe2, 0xc3, 0x83, 0xeb, 0x05, 0x89, 0x1e,
+ 0x93, 0x60, 0x2e, 0x80, 0x3e, 0xd7, 0x00, 0x01,
+ 0x75, 0x03, 0xe9, 0xb4, 0x00, 0x33, 0xc9, 0x8b,
+ 0x1e, 0x93, 0x60, 0x41, 0x83, 0xc3, 0x05, 0x8a,
+ 0x47, 0x04, 0x3c, 0x03, 0x74, 0xf5, 0x8b, 0x07,
+ 0x0a, 0xc0, 0x75, 0x28, 0x8b, 0x0e, 0x96, 0x60,
+ 0x0b, 0xc9, 0x74, 0xd6, 0x8b, 0x1e, 0x93, 0x60,
+ 0x83, 0xc3, 0x05, 0xe2, 0xfb, 0x8b, 0x07, 0xe8,
+ 0x8f, 0x00, 0x8a, 0x57, 0x02, 0xb6, 0x00, 0xb4,
+ 0xe0, 0xe8, 0x96, 0x00, 0xc7, 0x06, 0x96, 0x60,
+ 0x00, 0x00, 0xeb, 0xb6, 0x53, 0x51, 0xe8, 0x78,
+ 0x00, 0x8a, 0x4f, 0x02, 0xbb, 0x0e, 0x00, 0xe8,
+ 0x24, 0x1b, 0x59, 0x5b, 0x72, 0x02, 0xeb, 0xb3,
+ 0xa1, 0x96, 0x60, 0x3b, 0xc8, 0x74, 0x37, 0x0b,
+ 0xc0, 0x74, 0x1e, 0x53, 0x51, 0x8b, 0xc8, 0x8b,
+ 0x1e, 0x93, 0x60, 0x83, 0xc3, 0x05, 0xe2, 0xfb,
+ 0x8b, 0x07, 0xe8, 0x4c, 0x00, 0x8a, 0x57, 0x02,
+ 0xb6, 0x00, 0xb4, 0xe0, 0xe8, 0x53, 0x00, 0x59,
+ 0x5b, 0x89, 0x0e, 0x96, 0x60, 0x8b, 0x07, 0xe8,
+ 0x37, 0x00, 0x8a, 0x57, 0x02, 0xb6, 0x00, 0xb4,
+ 0xd1, 0x56, 0xe8, 0x3d, 0x00, 0x5e, 0xe8, 0x3a,
+ 0x9d, 0x72, 0x08, 0xe8, 0x06, 0x9d, 0x72, 0x03,
+ 0xe9, 0x57, 0xff, 0x8b, 0x0e, 0x96, 0x60, 0x8b,
+ 0x1e, 0x93, 0x60, 0x83, 0xc3, 0x05, 0xe2, 0xfb,
+ 0x8b, 0x47, 0x03, 0x3c, 0x0a, 0x74, 0x02, 0xf9,
+ 0xc3, 0xc7, 0x06, 0x96, 0x60, 0x00, 0x00, 0xf8,
+ 0xc3, 0x8a, 0xc8, 0xb5, 0x00, 0x8a, 0xc4, 0xb4,
+ 0x00, 0xf7, 0x26, 0xb6, 0x00, 0x03, 0xc1, 0x8b,
+ 0xf0, 0xc3, 0x06, 0x8b, 0x0e, 0xb1, 0x32, 0x8e,
+ 0xc1, 0x50, 0x56, 0xe8, 0x0f, 0x00, 0x5e, 0x58,
+ 0xb9, 0x00, 0xa0, 0x8e, 0xc1, 0xe8, 0x05, 0x00,
+ 0xe8, 0xec, 0x9b, 0x07, 0xc3, 0x8b, 0xca, 0x26,
+ 0x88, 0x24, 0x46, 0xe2, 0xfa, 0x81, 0xc6, 0x40,
+ 0x01, 0x2b, 0xf2, 0xb9, 0x0c, 0x00, 0x26, 0x88,
+ 0x24, 0x03, 0xf2, 0x26, 0x88, 0x64, 0xff, 0x2b,
+ 0xf2, 0x81, 0xc6, 0x40, 0x01, 0xe2, 0xef, 0x8b,
+ 0xca, 0x26, 0x88, 0x24, 0x46, 0xe2, 0xfa, 0xc3,
+ 0xbb, 0x94, 0x60, 0x83, 0xc3, 0x05, 0x3a, 0x47,
+ 0x03, 0x75, 0xf8, 0x80, 0x7f, 0x04, 0x03, 0x74,
+ 0x06, 0x80, 0x7f, 0x04, 0x00, 0x75, 0xec, 0x50,
+ 0x8b, 0x07, 0xe8, 0x8c, 0xff, 0x58, 0xb9, 0x0e,
+ 0x00, 0x8a, 0x57, 0x02, 0xb6, 0x00, 0x3c, 0x01,
+ 0x75, 0x04, 0xe8, 0xb9, 0x01, 0xc3, 0x3c, 0x02,
+ 0x75, 0x04, 0xe8, 0x8f, 0x02, 0xc3, 0x3c, 0x03,
+ 0x75, 0x24, 0x80, 0xfc, 0x01, 0x75, 0x0d, 0xa0,
+ 0xa8, 0x64, 0x3c, 0x0a, 0x74, 0x17, 0xfe, 0x06,
+ 0xa8, 0x64, 0xeb, 0x0b, 0xa0, 0xa8, 0x64, 0x0a,
+ 0xc0, 0x74, 0x0a, 0xfe, 0x0e, 0xa8, 0x64, 0xe8,
+ 0xa4, 0x05, 0xe8, 0xdc, 0x00, 0xc3, 0x3c, 0x04,
+ 0x75, 0x24, 0x80, 0xfc, 0x01, 0x75, 0x0d, 0xa0,
+ 0xa9, 0x64, 0x3c, 0x0a, 0x74, 0x17, 0xfe, 0x06,
+ 0xa9, 0x64, 0xeb, 0x0b, 0xa0, 0xa9, 0x64, 0x0a,
+ 0xc0, 0x74, 0x0a, 0xfe, 0x0e, 0xa9, 0x64, 0xe8,
+ 0x9e, 0x05, 0xe8, 0xc8, 0x00, 0xc3, 0x3c, 0x05,
+ 0x75, 0x24, 0x80, 0xfc, 0x01, 0x75, 0x0d, 0xa0,
+ 0xaa, 0x64, 0x3c, 0x03, 0x74, 0x17, 0xfe, 0x06,
+ 0xaa, 0x64, 0xeb, 0x0b, 0xa0, 0xaa, 0x64, 0x0a,
+ 0xc0, 0x74, 0x0a, 0xfe, 0x0e, 0xaa, 0x64, 0xe8,
+ 0x98, 0x05, 0xe8, 0xc9, 0x00, 0xc3, 0x3c, 0x06,
+ 0x75, 0x24, 0x80, 0xfc, 0x01, 0x75, 0x0d, 0xa0,
+ 0xab, 0x64, 0x3c, 0x03, 0x74, 0x17, 0xfe, 0x06,
+ 0xab, 0x64, 0xeb, 0x0b, 0xa0, 0xab, 0x64, 0x0a,
+ 0xc0, 0x74, 0x0a, 0xfe, 0x0e, 0xab, 0x64, 0xe8,
+ 0x92, 0x05, 0xe8, 0xd2, 0x00, 0xc3, 0x3c, 0x07,
+ 0x75, 0x24, 0x80, 0xfc, 0x01, 0x75, 0x0d, 0xa0,
+ 0xac, 0x64, 0x3c, 0x04, 0x74, 0x17, 0xfe, 0x06,
+ 0xac, 0x64, 0xeb, 0x0b, 0xa0, 0xac, 0x64, 0x0a,
+ 0xc0, 0x74, 0x0a, 0xfe, 0x0e, 0xac, 0x64, 0xe8,
+ 0x8c, 0x05, 0xe8, 0x86, 0x00, 0xc3, 0x3c, 0x08,
+ 0x75, 0x24, 0x80, 0xfc, 0x01, 0x75, 0x0d, 0xa0,
+ 0xad, 0x64, 0x3c, 0x01, 0x74, 0x17, 0xfe, 0x06,
+ 0xad, 0x64, 0xeb, 0x0b, 0xa0, 0xad, 0x64, 0x0a,
+ 0xc0, 0x74, 0x0a, 0xfe, 0x0e, 0xad, 0x64, 0xe8,
+ 0x86, 0x05, 0xe8, 0xa0, 0x00, 0xc3, 0x3c, 0x0b,
+ 0x75, 0x04, 0xe8, 0x9c, 0x03, 0xc3, 0x3c, 0x0d,
+ 0x75, 0x02, 0xc3, 0xc3, 0xb0, 0x3c, 0xe9, 0x17,
+ 0xa8, 0xa0, 0xa8, 0x64, 0x0a, 0xc0, 0x75, 0x06,
+ 0xc6, 0x06, 0x48, 0x32, 0x00, 0xc3, 0xe8, 0x22,
+ 0x00, 0xa2, 0x48, 0x32, 0xc3, 0xa0, 0xa9, 0x64,
+ 0x0a, 0xc0, 0x75, 0x0b, 0xc6, 0x06, 0x49, 0x32,
+ 0x00, 0xc6, 0x06, 0x47, 0x32, 0x00, 0xc3, 0xc6,
+ 0x06, 0x47, 0x32, 0x01, 0xe8, 0x04, 0x00, 0xa2,
+ 0x49, 0x32, 0xc3, 0x8a, 0xc8, 0xb5, 0x00, 0xb0,
+ 0x04, 0x04, 0x06, 0xe2, 0xfc, 0xc3, 0xb0, 0x03,
+ 0x2a, 0x06, 0xaa, 0x64, 0xc0, 0xe0, 0x02, 0xa2,
+ 0x8e, 0x32, 0xc3, 0xa0, 0xac, 0x64, 0x0a, 0xc0,
+ 0x74, 0x19, 0x8a, 0xe0, 0xb0, 0x64, 0x80, 0xfc,
+ 0x01, 0x74, 0x10, 0xb0, 0x32, 0x80, 0xfc, 0x02,
+ 0x74, 0x09, 0xb0, 0x14, 0x80, 0xfc, 0x03, 0x74,
+ 0x02, 0xb0, 0x01, 0xa2, 0x96, 0x32, 0xc3, 0x8a,
+ 0x26, 0xab, 0x64, 0xb0, 0x10, 0x0a, 0xe4, 0x74,
+ 0x10, 0xb0, 0x0b, 0x80, 0xfc, 0x01, 0x74, 0x09,
+ 0xb0, 0x05, 0x80, 0xfc, 0x02, 0x74, 0x02, 0xb0,
+ 0x01, 0xa2, 0x90, 0x32, 0xc3, 0x80, 0x3e, 0xad,
+ 0x64, 0x01, 0x75, 0x0e, 0x8b, 0x16, 0xb3, 0x32,
+ 0xbe, 0x00, 0xfa, 0xb0, 0x40, 0xe8, 0x32, 0x9b,
+ 0xeb, 0x03, 0xe8, 0xcc, 0xa0, 0xc6, 0x06, 0x08,
+ 0x66, 0x00, 0xe8, 0xdc, 0x9b, 0xc3, 0xc7, 0x06,
+ 0x96, 0x60, 0x00, 0x00, 0xe8, 0x23, 0x02, 0xbb,
+ 0x32, 0x64, 0xe8, 0xe6, 0xfc, 0x72, 0x0a, 0xc7,
+ 0x06, 0x96, 0x60, 0x00, 0x00, 0xe8, 0x7c, 0x03,
+ 0xc3, 0x8b, 0x0e, 0x96, 0x60, 0x49, 0xe8, 0xa5,
+ 0x02, 0x0b, 0xc9, 0x74, 0xd9, 0xb8, 0xa6, 0x64,
+ 0x8b, 0xd8, 0x8b, 0x1f, 0x3b, 0xc3, 0x75, 0x1e,
+ 0xbb, 0xa4, 0x64, 0x8b, 0x07, 0xbb, 0xaf, 0xb3,
+ 0x81, 0xeb, 0x00, 0x00, 0x3b, 0xc3, 0x75, 0x0e,
+ 0xb8, 0xf2, 0xdb, 0xbb, 0x78, 0x64, 0x2b, 0xc3,
+ 0x3b, 0xc1, 0x75, 0x02, 0xeb, 0x35, 0xb8, 0xa6,
+ 0x64, 0xa3, 0xa6, 0x64, 0xb8, 0xaf, 0xb3, 0xa3,
+ 0xa4, 0x64, 0x06, 0xa1, 0xb1, 0x32, 0x8e, 0xc0,
+ 0xbe, 0x79, 0x51, 0xb0, 0xdb, 0xb4, 0x00, 0xb9,
+ 0x46, 0x00, 0xba, 0xce, 0x00, 0xe8, 0x07, 0x05,
+ 0xbb, 0xc3, 0x62, 0xbe, 0xbb, 0x62, 0xe8, 0x9f,
+ 0x04, 0xe8, 0x60, 0x9c, 0x07, 0xe8, 0x82, 0x9a,
+ 0xe9, 0x7b, 0xff, 0x89, 0x1e, 0xaa, 0x00, 0x8c,
+ 0x1e, 0xac, 0x00, 0xba, 0x95, 0x00, 0xe8, 0x56,
+ 0xa3, 0x58, 0x81, 0xfc, 0x00, 0x02, 0x72, 0xf9,
+ 0xe8, 0xb6, 0xfe, 0xe8, 0xc7, 0xfe, 0xe8, 0xed,
+ 0xfe, 0xe8, 0xf7, 0xfe, 0xe8, 0x18, 0xff, 0xe8,
+ 0x33, 0xff, 0x8b, 0x0e, 0x90, 0xdb, 0xe8, 0x9a,
+ 0xa4, 0x83, 0x3e, 0xf3, 0xb4, 0x18, 0x75, 0x0b,
+ 0xe8, 0xe0, 0x4c, 0xc6, 0x06, 0xdc, 0x1c, 0x02,
+ 0xe9, 0xb6, 0xf4, 0xa1, 0xaf, 0x64, 0x8b, 0x1e,
+ 0xb1, 0x64, 0x8b, 0xf8, 0x8b, 0xf3, 0x8a, 0x0e,
+ 0x07, 0x66, 0x8a, 0x2e, 0xc3, 0x64, 0xe8, 0x0a,
+ 0x9f, 0xe9, 0x9d, 0xf4, 0xc7, 0x06, 0x96, 0x60,
+ 0x00, 0x00, 0xe8, 0x45, 0x01, 0xbb, 0x32, 0x64,
+ 0xe8, 0x08, 0xfc, 0x72, 0x0a, 0xc7, 0x06, 0x96,
+ 0x60, 0x00, 0x00, 0xe8, 0x9e, 0x02, 0xc3, 0x56,
+ 0xe8, 0xe2, 0x98, 0x5e, 0xe8, 0x38, 0x00, 0x73,
+ 0x29, 0xba, 0x95, 0x00, 0x8b, 0xda, 0xa1, 0x96,
+ 0x60, 0x48, 0x04, 0x30, 0x88, 0x47, 0x07, 0xb8,
+ 0x78, 0x64, 0xb9, 0xf2, 0xdb, 0x2b, 0xc8, 0xa3,
+ 0xaa, 0x00, 0x8c, 0x1e, 0xac, 0x00, 0xe8, 0x6d,
+ 0xa3, 0xc6, 0x06, 0x98, 0x60, 0x01, 0xe8, 0xd6,
+ 0x98, 0xc3, 0xc7, 0x06, 0x96, 0x60, 0x00, 0x00,
+ 0xe8, 0x61, 0x02, 0xe8, 0xc9, 0x98, 0xc3, 0x81,
+ 0xc6, 0x85, 0x02, 0x8b, 0x0e, 0x96, 0x60, 0x49,
+ 0x56, 0xc7, 0x06, 0xa6, 0x00, 0x18, 0x00, 0xe8,
+ 0x30, 0x01, 0x5e, 0xbb, 0x78, 0x64, 0x80, 0x3f,
+ 0x28, 0x74, 0x0b, 0x33, 0xc9, 0x41, 0x43, 0x80,
+ 0x3f, 0x00, 0x75, 0xf9, 0xeb, 0x08, 0xbb, 0x78,
+ 0x64, 0xc6, 0x07, 0x00, 0x33, 0xc9, 0xe8, 0x48,
+ 0x00, 0x33, 0xc0, 0x2e, 0xa0, 0xd7, 0x00, 0x3a,
+ 0xc4, 0x8a, 0xe0, 0x74, 0xf6, 0x3c, 0x80, 0x73,
+ 0xf2, 0x3c, 0x1c, 0x74, 0x1c, 0x3c, 0x01, 0x74,
+ 0x14, 0x3c, 0x0e, 0x74, 0x1a, 0x83, 0xf9, 0x16,
+ 0x73, 0xe1, 0xe8, 0x61, 0x00, 0x73, 0xdc, 0x41,
+ 0xe8, 0x1e, 0x00, 0xeb, 0xd6, 0x33, 0xc9, 0xf8,
+ 0xc3, 0x0b, 0xc9, 0x74, 0xce, 0xf9, 0xc3, 0x0b,
+ 0xc9, 0x74, 0xc8, 0x49, 0xbb, 0x78, 0x64, 0x03,
+ 0xd9, 0xc6, 0x07, 0x00, 0xe8, 0x02, 0x00, 0xeb,
+ 0xba, 0x50, 0x51, 0x06, 0xb8, 0x00, 0xa0, 0x8e,
+ 0xc0, 0x56, 0xe8, 0x13, 0x00, 0x5e, 0x56, 0xbb,
+ 0x78, 0x64, 0xe8, 0x90, 0x96, 0xbb, 0x90, 0x64,
+ 0xe8, 0x8a, 0x96, 0x5e, 0x07, 0x59, 0x58, 0xc3,
+ 0xbb, 0x78, 0x64, 0xe8, 0xd2, 0x96, 0x03, 0xf0,
+ 0xb9, 0x0b, 0x00, 0x51, 0xb9, 0x14, 0x00, 0x26,
+ 0xc6, 0x04, 0xe8, 0x46, 0xe2, 0xf9, 0x59, 0x81,
+ 0xc6, 0x2c, 0x01, 0xe2, 0xee, 0xc3, 0xbb, 0x3f,
+ 0x60, 0x3a, 0x07, 0x74, 0x0b, 0x83, 0xc3, 0x02,
+ 0x81, 0xfb, 0x93, 0x60, 0x72, 0xf3, 0xf8, 0xc3,
+ 0x50, 0x53, 0x51, 0x06, 0x56, 0xb8, 0x00, 0xa0,
+ 0x8e, 0xc0, 0xe8, 0xc3, 0xff, 0x5e, 0x56, 0xbb,
+ 0x78, 0x64, 0xe8, 0x40, 0x96, 0x5e, 0x07, 0x59,
+ 0x5b, 0x58, 0x8a, 0x5f, 0x01, 0xbf, 0x78, 0x64,
+ 0x03, 0xf9, 0x88, 0x1d, 0xc6, 0x45, 0x01, 0x00,
+ 0xf9, 0xc3, 0x06, 0xa1, 0xb1, 0x32, 0x8e, 0xc0,
+ 0xe8, 0xb7, 0x02, 0xbb, 0x70, 0x64, 0xbe, 0x6e,
+ 0x64, 0xe8, 0xdc, 0x02, 0xe8, 0x0b, 0x00, 0xbb,
+ 0x32, 0x64, 0xe8, 0xb6, 0x02, 0xe8, 0x94, 0x9a,
+ 0x07, 0xc3, 0x33, 0xc9, 0x51, 0xc7, 0x06, 0xa6,
+ 0x00, 0x18, 0x00, 0xe8, 0x24, 0x00, 0x59, 0x51,
+ 0xbe, 0x3b, 0x0f, 0x8b, 0xc1, 0xb9, 0x0f, 0x00,
+ 0xf7, 0xe1, 0xf7, 0x26, 0xb6, 0x00, 0x03, 0xf0,
+ 0x81, 0xc6, 0x85, 0x02, 0xbb, 0x78, 0x64, 0xe8,
+ 0xe3, 0x95, 0x59, 0x41, 0x83, 0xf9, 0x0a, 0x72,
+ 0xd3, 0xc3, 0xba, 0x95, 0x00, 0x8b, 0xda, 0x8a,
+ 0xc1, 0x04, 0x30, 0x88, 0x47, 0x07, 0xb8, 0x00,
+ 0x3d, 0xb1, 0x00, 0xcd, 0x21, 0x72, 0x1c, 0x8b,
+ 0xd8, 0xb4, 0x3e, 0xcd, 0x21, 0x72, 0x2c, 0x8c,
+ 0x1e, 0xac, 0x00, 0xb8, 0x78, 0x64, 0xa3, 0xaa,
+ 0x00, 0xc7, 0x06, 0xa8, 0x00, 0x00, 0x00, 0xe8,
+ 0x9d, 0xa1, 0xc3, 0x3d, 0x02, 0x00, 0x75, 0x13,
+ 0xbb, 0x78, 0x64, 0xc6, 0x07, 0x28, 0xc6, 0x47,
+ 0x01, 0x2d, 0xc6, 0x47, 0x02, 0x29, 0xc6, 0x47,
+ 0x03, 0x00, 0xc3, 0xe9, 0xa2, 0xa4, 0xb8, 0x2f,
+ 0x00, 0xa3, 0xa6, 0x00, 0xe8, 0xab, 0xff, 0xbb,
+ 0x78, 0x64, 0x80, 0x3f, 0x28, 0x75, 0x03, 0x33,
+ 0xc9, 0xc3, 0xba, 0x95, 0x00, 0xe8, 0x48, 0xa0,
+ 0xc3, 0xe8, 0xf9, 0x96, 0xe8, 0x1e, 0x12, 0xe8,
+ 0x15, 0x97, 0x06, 0xa1, 0xb1, 0x32, 0x8e, 0xc0,
+ 0xbe, 0x26, 0x54, 0xb0, 0xe8, 0xb4, 0x00, 0xb9,
+ 0x42, 0x00, 0xba, 0x74, 0x00, 0xe8, 0x77, 0x02,
+ 0xbb, 0x27, 0x62, 0xbe, 0x21, 0x62, 0xe8, 0x0f,
+ 0x02, 0xe8, 0xd0, 0x99, 0x07, 0x2e, 0x8a, 0x26,
+ 0xd7, 0x00, 0xe8, 0x8f, 0x97, 0x72, 0x1c, 0xe8,
+ 0xb9, 0x97, 0x72, 0x17, 0x2e, 0xa0, 0xd7, 0x00,
+ 0x3c, 0x80, 0x73, 0xee, 0x0a, 0xc0, 0x74, 0xea,
+ 0x3a, 0xc4, 0x74, 0xe6, 0x3c, 0x15, 0x75, 0x03,
+ 0xe9, 0x74, 0xf2, 0xc7, 0x06, 0x96, 0x60, 0x00,
+ 0x00, 0xe8, 0xa1, 0x96, 0xe8, 0xfb, 0x11, 0xe8,
+ 0xbd, 0x96, 0xe8, 0x4f, 0x00, 0xc3, 0xe8, 0x94,
+ 0x96, 0xe8, 0xb9, 0x11, 0xe8, 0xb0, 0x96, 0x06,
+ 0xa1, 0xb1, 0x32, 0x8e, 0xc0, 0xbe, 0x6d, 0x51,
+ 0xb0, 0xe8, 0xb4, 0x00, 0xb9, 0x46, 0x00, 0xba,
+ 0xe6, 0x00, 0xe8, 0x12, 0x02, 0xbb, 0x52, 0x62,
+ 0xbe, 0x4a, 0x62, 0xe8, 0xaa, 0x01, 0xe8, 0x6b,
+ 0x99, 0x07, 0x2e, 0x8a, 0x26, 0xd7, 0x00, 0xe8,
+ 0x2a, 0x97, 0x72, 0x05, 0xe8, 0x54, 0x97, 0x73,
+ 0xf6, 0xc7, 0x06, 0x96, 0x60, 0x00, 0x00, 0xe8,
+ 0x53, 0x96, 0xe8, 0xad, 0x11, 0xe8, 0x6f, 0x96,
+ 0xe8, 0x01, 0x00, 0xc3, 0xc6, 0x06, 0xe6, 0x1c,
+ 0xd1, 0x06, 0xa1, 0xb1, 0x32, 0x8e, 0xc0, 0xe8,
+ 0x48, 0x01, 0xbb, 0x29, 0x61, 0xbe, 0x11, 0x61,
+ 0xe8, 0x6d, 0x01, 0xbb, 0x99, 0x60, 0xe8, 0x4a,
+ 0x01, 0xe8, 0x14, 0x00, 0xe8, 0x1e, 0x00, 0xe8,
+ 0x28, 0x00, 0xe8, 0x32, 0x00, 0xe8, 0x3c, 0x00,
+ 0xe8, 0x46, 0x00, 0xe8, 0x16, 0x99, 0x07, 0xc3,
+ 0xb0, 0x06, 0xbb, 0x29, 0x63, 0x8a, 0x0e, 0xa8,
+ 0x64, 0xe8, 0x54, 0x01, 0xc3, 0xb0, 0x06, 0xbb,
+ 0x6b, 0x63, 0x8a, 0x0e, 0xa9, 0x64, 0xe8, 0x47,
+ 0x01, 0xc3, 0xb0, 0x09, 0xbb, 0xad, 0x63, 0x8a,
+ 0x0e, 0xaa, 0x64, 0xe8, 0x3a, 0x01, 0xc3, 0xb0,
+ 0x09, 0xbb, 0xd1, 0x63, 0x8a, 0x0e, 0xab, 0x64,
+ 0xe8, 0x2d, 0x01, 0xc3, 0xb0, 0x09, 0xbb, 0xf5,
+ 0x63, 0x8a, 0x0e, 0xac, 0x64, 0xe8, 0x20, 0x01,
+ 0xc3, 0xb0, 0x08, 0xbb, 0x22, 0x64, 0x8a, 0x0e,
+ 0xad, 0x64, 0xe8, 0x13, 0x01, 0xc3, 0x06, 0xa1,
+ 0xb1, 0x32, 0x8e, 0xc0, 0x51, 0x52, 0x56, 0xe8,
+ 0xc0, 0x00, 0xe8, 0xa3, 0xff, 0xb8, 0x00, 0xa0,
+ 0x8e, 0xc0, 0x5e, 0x5a, 0x59, 0xe8, 0xb2, 0x00,
+ 0xe8, 0x95, 0xff, 0x07, 0xe8, 0xa0, 0x95, 0xc3,
+ 0x06, 0xa1, 0xb1, 0x32, 0x8e, 0xc0, 0x51, 0x52,
+ 0x56, 0xe8, 0x9e, 0x00, 0xe8, 0x8e, 0xff, 0xb8,
+ 0x00, 0xa0, 0x8e, 0xc0, 0x5e, 0x5a, 0x59, 0xe8,
+ 0x90, 0x00, 0xe8, 0x80, 0xff, 0x07, 0xe8, 0x7e,
+ 0x95, 0xc3, 0x06, 0xa1, 0xb1, 0x32, 0x8e, 0xc0,
+ 0x51, 0x52, 0x56, 0xe8, 0x7c, 0x00, 0xe8, 0x79,
+ 0xff, 0xb8, 0x00, 0xa0, 0x8e, 0xc0, 0x5e, 0x5a,
+ 0x59, 0xe8, 0x6e, 0x00, 0xe8, 0x6b, 0xff, 0x07,
+ 0xe8, 0x5c, 0x95, 0xc3, 0x06, 0xa1, 0xb1, 0x32,
+ 0x8e, 0xc0, 0x51, 0x52, 0x56, 0xe8, 0x5a, 0x00,
+ 0xe8, 0x64, 0xff, 0xb8, 0x00, 0xa0, 0x8e, 0xc0,
+ 0x5e, 0x5a, 0x59, 0xe8, 0x4c, 0x00, 0xe8, 0x56,
+ 0xff, 0x07, 0xe8, 0x3a, 0x95, 0xc3, 0x06, 0xa1,
+ 0xb1, 0x32, 0x8e, 0xc0, 0x51, 0x52, 0x56, 0xe8,
+ 0x38, 0x00, 0xe8, 0x4f, 0xff, 0xb8, 0x00, 0xa0,
+ 0x8e, 0xc0, 0x5e, 0x5a, 0x59, 0xe8, 0x2a, 0x00,
+ 0xe8, 0x41, 0xff, 0x07, 0xe8, 0x18, 0x95, 0xc3,
+ 0x06, 0xa1, 0xb1, 0x32, 0x8e, 0xc0, 0x51, 0x52,
+ 0x56, 0xe8, 0x16, 0x00, 0xe8, 0x3a, 0xff, 0xb8,
+ 0x00, 0xa0, 0x8e, 0xc0, 0x5e, 0x5a, 0x59, 0xe8,
+ 0x08, 0x00, 0xe8, 0x2c, 0xff, 0x07, 0xe8, 0xf6,
+ 0x94, 0xc3, 0xb0, 0xe8, 0xb4, 0xe0, 0xe8, 0x8e,
+ 0x00, 0xc3, 0xbe, 0x32, 0x05, 0xb0, 0xe8, 0xb4,
+ 0x00, 0xb9, 0xc0, 0x00, 0xba, 0xdc, 0x00, 0xe8,
+ 0x7d, 0x00, 0xc3, 0x53, 0x8b, 0x07, 0xe8, 0xc0,
+ 0xf8, 0xb9, 0x0e, 0x00, 0x8a, 0x57, 0x02, 0xb6,
+ 0x00, 0xb4, 0xe0, 0xe8, 0x38, 0x00, 0x5b, 0x83,
+ 0xc3, 0x05, 0x80, 0x3f, 0x00, 0x75, 0xe4, 0xc3,
+ 0x56, 0x8b, 0x34, 0xe8, 0x37, 0x93, 0x5e, 0x43,
+ 0x46, 0x46, 0x80, 0x3f, 0x00, 0x75, 0xf1, 0xc3,
+ 0xb4, 0x00, 0xb5, 0x00, 0x2b, 0xd8, 0x41, 0x03,
+ 0xd8, 0xe2, 0xfc, 0x8a, 0x47, 0x01, 0xf7, 0x26,
+ 0xb6, 0x00, 0x8a, 0x0f, 0x03, 0xc1, 0x8b, 0xf0,
+ 0x43, 0x43, 0xe8, 0x10, 0x93, 0xc3, 0x8b, 0xda,
+ 0x26, 0x88, 0x24, 0x46, 0x4a, 0x75, 0xf9, 0x81,
+ 0xc6, 0x40, 0x01, 0x2b, 0xf3, 0x83, 0xe9, 0x02,
+ 0x8b, 0xd3, 0x26, 0x88, 0x24, 0x46, 0x83, 0xea,
+ 0x02, 0x03, 0xf2, 0x26, 0x88, 0x24, 0x46, 0x81,
+ 0xc6, 0x40, 0x01, 0x2b, 0xf3, 0xe2, 0xe9, 0x26,
+ 0x88, 0x24, 0x46, 0x4b, 0x75, 0xf9, 0xc3, 0x8b,
+ 0xda, 0x26, 0x88, 0x24, 0x46, 0x4a, 0x75, 0xf9,
+ 0x81, 0xc6, 0x40, 0x01, 0x2b, 0xf3, 0x83, 0xe9,
+ 0x02, 0x8b, 0xd3, 0x26, 0x88, 0x24, 0x46, 0x83,
+ 0xea, 0x02, 0x26, 0x88, 0x04, 0x46, 0x4a, 0x75,
+ 0xf9, 0x26, 0x88, 0x24, 0x46, 0x81, 0xc6, 0x40,
+ 0x01, 0x2b, 0xf3, 0xe2, 0xe4, 0x26, 0x88, 0x24,
+ 0x46, 0x4b, 0x75, 0xf9, 0xc3, 0x8b, 0x07, 0x0b,
+ 0xc0, 0x74, 0x0d, 0x83, 0x7f, 0x02, 0xff, 0x74,
+ 0x04, 0xc7, 0x07, 0x00, 0x00, 0x8b, 0xd8, 0xc3,
+ 0x83, 0xc3, 0x02, 0xeb, 0xe8, 0xe8, 0xed, 0x00,
+ 0xbb, 0xf2, 0xdb, 0x80, 0x3f, 0x00, 0x74, 0x2f,
+ 0x83, 0xeb, 0x02, 0x83, 0xc3, 0x02, 0x53, 0x80,
+ 0x3f, 0xff, 0x75, 0x05, 0x53, 0xe8, 0x75, 0x0d,
+ 0x5b, 0xe8, 0x71, 0x8e, 0x5b, 0x2e, 0x80, 0x3e,
+ 0xd7, 0x00, 0x01, 0x74, 0x09, 0xe8, 0xad, 0x00,
+ 0x80, 0x7f, 0x03, 0x00, 0x75, 0x03, 0xe9, 0xa0,
+ 0x00, 0x80, 0x7f, 0x02, 0x00, 0x75, 0xd4, 0x53,
+ 0x8a, 0x26, 0x96, 0xda, 0xa0, 0x97, 0xda, 0xe8,
+ 0x04, 0x0d, 0xe8, 0x4f, 0x98, 0xa0, 0x96, 0xda,
+ 0x8b, 0x0e, 0x98, 0xda, 0x8b, 0x16, 0x9a, 0xda,
+ 0xe8, 0xd3, 0x00, 0x5b, 0x43, 0xe8, 0x4d, 0x0d,
+ 0x83, 0xc3, 0x02, 0x53, 0xa0, 0x96, 0xda, 0x8b,
+ 0x0e, 0x9c, 0xda, 0x8b, 0x16, 0x9e, 0xda, 0x80,
+ 0x3f, 0xff, 0x75, 0x03, 0xe8, 0x74, 0x00, 0xe8,
+ 0xb7, 0x01, 0x5b, 0x2e, 0x80, 0x3e, 0xd7, 0x00,
+ 0x01, 0x74, 0x3b, 0xe8, 0x57, 0x00, 0x80, 0x7f,
+ 0x02, 0x00, 0x75, 0xd4, 0x80, 0x7f, 0x03, 0x00,
+ 0x74, 0x2c, 0xe8, 0x18, 0x0d, 0x43, 0x83, 0xc3,
+ 0x02, 0x53, 0x80, 0x3f, 0xff, 0x75, 0x03, 0xe8,
+ 0x49, 0x00, 0xe8, 0x16, 0x8f, 0x5b, 0x2e, 0x80,
+ 0x3e, 0xd7, 0x00, 0x01, 0x74, 0x10, 0xe8, 0x2c,
+ 0x00, 0x80, 0x7f, 0x02, 0x00, 0x75, 0xdf, 0x43,
+ 0x80, 0x7f, 0x02, 0x00, 0x75, 0x9f, 0xa0, 0x96,
+ 0xda, 0x8b, 0x0e, 0xa0, 0xda, 0x8b, 0x16, 0xa2,
+ 0xda, 0xe8, 0x62, 0x00, 0xe8, 0x0f, 0x98, 0xc6,
+ 0x06, 0x33, 0x33, 0x01, 0xc6, 0x06, 0xdd, 0x1c,
+ 0x02, 0xe8, 0x50, 0x98, 0xc3, 0x4b, 0x43, 0x80,
+ 0x3f, 0x00, 0x75, 0xfa, 0x80, 0x7f, 0x01, 0x00,
+ 0x75, 0xf4, 0xc3, 0x60, 0xb8, 0x5a, 0x00, 0xe8,
+ 0xaa, 0x0c, 0x61, 0x43, 0xc3, 0x06, 0xb8, 0x69,
+ 0x1c, 0x8e, 0xc0, 0xbe, 0xf2, 0xdb, 0x33, 0xc9,
+ 0x26, 0x8a, 0x07, 0x8a, 0xe0, 0x26, 0x0a, 0x67,
+ 0x01, 0x26, 0x0a, 0x67, 0x02, 0x26, 0x0a, 0x67,
+ 0x03, 0x74, 0x12, 0x88, 0x04, 0x41, 0x81, 0xf9,
+ 0xcc, 0x07, 0x72, 0x05, 0xb0, 0x39, 0xe9, 0x87,
+ 0xa0, 0x43, 0x46, 0xeb, 0xdb, 0x33, 0xc0, 0x89,
+ 0x04, 0x89, 0x44, 0x02, 0x07, 0xc3, 0xe8, 0x0e,
+ 0x00, 0xc6, 0x06, 0xdc, 0x1c, 0x02, 0xe8, 0x7d,
+ 0x15, 0xc6, 0x06, 0xdc, 0x1c, 0x03, 0xc3, 0xbf,
+ 0xc7, 0x32, 0xb3, 0x1b, 0x48, 0xf6, 0xe3, 0x03,
+ 0xf8, 0x89, 0x0d, 0xc6, 0x06, 0x34, 0x33, 0x00,
+ 0x52, 0x57, 0xe8, 0x9e, 0x96, 0x5f, 0x5a, 0x52,
+ 0x57, 0xe8, 0x69, 0x18, 0x5f, 0x57, 0xa1, 0x7a,
+ 0x32, 0x0b, 0xc0, 0x74, 0x1f, 0x40, 0x3b, 0x05,
+ 0x75, 0x1a, 0xe8, 0x48, 0x96, 0xa0, 0x49, 0x32,
+ 0xb4, 0x04, 0x8a, 0x2e, 0x7c, 0x32, 0x06, 0xff,
+ 0x1e, 0x4a, 0x32, 0x07, 0xb8, 0x3b, 0x0b, 0x8e,
+ 0xd8, 0xe8, 0x6f, 0x96, 0x5f, 0x5a, 0x39, 0x15,
+ 0x76, 0xcd, 0xc6, 0x06, 0x34, 0x33, 0x01, 0xc7,
+ 0x06, 0x7a, 0x32, 0x00, 0x00, 0xc3, 0x60, 0xe8,
+ 0xa5, 0x92, 0x61, 0xbf, 0xc7, 0x32, 0xb3, 0x1b,
+ 0x48, 0xf6, 0xe3, 0x03, 0xf8, 0x89, 0x0d, 0xc6,
+ 0x06, 0x34, 0x33, 0x00, 0x52, 0x57, 0xe8, 0x42,
+ 0x96, 0x5f, 0x5a, 0x52, 0x57, 0xe8, 0x08, 0xf5,
+ 0xe8, 0xa4, 0x0c, 0xe8, 0x07, 0x18, 0xe8, 0x25,
+ 0x15, 0x5f, 0x57, 0xa1, 0x7a, 0x32, 0x0b, 0xc0,
+ 0x74, 0x1f, 0x40, 0x3b, 0x05, 0x75, 0x1a, 0xe8,
+ 0xe3, 0x95, 0xa0, 0x49, 0x32, 0xb4, 0x04, 0x8a,
+ 0x2e, 0x7c, 0x32, 0x06, 0xff, 0x1e, 0x4a, 0x32,
+ 0x07, 0xb8, 0x3b, 0x0b, 0x8e, 0xd8, 0xe8, 0x0a,
+ 0x96, 0x5f, 0x5a, 0x33, 0xc0, 0x80, 0x3e, 0xe1,
+ 0xc3, 0x00, 0x75, 0x1f, 0x8b, 0x05, 0xe8, 0x1a,
+ 0x93, 0xc6, 0x06, 0xcf, 0x00, 0x04, 0x72, 0x13,
+ 0xe8, 0xe1, 0x92, 0xc6, 0x06, 0xcf, 0x00, 0x02,
+ 0x72, 0x09, 0x33, 0xc0, 0xa2, 0xcf, 0x00, 0x39,
+ 0x15, 0x76, 0xa0, 0x50, 0xc6, 0x06, 0x34, 0x33,
+ 0x01, 0xc7, 0x06, 0x7a, 0x32, 0x00, 0x00, 0xc6,
+ 0x06, 0xdc, 0x1c, 0x02, 0xe8, 0x8f, 0x14, 0xc6,
+ 0x06, 0xdc, 0x1c, 0x03, 0xe8, 0xee, 0x91, 0x58,
+ 0xc3, 0x53, 0xbf, 0xc7, 0x32, 0xb3, 0x1b, 0x48,
+ 0xf6, 0xe3, 0x03, 0xf8, 0x89, 0x0d, 0x5b, 0x51,
+ 0x52, 0x57, 0xe8, 0xc6, 0x8d, 0x5f, 0x5a, 0x59,
+ 0x51, 0x52, 0x57, 0xe8, 0x77, 0x17, 0x2e, 0x80,
+ 0x3e, 0xd7, 0x00, 0x01, 0x74, 0x24, 0x80, 0x3e,
+ 0x96, 0x32, 0x00, 0x74, 0x08, 0xbb, 0x92, 0x32,
+ 0xe8, 0xd3, 0x94, 0x72, 0x15, 0xe8, 0xab, 0x92,
+ 0x72, 0x10, 0xe8, 0x77, 0x92, 0x72, 0x0b, 0x5f,
+ 0x5a, 0x59, 0x39, 0x15, 0x76, 0xd2, 0x89, 0x0d,
+ 0xeb, 0xce, 0x5f, 0x5a, 0x59, 0xa1, 0xa4, 0xda,
+ 0x89, 0x05, 0xc6, 0x06, 0x33, 0x33, 0x01, 0xc6,
+ 0x06, 0xdd, 0x1c, 0x02, 0xc6, 0x06, 0xdb, 0x1c,
+ 0x01, 0xc6, 0x06, 0xdc, 0x1c, 0x02, 0xe8, 0x1d,
+ 0x14, 0xc6, 0x06, 0x33, 0x33, 0x00, 0xc6, 0x06,
+ 0xdc, 0x1c, 0x03, 0xc6, 0x06, 0xdd, 0x1c, 0x03,
+ 0xc6, 0x06, 0xdb, 0x1c, 0x00, 0xc3, 0x50, 0x57,
+ 0x56, 0xe8, 0x41, 0xfe, 0x5e, 0x5f, 0x58, 0x50,
+ 0x33, 0xd2, 0x8a, 0xd0, 0x4a, 0xd1, 0xe2, 0xbb,
+ 0x47, 0x33, 0x03, 0xda, 0x89, 0x37, 0x2b, 0xda,
+ 0x8a, 0xd4, 0x4a, 0xd1, 0xe2, 0x03, 0xda, 0x89,
+ 0x3f, 0xe8, 0xc8, 0x95, 0xc6, 0x06, 0x33, 0x33,
+ 0x01, 0xc6, 0x06, 0xdd, 0x1c, 0x02, 0xe8, 0xd5,
+ 0x13, 0xc6, 0x06, 0x33, 0x33, 0x00, 0xc6, 0x06,
+ 0xdd, 0x1c, 0x03, 0x58, 0x50, 0x98, 0xbf, 0xc7,
+ 0x32, 0xb3, 0x1b, 0x48, 0xf6, 0xe3, 0x03, 0xf8,
+ 0x89, 0x3e, 0x41, 0x33, 0xc7, 0x05, 0x01, 0x00,
+ 0x58, 0x8a, 0xc4, 0x98, 0xbf, 0xc7, 0x32, 0xb3,
+ 0x1b, 0x48, 0xf6, 0xe3, 0x03, 0xf8, 0x89, 0x3e,
+ 0x43, 0x33, 0xc7, 0x05, 0x01, 0x00, 0xbb, 0xf2,
+ 0xdb, 0x83, 0xeb, 0x02, 0x83, 0xc3, 0x02, 0x53,
+ 0xa0, 0x45, 0x33, 0xa2, 0xe7, 0x1c, 0xe8, 0x6e,
+ 0x06, 0x80, 0x3f, 0xff, 0x75, 0x03, 0xe8, 0xc5,
+ 0x00, 0x8b, 0x3e, 0x41, 0x33, 0xe8, 0xd3, 0x8c,
+ 0x5b, 0x53, 0xe8, 0x88, 0x16, 0x8b, 0x3e, 0x43,
+ 0x33, 0xc7, 0x05, 0x01, 0x00, 0x2e, 0x80, 0x3e,
+ 0xd7, 0x00, 0x01, 0x74, 0x19, 0x80, 0x3e, 0x96,
+ 0x32, 0x00, 0x74, 0x08, 0xbb, 0x92, 0x32, 0xe8,
+ 0xdc, 0x93, 0x72, 0x0a, 0xe8, 0xb4, 0x91, 0x72,
+ 0x05, 0xe8, 0x80, 0x91, 0x73, 0xd4, 0x5b, 0x2e,
+ 0x80, 0x3e, 0xd7, 0x00, 0x01, 0x74, 0x76, 0xe8,
+ 0x6b, 0xfd, 0x80, 0x7f, 0x02, 0x00, 0x75, 0xa4,
+ 0x80, 0x7f, 0x03, 0x00, 0x74, 0x67, 0x43, 0x83,
+ 0xc3, 0x02, 0x53, 0xa0, 0x46, 0x33, 0xa2, 0xe7,
+ 0x1c, 0xe8, 0x0b, 0x06, 0x80, 0x3f, 0xff, 0x75,
+ 0x03, 0xe8, 0x62, 0x00, 0x8b, 0x3e, 0x43, 0x33,
+ 0xe8, 0x70, 0x8c, 0x5b, 0x53, 0xe8, 0x25, 0x16,
+ 0x8b, 0x3e, 0x41, 0x33, 0xc7, 0x05, 0x01, 0x00,
+ 0x2e, 0x80, 0x3e, 0xd7, 0x00, 0x01, 0x74, 0x19,
+ 0x80, 0x3e, 0x96, 0x32, 0x00, 0x74, 0x08, 0xbb,
+ 0x92, 0x32, 0xe8, 0x79, 0x93, 0x72, 0x0a, 0xe8,
+ 0x51, 0x91, 0x72, 0x05, 0xe8, 0x1d, 0x91, 0x73,
+ 0xd4, 0x5b, 0x2e, 0x80, 0x3e, 0xd7, 0x00, 0x01,
+ 0x74, 0x13, 0xe8, 0x08, 0xfd, 0x80, 0x7f, 0x02,
+ 0x00, 0x75, 0xa4, 0x43, 0x80, 0x7f, 0x02, 0x00,
+ 0x74, 0x03, 0xe9, 0x37, 0xff, 0xe8, 0xaf, 0x05,
+ 0xe8, 0xf3, 0x94, 0xc6, 0x06, 0x33, 0x33, 0x01,
+ 0xc6, 0x06, 0xdd, 0x1c, 0x02, 0xc3, 0x60, 0x8b,
+ 0x3e, 0x41, 0x33, 0xc7, 0x05, 0x01, 0x00, 0x8b,
+ 0x3e, 0x43, 0x33, 0xc7, 0x05, 0x01, 0x00, 0xc6,
+ 0x06, 0x33, 0x33, 0x01, 0xc6, 0x06, 0xdd, 0x1c,
+ 0x02, 0xe8, 0xa2, 0x12, 0xc6, 0x06, 0x33, 0x33,
+ 0x00, 0xc6, 0x06, 0xdd, 0x1c, 0x03, 0xb8, 0x5a,
+ 0x00, 0xe8, 0x78, 0x09, 0x8b, 0x3e, 0x41, 0x33,
+ 0xc7, 0x05, 0x01, 0x00, 0x8b, 0x3e, 0x43, 0x33,
+ 0xc7, 0x05, 0x01, 0x00, 0x61, 0x43, 0xc3, 0x98,
+ 0x50, 0x56, 0xe8, 0xb8, 0xfc, 0x5e, 0x58, 0x50,
+ 0x48, 0xd1, 0xe0, 0xbb, 0x47, 0x33, 0x03, 0xd8,
+ 0x89, 0x37, 0xe8, 0x4f, 0x94, 0xc6, 0x06, 0x33,
+ 0x33, 0x01, 0xc6, 0x06, 0xdd, 0x1c, 0x02, 0xe8,
+ 0x5c, 0x12, 0xc6, 0x06, 0x33, 0x33, 0x00, 0xc6,
+ 0x06, 0xdd, 0x1c, 0x03, 0x58, 0xbf, 0xc7, 0x32,
+ 0xb3, 0x1b, 0x48, 0xf6, 0xe3, 0x03, 0xf8, 0x89,
+ 0x3e, 0x41, 0x33, 0xc7, 0x05, 0x01, 0x00, 0xbb,
+ 0xf0, 0xdb, 0x83, 0xc3, 0x02, 0x53, 0xa0, 0x45,
+ 0x33, 0xa2, 0xe7, 0x1c, 0xe8, 0x10, 0x05, 0x80,
+ 0x3f, 0xff, 0x75, 0x03, 0xe8, 0x53, 0x00, 0x8b,
+ 0x3e, 0x41, 0x33, 0xe8, 0x75, 0x8b, 0x5b, 0x53,
+ 0xe8, 0x2a, 0x15, 0x2e, 0x80, 0x3e, 0xd7, 0x00,
+ 0x01, 0x74, 0x19, 0x80, 0x3e, 0x96, 0x32, 0x00,
+ 0x74, 0x08, 0xbb, 0x92, 0x32, 0xe8, 0x86, 0x92,
+ 0x72, 0x0a, 0xe8, 0x5e, 0x90, 0x72, 0x05, 0xe8,
+ 0x2a, 0x90, 0x73, 0xdc, 0x5b, 0x2e, 0x80, 0x3e,
+ 0xd7, 0x00, 0x01, 0x74, 0x09, 0xe8, 0x15, 0xfc,
+ 0x80, 0x7f, 0x02, 0x00, 0x75, 0xac, 0xe8, 0x26,
+ 0x00, 0xe8, 0xc3, 0x04, 0xe8, 0x07, 0x94, 0xc6,
+ 0x06, 0x33, 0x33, 0x01, 0xc6, 0x06, 0xdd, 0x1c,
+ 0x02, 0xc3, 0x60, 0xe8, 0x11, 0x00, 0xb8, 0x5a,
+ 0x00, 0xe8, 0xb0, 0x08, 0x8b, 0x3e, 0x41, 0x33,
+ 0xc7, 0x05, 0x01, 0x00, 0x61, 0x43, 0xc3, 0x8b,
+ 0x3e, 0x41, 0x33, 0xc7, 0x05, 0x01, 0x00, 0xc6,
+ 0x06, 0x33, 0x33, 0x01, 0xc6, 0x06, 0xdd, 0x1c,
+ 0x02, 0xe8, 0xaa, 0x11, 0xc6, 0x06, 0x33, 0x33,
+ 0x00, 0xc6, 0x06, 0xdd, 0x1c, 0x03, 0xc3, 0xb0,
+ 0xe7, 0xb4, 0x00, 0xbf, 0x01, 0x00, 0xb3, 0x01,
+ 0xb7, 0x01, 0xb1, 0x01, 0xb5, 0x15, 0xb2, 0x01,
+ 0xb6, 0x01, 0xe8, 0x9b, 0x02, 0xbb, 0x47, 0x33,
+ 0xc7, 0x07, 0x98, 0x03, 0xc6, 0x06, 0x96, 0xda,
+ 0x01, 0xc3, 0xe8, 0xda, 0xff, 0xbb, 0x47, 0x33,
+ 0xc7, 0x07, 0x9a, 0x03, 0xc3, 0xe8, 0xcf, 0xff,
+ 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x99, 0x03, 0xc3,
+ 0xb0, 0xef, 0xb4, 0x00, 0xbf, 0x01, 0x00, 0xb3,
+ 0x01, 0xb7, 0x01, 0xb1, 0x01, 0xb5, 0x14, 0xb2,
+ 0x01, 0xb6, 0x01, 0xe8, 0x62, 0x02, 0xbb, 0x47,
+ 0x33, 0xc7, 0x07, 0x59, 0x03, 0xc6, 0x06, 0x96,
+ 0xda, 0x01, 0xc3, 0xb0, 0xec, 0xb4, 0x01, 0xbf,
+ 0x01, 0x00, 0xb3, 0x01, 0xb7, 0x01, 0xb1, 0x01,
+ 0xb5, 0x14, 0xb2, 0x01, 0xb6, 0x01, 0xe8, 0x3f,
+ 0x02, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x2d, 0x03,
+ 0xc6, 0x06, 0x96, 0xda, 0x01, 0xc3, 0xb0, 0xec,
+ 0xb4, 0x00, 0xbf, 0x01, 0x00, 0xb3, 0x01, 0xb7,
+ 0x01, 0xb1, 0x01, 0xb5, 0x14, 0xb2, 0x01, 0xb6,
+ 0x01, 0xe8, 0x1c, 0x02, 0xbb, 0x47, 0x33, 0xc7,
+ 0x07, 0x2e, 0x03, 0xc6, 0x06, 0x96, 0xda, 0x01,
+ 0xc3, 0xe8, 0xda, 0xff, 0xbb, 0x47, 0x33, 0xc7,
+ 0x07, 0x40, 0x03, 0xc3, 0xe8, 0xcf, 0xff, 0xbb,
+ 0x47, 0x33, 0xc7, 0x07, 0x58, 0x03, 0xc3, 0xe8,
+ 0xc4, 0xff, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0xaa,
+ 0x03, 0xc3, 0xb0, 0xd0, 0xb4, 0x02, 0xbf, 0x01,
+ 0x00, 0xb3, 0x01, 0xb7, 0x01, 0xb1, 0x01, 0xb5,
+ 0x22, 0xb2, 0x01, 0xb6, 0x01, 0xe8, 0xd8, 0x01,
+ 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x29, 0x03, 0xc6,
+ 0x06, 0x96, 0xda, 0x01, 0xc3, 0xb0, 0xe5, 0xb4,
+ 0x01, 0xb3, 0x01, 0xb7, 0x01, 0xb1, 0x02, 0xb5,
+ 0x13, 0xb2, 0x14, 0xb6, 0x14, 0xbf, 0x01, 0x00,
+ 0xe8, 0xb5, 0x01, 0xbb, 0x47, 0x33, 0xc7, 0x07,
+ 0x0b, 0x02, 0xc6, 0x06, 0x96, 0xda, 0x01, 0xc3,
+ 0xb0, 0xd8, 0xb4, 0x01, 0xb3, 0x01, 0xb7, 0x01,
+ 0xb1, 0x01, 0xb5, 0x18, 0xb2, 0x18, 0xb6, 0x18,
+ 0xbf, 0x01, 0x00, 0xe8, 0x92, 0x01, 0xbb, 0x47,
+ 0x33, 0xc7, 0x07, 0x0a, 0x02, 0xc6, 0x06, 0x96,
+ 0xda, 0x01, 0xc3, 0xb0, 0xe5, 0xb4, 0x07, 0xb3,
+ 0x01, 0xb7, 0x02, 0xb1, 0x03, 0xb5, 0x20, 0xb2,
+ 0x21, 0xb6, 0x22, 0xbf, 0x03, 0x00, 0xe8, 0x6f,
+ 0x01, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0xf6, 0x01,
+ 0xc6, 0x06, 0x96, 0xda, 0x01, 0xc3, 0xb0, 0xd9,
+ 0xb4, 0x01, 0xb3, 0x01, 0xb7, 0x01, 0xb1, 0x01,
+ 0xb5, 0x14, 0xb2, 0x15, 0xb6, 0x15, 0xbf, 0x01,
+ 0x00, 0xe8, 0x4c, 0x01, 0xbb, 0x47, 0x33, 0xc7,
+ 0x07, 0x11, 0x02, 0xc6, 0x06, 0x96, 0xda, 0x01,
+ 0xc3, 0xb0, 0xd9, 0xb4, 0x00, 0xb3, 0x01, 0xb7,
+ 0x01, 0xb1, 0x01, 0xb5, 0x09, 0xb2, 0x09, 0xb6,
+ 0x09, 0xbf, 0x01, 0x00, 0xe8, 0x29, 0x01, 0xbb,
+ 0x47, 0x33, 0xc7, 0x07, 0x22, 0x02, 0xc6, 0x06,
+ 0x96, 0xda, 0x01, 0xc3, 0xb0, 0xe5, 0xb4, 0x01,
+ 0xbf, 0x01, 0x00, 0xb3, 0x01, 0xb7, 0x01, 0xb1,
+ 0x01, 0xb5, 0x14, 0xb2, 0x15, 0xb6, 0x15, 0xe8,
+ 0x06, 0x01, 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x02,
+ 0x0c, 0x02, 0xc6, 0x06, 0x96, 0xda, 0x02, 0xc3,
+ 0xb0, 0xe5, 0xb4, 0x04, 0xbf, 0x01, 0x00, 0xb3,
+ 0x01, 0xb7, 0x01, 0xb1, 0x01, 0xb5, 0x1f, 0xb2,
+ 0x01, 0xb6, 0x01, 0xe8, 0xe2, 0x00, 0xbb, 0x47,
+ 0x33, 0xc7, 0x47, 0x02, 0xa0, 0x02, 0xc6, 0x06,
+ 0x96, 0xda, 0x02, 0xc3, 0xb0, 0xd0, 0xb4, 0x01,
+ 0xbf, 0x03, 0x00, 0xb3, 0x03, 0xb7, 0x03, 0xb1,
+ 0x01, 0xb5, 0x0d, 0xb2, 0x03, 0xb6, 0x03, 0xe8,
+ 0xbe, 0x00, 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x02,
+ 0x9a, 0x02, 0xc6, 0x06, 0x96, 0xda, 0x02, 0xc3,
+ 0xb0, 0xd0, 0xb4, 0x06, 0xbf, 0x01, 0x00, 0xb3,
+ 0x01, 0xb7, 0x01, 0xb1, 0x01, 0xb5, 0x12, 0xb2,
+ 0x01, 0xb6, 0x01, 0xe8, 0x9a, 0x00, 0xbb, 0x47,
+ 0x33, 0xc7, 0x07, 0x1d, 0x03, 0xc6, 0x06, 0x96,
+ 0xda, 0x01, 0xc3, 0xb0, 0xd0, 0xb4, 0x01, 0xbf,
+ 0x01, 0x00, 0xb3, 0x01, 0xb7, 0x01, 0xb1, 0x01,
+ 0xb5, 0x14, 0xb2, 0x01, 0xb6, 0x01, 0xe8, 0x77,
+ 0x00, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0xbe, 0x02,
+ 0xc6, 0x06, 0x96, 0xda, 0x01, 0xc3, 0xb0, 0xef,
+ 0xb4, 0x01, 0xbf, 0x01, 0x00, 0xb3, 0x01, 0xb7,
+ 0x01, 0xb1, 0x01, 0xb5, 0x14, 0xb2, 0x01, 0xb6,
+ 0x01, 0xe8, 0x54, 0x00, 0xbb, 0x47, 0x33, 0xc7,
+ 0x07, 0xc5, 0x02, 0xc6, 0x06, 0x96, 0xda, 0x01,
+ 0xc3, 0xb0, 0xef, 0xb4, 0x01, 0xbf, 0x01, 0x00,
+ 0xb3, 0x01, 0xb7, 0x01, 0xb1, 0x01, 0xb5, 0x03,
+ 0xb2, 0x01, 0xb6, 0x01, 0xe8, 0x31, 0x00, 0xbb,
+ 0x47, 0x33, 0xc7, 0x07, 0xd7, 0x02, 0xc6, 0x06,
+ 0x96, 0xda, 0x01, 0xc3, 0xb0, 0xd0, 0xb4, 0x00,
+ 0xb3, 0x01, 0xb7, 0x01, 0xb1, 0x01, 0xb5, 0x18,
+ 0xb2, 0x01, 0xb6, 0x01, 0xbf, 0x01, 0x00, 0xe8,
+ 0x0e, 0x00, 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x06,
+ 0x17, 0x03, 0xc6, 0x06, 0x96, 0xda, 0x04, 0xc3,
+ 0xa2, 0xe7, 0x1c, 0x88, 0x26, 0x97, 0xda, 0x89,
+ 0x3e, 0xa4, 0xda, 0x88, 0x1e, 0x98, 0xda, 0x88,
+ 0x3e, 0x9a, 0xda, 0x88, 0x0e, 0x9c, 0xda, 0x88,
+ 0x2e, 0x9e, 0xda, 0x88, 0x16, 0xa0, 0xda, 0x88,
+ 0x36, 0xa2, 0xda, 0xc3, 0x26, 0x8b, 0x0f, 0x26,
+ 0x8b, 0x57, 0x02, 0x26, 0x8b, 0x77, 0x04, 0x8b,
+ 0xf9, 0x83, 0xc3, 0x06, 0x1e, 0x8e, 0xd8, 0x8b,
+ 0xcf, 0x26, 0x8a, 0x07, 0x3c, 0xff, 0x74, 0x02,
+ 0x88, 0x04, 0x43, 0x46, 0xe2, 0xf3, 0x81, 0xc6,
+ 0x40, 0x01, 0x2b, 0xf7, 0x4a, 0x75, 0xe8, 0x1f,
+ 0xc3, 0x50, 0x32, 0xe4, 0xe8, 0x66, 0x8a, 0x58,
+ 0xc6, 0x47, 0x12, 0x01, 0xc3, 0x50, 0x32, 0xe4,
+ 0xe8, 0x5a, 0x8a, 0x58, 0xc6, 0x47, 0x12, 0x00,
+ 0xc3, 0xb4, 0x00, 0xe8, 0x4f, 0x8a, 0x83, 0xc3,
+ 0x13, 0xfc, 0xac, 0x3c, 0xff, 0x74, 0x05, 0x88,
+ 0x07, 0x43, 0xeb, 0xf6, 0xc3, 0x50, 0x51, 0x52,
+ 0xb4, 0x00, 0xe8, 0x38, 0x8a, 0x5a, 0x59, 0x58,
+ 0x89, 0x4f, 0x09, 0x89, 0x57, 0x0b, 0x89, 0x4f,
+ 0x0d, 0x89, 0x57, 0x0f, 0x88, 0x67, 0x11, 0xc3,
+ 0xe8, 0x04, 0x00, 0xe8, 0xc8, 0xf8, 0xc3, 0x32,
+ 0xe4, 0x50, 0xe8, 0x2f, 0x90, 0x58, 0x50, 0xbe,
+ 0xc7, 0x32, 0xbb, 0x47, 0x33, 0x48, 0xb1, 0x1b,
+ 0xf6, 0xe1, 0x03, 0xf0, 0x06, 0x8b, 0x44, 0x16,
+ 0x8e, 0xc0, 0xba, 0x02, 0x00, 0xbe, 0x00, 0x00,
+ 0x26, 0x8b, 0x34, 0x2b, 0xf2, 0x8b, 0xc6, 0xb1,
+ 0x03, 0xf6, 0xf1, 0x07, 0x8b, 0xd0, 0xb9, 0x01,
+ 0x00, 0x51, 0x52, 0xe8, 0x75, 0x8f, 0x5a, 0x59,
+ 0x58, 0xc3, 0xe8, 0xc2, 0xff, 0xe8, 0x97, 0xf8,
+ 0xc3, 0xe8, 0xeb, 0x00, 0xe8, 0xb1, 0xff, 0xe8,
+ 0x2c, 0x90, 0xc6, 0x06, 0x33, 0x33, 0x01, 0xc6,
+ 0x06, 0xdd, 0x1c, 0x02, 0xc3, 0xc6, 0x06, 0x27,
+ 0xc4, 0x00, 0xe8, 0xd2, 0x00, 0xe8, 0x9f, 0xff,
+ 0xe8, 0xcb, 0xf8, 0xa3, 0x3f, 0x33, 0x0b, 0xc0,
+ 0x74, 0x4d, 0xa1, 0x52, 0x72, 0xa3, 0x50, 0x72,
+ 0xa1, 0x50, 0x72, 0x3b, 0x06, 0x23, 0xc4, 0x75,
+ 0x3e, 0xa1, 0x1f, 0xc4, 0xe8, 0xbd, 0x0d, 0x3b,
+ 0x06, 0x25, 0xc4, 0x75, 0x32, 0xa0, 0xce, 0x00,
+ 0x0a, 0xc0, 0x74, 0x06, 0x3a, 0x06, 0xcf, 0x00,
+ 0x75, 0x25, 0xc6, 0x06, 0x27, 0xc4, 0x01, 0xa1,
+ 0x3f, 0x33, 0x3b, 0x06, 0x3b, 0x33, 0x72, 0x17,
+ 0x3b, 0x06, 0x3d, 0x33, 0x77, 0x11, 0xe8, 0x0e,
+ 0x00, 0xa3, 0x52, 0x72, 0xa3, 0x50, 0x72, 0xa3,
+ 0x1f, 0xc4, 0xa2, 0xcf, 0x00, 0xf9, 0xc3, 0x33,
+ 0xc0, 0xa3, 0x23, 0xc4, 0xa3, 0x25, 0xc4, 0xa3,
+ 0x3b, 0x33, 0xa3, 0x3d, 0x33, 0xf8, 0xc3, 0xe8,
+ 0x65, 0x00, 0xe8, 0x50, 0x8f, 0xe8, 0x64, 0x8f,
+ 0xe8, 0xd8, 0x8e, 0xe8, 0x38, 0x01, 0xc3, 0xe8,
+ 0x55, 0x00, 0xc6, 0x06, 0xdc, 0x64, 0x00, 0xe8,
+ 0xe8, 0xff, 0xc6, 0x06, 0xdc, 0x64, 0x01, 0xc3,
+ 0xe8, 0xdc, 0xff, 0xe8, 0x16, 0x00, 0xc3, 0xe8,
+ 0xd8, 0xff, 0xe8, 0x0f, 0x00, 0xc3, 0xe8, 0xde,
+ 0xff, 0xe8, 0x08, 0x00, 0xc3, 0xe8, 0xda, 0xff,
+ 0xe8, 0x01, 0x00, 0xc3, 0xe8, 0x64, 0x90, 0xe8,
+ 0x6c, 0x8f, 0xe8, 0x44, 0x23, 0xc6, 0x06, 0x33,
+ 0x33, 0x01, 0xc6, 0x06, 0xdd, 0x1c, 0x02, 0xc6,
+ 0x06, 0xdc, 0x1c, 0x02, 0xe8, 0x2f, 0x0d, 0xc6,
+ 0x06, 0x33, 0x33, 0x00, 0xc6, 0x06, 0xdd, 0x1c,
+ 0x03, 0xc6, 0x06, 0xdc, 0x1c, 0x03, 0xc3, 0xc6,
+ 0x06, 0xda, 0x1c, 0x01, 0xc6, 0x06, 0xdb, 0x1c,
+ 0x01, 0xe8, 0x12, 0x0d, 0xc6, 0x06, 0xda, 0x1c,
+ 0x00, 0xc6, 0x06, 0xdb, 0x1c, 0x00, 0xc3, 0xe8,
+ 0xd3, 0x8e, 0xe8, 0xe7, 0x8e, 0xe8, 0x5b, 0x8e,
+ 0xe8, 0x47, 0x24, 0xc6, 0x06, 0x07, 0x66, 0x01,
+ 0xa1, 0x7a, 0x32, 0x3a, 0x06, 0x07, 0x66, 0x75,
+ 0x03, 0xe8, 0xe9, 0x8d, 0xbb, 0xa4, 0x32, 0xe8,
+ 0x64, 0x8d, 0x73, 0xf8, 0x8b, 0x0e, 0x90, 0x32,
+ 0xe8, 0x48, 0x8d, 0xc6, 0x06, 0x33, 0x33, 0x01,
+ 0xc6, 0x06, 0xdd, 0x1c, 0x02, 0xc6, 0x06, 0xdc,
+ 0x1c, 0x02, 0xe8, 0x1f, 0x13, 0xe8, 0xfc, 0x0f,
+ 0xe8, 0x13, 0x0f, 0xe8, 0x4d, 0x13, 0x72, 0x77,
+ 0xe8, 0x40, 0x10, 0xe8, 0xa9, 0x11, 0xa0, 0x07,
+ 0x66, 0xfe, 0xc8, 0x3a, 0x06, 0x35, 0x33, 0x75,
+ 0x12, 0x8b, 0x1e, 0x37, 0x33, 0x8b, 0x36, 0x39,
+ 0x33, 0xe8, 0xfb, 0x86, 0xc6, 0x06, 0xdb, 0x1c,
+ 0x02, 0xeb, 0x0b, 0x3a, 0x06, 0x36, 0x33, 0x75,
+ 0x05, 0xc6, 0x06, 0xdb, 0x1c, 0x01, 0xe8, 0xf5,
+ 0x0e, 0xa1, 0x7a, 0x32, 0x0b, 0xc0, 0x74, 0x1e,
+ 0x40, 0x3a, 0x06, 0x07, 0x66, 0x75, 0x17, 0xa0,
+ 0x49, 0x32, 0xb4, 0x04, 0x8a, 0x2e, 0x7c, 0x32,
+ 0xff, 0x1e, 0x4a, 0x32, 0xb8, 0x3b, 0x0b, 0x8e,
+ 0xd8, 0x8e, 0xc0, 0xe8, 0xa5, 0x8d, 0xe8, 0xff,
+ 0x8a, 0xe8, 0x45, 0x18, 0xe8, 0xf8, 0x11, 0xe8,
+ 0x10, 0x0f, 0xe8, 0xba, 0x89, 0xc6, 0x06, 0x33,
+ 0x33, 0x00, 0xc6, 0x06, 0xdd, 0x1c, 0x03, 0xc6,
+ 0x06, 0xdc, 0x1c, 0x03, 0xe9, 0x51, 0xff, 0xc7,
+ 0x06, 0x7a, 0x32, 0x00, 0x00, 0xc3, 0xe8, 0x7d,
+ 0x90, 0xe8, 0x86, 0x23, 0xc6, 0x06, 0x07, 0x66,
+ 0x01, 0xa1, 0x7a, 0x32, 0x3a, 0x06, 0x07, 0x66,
+ 0x75, 0x03, 0xe8, 0x28, 0x8d, 0xbb, 0xa4, 0x32,
+ 0xe8, 0xa3, 0x8c, 0x73, 0xf8, 0x8b, 0x0e, 0x90,
+ 0x32, 0xe8, 0x87, 0x8c, 0xc6, 0x06, 0x33, 0x33,
+ 0x01, 0xc6, 0x06, 0xdd, 0x1c, 0x02, 0xc6, 0x06,
+ 0xdc, 0x1c, 0x02, 0xe8, 0x5e, 0x12, 0xe8, 0x3b,
+ 0x0f, 0xe8, 0x8f, 0x12, 0x72, 0x48, 0xe8, 0x82,
+ 0x0f, 0xe8, 0xeb, 0x10, 0xa1, 0x7a, 0x32, 0x0b,
+ 0xc0, 0x74, 0x1e, 0x40, 0x3a, 0x06, 0x07, 0x66,
+ 0x75, 0x17, 0xa0, 0x49, 0x32, 0xb4, 0x04, 0x8a,
+ 0x2e, 0x7c, 0x32, 0xff, 0x1e, 0x4a, 0x32, 0xb8,
+ 0x3b, 0x0b, 0x8e, 0xd8, 0x8e, 0xc0, 0xe8, 0x12,
+ 0x8d, 0xe8, 0x6c, 0x8a, 0xe8, 0xb2, 0x17, 0xe8,
+ 0x65, 0x11, 0xe8, 0x2a, 0x89, 0xc6, 0x06, 0x33,
+ 0x33, 0x00, 0xc6, 0x06, 0xdd, 0x1c, 0x03, 0xc6,
+ 0x06, 0xdc, 0x1c, 0x03, 0xeb, 0x83, 0xc7, 0x06,
+ 0x7a, 0x32, 0x00, 0x00, 0xc3, 0xc6, 0x06, 0x27,
+ 0xc4, 0x00, 0xe8, 0x32, 0x89, 0xe8, 0xf2, 0x22,
+ 0xc6, 0x06, 0x07, 0x66, 0x01, 0xa1, 0x7a, 0x32,
+ 0x3a, 0x06, 0x07, 0x66, 0x75, 0x03, 0xe8, 0x94,
+ 0x8c, 0xc6, 0x06, 0xdd, 0x1c, 0x03, 0xc6, 0x06,
+ 0xdc, 0x1c, 0x03, 0xc6, 0x06, 0xda, 0x1c, 0x01,
+ 0xe8, 0xe0, 0x0b, 0x3d, 0x01, 0x00, 0x76, 0x05,
+ 0xc6, 0x06, 0xda, 0x1c, 0x02, 0xe8, 0xcc, 0x11,
+ 0xe8, 0xa9, 0x0e, 0xe8, 0xff, 0x0c, 0xe8, 0x5e,
+ 0x10, 0xe8, 0x11, 0x0d, 0xe8, 0x01, 0x8a, 0xe8,
+ 0x47, 0x17, 0xe8, 0xfa, 0x10, 0xe8, 0x48, 0x0d,
+ 0xe8, 0xbc, 0x88, 0xa0, 0x07, 0x66, 0x32, 0xe4,
+ 0xe8, 0xb0, 0x89, 0xc6, 0x06, 0xcf, 0x00, 0x04,
+ 0x73, 0x03, 0xe9, 0x8f, 0x00, 0xe8, 0x74, 0x89,
+ 0xc6, 0x06, 0xcf, 0x00, 0x02, 0x73, 0x03, 0xe9,
+ 0x82, 0x00, 0x33, 0xc0, 0xa2, 0xcf, 0x00, 0xbb,
+ 0xa4, 0x32, 0xe8, 0xb1, 0x8b, 0x73, 0x9a, 0x50,
+ 0x8b, 0x0e, 0x90, 0x32, 0xe8, 0x94, 0x8b, 0xc6,
+ 0x06, 0x33, 0x33, 0x01, 0xc6, 0x06, 0xdd, 0x1c,
+ 0x02, 0xc6, 0x06, 0xdc, 0x1c, 0x02, 0xe8, 0x6b,
+ 0x11, 0xe8, 0x48, 0x0e, 0xe8, 0x9e, 0x0c, 0xe8,
+ 0x99, 0x11, 0x58, 0x72, 0x4f, 0xe8, 0x8b, 0x0e,
+ 0xe8, 0xf4, 0x0f, 0xe8, 0xa7, 0x0c, 0xa1, 0x7a,
+ 0x32, 0x0b, 0xc0, 0x74, 0x1e, 0x40, 0x3a, 0x06,
+ 0x07, 0x66, 0x75, 0x17, 0xa0, 0x49, 0x32, 0xb4,
+ 0x04, 0x8a, 0x2e, 0x7c, 0x32, 0xff, 0x1e, 0x4a,
+ 0x32, 0xb8, 0x3b, 0x0b, 0x8e, 0xd8, 0x8e, 0xc0,
+ 0xe8, 0x18, 0x8c, 0xe8, 0x72, 0x89, 0xe8, 0xb8,
+ 0x16, 0xe8, 0x6b, 0x10, 0xe8, 0xb9, 0x0c, 0xe8,
+ 0x2d, 0x88, 0xc6, 0x06, 0x33, 0x33, 0x00, 0xc6,
+ 0x06, 0xdd, 0x1c, 0x03, 0xc6, 0x06, 0xdc, 0x1c,
+ 0x03, 0xe9, 0x19, 0xff, 0x50, 0xc6, 0x06, 0xda,
+ 0x1c, 0x01, 0xe8, 0x40, 0x0c, 0xe8, 0x55, 0x0c,
+ 0xe8, 0x45, 0x89, 0xe8, 0x92, 0x0c, 0xe8, 0x06,
+ 0x88, 0xe8, 0x09, 0x88, 0x58, 0x8b, 0x0e, 0x52,
+ 0x72, 0x8b, 0x16, 0x3d, 0x33, 0x51, 0x52, 0xe8,
+ 0xa9, 0xfc, 0x72, 0x07, 0xe8, 0x5a, 0xfe, 0x5a,
+ 0x59, 0xf8, 0xc3, 0x89, 0x16, 0x3d, 0x33, 0xa1,
+ 0x7a, 0x32, 0x3a, 0x06, 0x07, 0x66, 0x75, 0x03,
+ 0xe8, 0x7a, 0x8b, 0xbb, 0xa4, 0x32, 0xe8, 0xf5,
+ 0x8a, 0x73, 0xf8, 0x8b, 0x0e, 0x90, 0x32, 0xe8,
+ 0xd9, 0x8a, 0xc6, 0x06, 0x33, 0x33, 0x01, 0xc6,
+ 0x06, 0xdd, 0x1c, 0x02, 0xc6, 0x06, 0xdc, 0x1c,
+ 0x02, 0xe8, 0xb0, 0x10, 0xe8, 0x8d, 0x0d, 0xe8,
+ 0xe1, 0x10, 0x72, 0x54, 0xa0, 0x07, 0x66, 0x32,
+ 0xe4, 0x3b, 0x06, 0x3d, 0x33, 0x73, 0x49, 0xe8,
+ 0xc9, 0x0d, 0xe8, 0x32, 0x0f, 0xa1, 0x7a, 0x32,
+ 0x0b, 0xc0, 0x74, 0x1e, 0x40, 0x3a, 0x06, 0x07,
+ 0x66, 0x75, 0x17, 0xa0, 0x49, 0x32, 0xb4, 0x04,
+ 0x8a, 0x2e, 0x7c, 0x32, 0xff, 0x1e, 0x4a, 0x32,
+ 0xb8, 0x3b, 0x0b, 0x8e, 0xd8, 0x8e, 0xc0, 0xe8,
+ 0x59, 0x8b, 0xe8, 0xb3, 0x88, 0xe8, 0xf9, 0x15,
+ 0xe8, 0xac, 0x0f, 0xe8, 0x71, 0x87, 0xc6, 0x06,
+ 0x33, 0x33, 0x00, 0xc6, 0x06, 0xdd, 0x1c, 0x03,
+ 0xc6, 0x06, 0xdc, 0x1c, 0x03, 0xe9, 0x77, 0xff,
+ 0x33, 0xc0, 0xa3, 0x7a, 0x32, 0xa3, 0x3d, 0x33,
+ 0x5a, 0x59, 0xf9, 0xc3, 0xb9, 0xe8, 0x03, 0xbb,
+ 0xac, 0x32, 0xe8, 0x56, 0x8a, 0xc7, 0x06, 0x52,
+ 0x72, 0x00, 0x00, 0xc7, 0x06, 0x50, 0x72, 0x00,
+ 0x00, 0xc7, 0x06, 0x1f, 0xc4, 0x00, 0x00, 0xe8,
+ 0x5d, 0x87, 0xe8, 0x7a, 0x01, 0x73, 0x09, 0xb9,
+ 0xe8, 0x03, 0xbb, 0xac, 0x32, 0xe8, 0x33, 0x8a,
+ 0xe8, 0xd2, 0x0c, 0xe8, 0xf0, 0x09, 0x33, 0xc0,
+ 0xa2, 0xcf, 0x00, 0xbb, 0xac, 0x32, 0xe8, 0x35,
+ 0x8a, 0x72, 0x1c, 0xe8, 0x0d, 0x88, 0xc6, 0x06,
+ 0xcf, 0x00, 0x04, 0x72, 0x0a, 0xe8, 0xd4, 0x87,
+ 0xc6, 0x06, 0xcf, 0x00, 0x02, 0x73, 0xcb, 0xe8,
+ 0x03, 0x87, 0xe8, 0x7a, 0xfc, 0xf9, 0xc3, 0xe8,
+ 0xfb, 0x86, 0xe8, 0x72, 0xfc, 0xf8, 0xc3, 0x0b,
+ 0xc0, 0x75, 0x01, 0xc3, 0x33, 0xdb, 0x8a, 0xd8,
+ 0x43, 0xbf, 0xc7, 0x32, 0xb0, 0x1b, 0xfe, 0xcc,
+ 0xf6, 0xe4, 0x03, 0xf8, 0x53, 0x57, 0x8b, 0x05,
+ 0x3b, 0xc3, 0x74, 0x07, 0xe8, 0x7e, 0x0c, 0x5f,
+ 0x5b, 0xeb, 0xf1, 0x5f, 0x5b, 0xc3, 0x0b, 0xc0,
+ 0x75, 0x01, 0xc3, 0x0a, 0xc0, 0x75, 0x01, 0xc3,
+ 0x33, 0xdb, 0x8a, 0xd8, 0xbf, 0xc7, 0x32, 0xb0,
+ 0x1b, 0xfe, 0xcc, 0xf6, 0xe4, 0x03, 0xf8, 0x53,
+ 0x57, 0x8a, 0x45, 0x1a, 0x3a, 0xc3, 0x74, 0x07,
+ 0xe8, 0x52, 0x0c, 0x5f, 0x5b, 0xeb, 0xf0, 0x5f,
+ 0x5b, 0xc3, 0xbb, 0xa8, 0x32, 0x8b, 0xc8, 0xe8,
+ 0xa1, 0x89, 0xe8, 0x40, 0x0c, 0xbb, 0xa8, 0x32,
+ 0xe8, 0xab, 0x89, 0x73, 0xf5, 0xc3, 0xb8, 0x32,
+ 0x00, 0xe8, 0xe6, 0xff, 0xc3, 0xb8, 0x64, 0x00,
+ 0xe8, 0xdf, 0xff, 0xc3, 0xbb, 0xa8, 0x32, 0x8b,
+ 0xc8, 0xe8, 0x7f, 0x89, 0xbb, 0xa8, 0x32, 0xe8,
+ 0x8c, 0x89, 0x73, 0xf8, 0xc3, 0x53, 0xb8, 0x10,
+ 0x00, 0xe8, 0xe8, 0xff, 0x5b, 0xc3, 0xa0, 0xe1,
+ 0xc3, 0x0a, 0xc0, 0x74, 0x14, 0xbb, 0x6f, 0xbb,
+ 0x83, 0xc3, 0x03, 0x8a, 0x27, 0x3a, 0xc4, 0x75,
+ 0xf7, 0x8b, 0x47, 0x01, 0xa3, 0xdc, 0xbb, 0xeb,
+ 0x1d, 0x80, 0x3e, 0x3d, 0x66, 0x06, 0x74, 0x01,
+ 0xc3, 0x80, 0x3e, 0xdb, 0xbb, 0x01, 0x74, 0x0e,
+ 0xbb, 0x57, 0x34, 0xe8, 0xaf, 0x80, 0xc7, 0x06,
+ 0x1f, 0xc4, 0x00, 0x00, 0xeb, 0x10, 0xe8, 0x2c,
+ 0x86, 0xc7, 0x06, 0x1f, 0xc4, 0x00, 0x00, 0xff,
+ 0x16, 0xdc, 0xbb, 0xe8, 0x41, 0x86, 0xc6, 0x06,
+ 0x3d, 0x66, 0x00, 0x33, 0xc0, 0xa3, 0x50, 0x72,
+ 0xa3, 0x52, 0x72, 0xa2, 0xe1, 0xc3, 0xe8, 0x7f,
+ 0x15, 0xc3, 0xc6, 0x06, 0xdb, 0xbb, 0x00, 0xbb,
+ 0x87, 0xbb, 0xe8, 0xfd, 0x1f, 0x8a, 0x07, 0x0a,
+ 0xc0, 0x74, 0x31, 0x8a, 0xc8, 0xa1, 0x1f, 0xc4,
+ 0xe8, 0x79, 0x08, 0x3a, 0xc1, 0x75, 0x26, 0x8a,
+ 0x67, 0x01, 0x3a, 0x26, 0x50, 0x72, 0x75, 0x1d,
+ 0xc6, 0x06, 0xdb, 0xbb, 0x01, 0x8b, 0x77, 0x03,
+ 0x8b, 0x7f, 0x05, 0x8a, 0x47, 0x02, 0xa2, 0xc3,
+ 0x64, 0x8b, 0x47, 0x07, 0xa3, 0xdc, 0xbb, 0xe8,
+ 0xc8, 0x1b, 0x72, 0x06, 0xc3, 0x83, 0xc3, 0x09,
+ 0xeb, 0xc3, 0xb0, 0x36, 0xe9, 0x49, 0x93, 0x83,
+ 0x3e, 0xc2, 0x00, 0x00, 0x74, 0x05, 0xe8, 0x21,
+ 0x00, 0xf8, 0xc3, 0xbb, 0x98, 0x32, 0x8b, 0x07,
+ 0x0b, 0x47, 0x02, 0x75, 0x06, 0xb9, 0x32, 0x00,
+ 0xe8, 0xa8, 0x88, 0xe8, 0xb8, 0x88, 0x72, 0x02,
+ 0xf8, 0xc3, 0xe8, 0x05, 0x00, 0xe8, 0x66, 0x00,
+ 0xf9, 0xc3, 0xbb, 0x98, 0x32, 0x33, 0xc0, 0x89,
+ 0x07, 0x89, 0x47, 0x02, 0xc3, 0xb8, 0x11, 0x00,
+ 0xba, 0x0c, 0x00, 0x8b, 0x1e, 0xc0, 0x00, 0x8b,
+ 0x0e, 0xc2, 0x00, 0x3b, 0xd8, 0x72, 0x1d, 0x3b,
+ 0xca, 0x72, 0x19, 0x05, 0x1e, 0x01, 0x81, 0xc2,
+ 0x8d, 0x00, 0x3b, 0xd8, 0x77, 0x0e, 0x3b, 0xca,
+ 0x77, 0x0a, 0xc6, 0x06, 0x6e, 0xc4, 0x01, 0xe8,
+ 0xc8, 0xff, 0xf8, 0xc3, 0xbb, 0x6e, 0xc4, 0x80,
+ 0x3f, 0x01, 0x74, 0x05, 0xc6, 0x07, 0x00, 0xf8,
+ 0xc3, 0xbb, 0x98, 0x32, 0x8b, 0x07, 0x0b, 0x47,
+ 0x02, 0xe8, 0xae, 0xff, 0xc6, 0x06, 0x6e, 0xc4,
+ 0x00, 0xf9, 0xc3, 0xb9, 0x19, 0x00, 0xbb, 0x98,
+ 0x32, 0xe8, 0x37, 0x88, 0xf8, 0xc3, 0xc6, 0x06,
+ 0xe1, 0xc3, 0x00, 0xc6, 0x06, 0xda, 0x1c, 0x01,
+ 0xe8, 0x4a, 0x09, 0xe8, 0x2d, 0x09, 0xe8, 0x79,
+ 0x00, 0xbf, 0x75, 0xc4, 0xb0, 0x01, 0xb9, 0x18,
+ 0x00, 0xfc, 0xf3, 0xaa, 0xa1, 0xbf, 0x32, 0xa3,
+ 0xac, 0x00, 0x33, 0xc0, 0xa3, 0xaa, 0x00, 0xb9,
+ 0x04, 0x00, 0xba, 0x54, 0x00, 0xe8, 0x90, 0x8e,
+ 0xe8, 0x9c, 0x00, 0xe8, 0x45, 0x02, 0xe8, 0xf4,
+ 0x84, 0xe8, 0xbc, 0x8a, 0xe8, 0xa4, 0x8a, 0xe8,
+ 0x13, 0x00, 0xe8, 0x1b, 0x86, 0xe8, 0x9a, 0x00,
+ 0xe8, 0x6f, 0x00, 0xe8, 0x01, 0x85, 0xc7, 0x06,
+ 0x52, 0x72, 0x00, 0x00, 0xc3, 0xe8, 0x9f, 0x87,
+ 0x80, 0x3e, 0xb0, 0x32, 0x01, 0x74, 0x05, 0xc6,
+ 0x06, 0xdc, 0x1c, 0x03, 0xc6, 0x06, 0xda, 0x1c,
+ 0x01, 0x83, 0x3e, 0x1f, 0xc4, 0x00, 0x74, 0x05,
+ 0xc6, 0x06, 0xda, 0x1c, 0x02, 0xe8, 0x4e, 0x07,
+ 0xc6, 0x06, 0xda, 0x1c, 0x00, 0x83, 0x3e, 0x1f,
+ 0xc4, 0x00, 0x74, 0x05, 0xc6, 0x06, 0xda, 0x1c,
+ 0x03, 0xc3, 0xc6, 0x06, 0x3d, 0x66, 0x00, 0xc7,
+ 0x06, 0x1f, 0xc4, 0x00, 0x00, 0xc6, 0x06, 0xc3,
+ 0x64, 0x00, 0xe8, 0x75, 0x1e, 0x80, 0x3e, 0xb0,
+ 0x32, 0x01, 0x74, 0x15, 0xe8, 0x22, 0x1d, 0xc6,
+ 0x06, 0xdc, 0x1c, 0x02, 0xc6, 0x06, 0xda, 0x1c,
+ 0x01, 0xe8, 0x12, 0x07, 0xc6, 0x06, 0xdc, 0x1c,
+ 0x03, 0xc3, 0x06, 0x1e, 0xb8, 0x00, 0xa0, 0x8e,
+ 0xc0, 0xa1, 0xb1, 0x32, 0x8e, 0xd8, 0xfc, 0xf3,
+ 0xa5, 0x1f, 0xe8, 0x5a, 0x84, 0x07, 0xc3, 0xe8,
+ 0x13, 0x01, 0xe8, 0x4c, 0x00, 0xe8, 0x2f, 0x01,
+ 0xe8, 0x07, 0x00, 0xe8, 0x82, 0x85, 0xe8, 0xd9,
+ 0xff, 0xc3, 0xb8, 0x0c, 0x00, 0xbb, 0x40, 0x01,
+ 0xf7, 0xe3, 0x8b, 0xf0, 0x8b, 0xf8, 0xb8, 0x0c,
+ 0x00, 0x05, 0x8d, 0x00, 0xf7, 0xe3, 0x2b, 0xc6,
+ 0x8b, 0xc8, 0xd1, 0xe9, 0xc3, 0xe8, 0x60, 0x85,
+ 0xe8, 0x2a, 0x84, 0xe8, 0xdc, 0xff, 0xe8, 0xb1,
+ 0xff, 0xe8, 0x43, 0x84, 0xc7, 0x06, 0x52, 0x72,
+ 0x00, 0x00, 0xbf, 0x75, 0xc4, 0xb0, 0x01, 0xb9,
+ 0x18, 0x00, 0xfc, 0xf3, 0xaa, 0xe8, 0xaf, 0xff,
+ 0xc3, 0x06, 0xa1, 0xb1, 0x32, 0x8e, 0xc0, 0x33,
+ 0xc9, 0x3b, 0x0e, 0x73, 0xc4, 0x73, 0x20, 0x41,
+ 0x51, 0xe8, 0x1d, 0x00, 0x89, 0x36, 0x71, 0xc4,
+ 0xb9, 0x1a, 0x00, 0xba, 0x28, 0x00, 0xe8, 0x4f,
+ 0x00, 0xb4, 0xea, 0xe8, 0x37, 0x02, 0xc7, 0x06,
+ 0x71, 0xc4, 0x00, 0x00, 0x59, 0xeb, 0xda, 0x07,
+ 0xc3, 0x33, 0xd2, 0x49, 0xfe, 0xce, 0xfe, 0xc6,
+ 0x83, 0xe9, 0x06, 0x73, 0xf9, 0x83, 0xc1, 0x06,
+ 0xbe, 0x11, 0x0f, 0x81, 0xc6, 0x45, 0x06, 0x81,
+ 0xc6, 0x45, 0x06, 0x33, 0xc0, 0x0a, 0xf6, 0x74,
+ 0x0a, 0x05, 0x1a, 0x00, 0x05, 0x05, 0x00, 0xfe,
+ 0xce, 0xeb, 0xf2, 0xf7, 0x26, 0xb6, 0x00, 0x03,
+ 0xf0, 0x0a, 0xc9, 0x74, 0x0a, 0x83, 0xc6, 0x28,
+ 0x83, 0xc6, 0x05, 0xfe, 0xc9, 0xeb, 0xf2, 0xc3,
+ 0x1e, 0x52, 0xbb, 0x40, 0x01, 0xa1, 0xb5, 0x32,
+ 0x8e, 0xd8, 0x8b, 0xc6, 0x2d, 0x11, 0x0f, 0x33,
+ 0xd2, 0xf7, 0xf3, 0x8b, 0xfa, 0x83, 0xc7, 0x06,
+ 0xbb, 0x1e, 0x01, 0xf7, 0xe3, 0x03, 0xf8, 0x5a,
+ 0x81, 0xc6, 0x41, 0x01, 0x81, 0xc7, 0x1f, 0x01,
+ 0x49, 0x49, 0x4a, 0x4a, 0x8b, 0xd9, 0x8b, 0xca,
+ 0x8a, 0x05, 0x3c, 0xe8, 0x75, 0x06, 0x26, 0xc6,
+ 0x04, 0xd6, 0xeb, 0x04, 0x26, 0xc6, 0x04, 0xe0,
+ 0x46, 0x47, 0xe2, 0xec, 0x81, 0xc6, 0x40, 0x01,
+ 0x2b, 0xf2, 0x81, 0xc7, 0x1e, 0x01, 0x2b, 0xfa,
+ 0x4b, 0x75, 0xdb, 0x1f, 0xc3, 0x06, 0xa1, 0xb5,
+ 0x32, 0x8e, 0xc0, 0xa3, 0xac, 0x00, 0xc7, 0x06,
+ 0xaa, 0x00, 0x00, 0x00, 0xb9, 0x03, 0x00, 0xba,
+ 0x54, 0x00, 0xe8, 0xc3, 0x8c, 0xa1, 0xb1, 0x32,
+ 0x33, 0xdb, 0xe8, 0xf7, 0xf6, 0x07, 0xc3, 0x06,
+ 0xa1, 0xbf, 0x32, 0x8e, 0xc0, 0x33, 0xc9, 0x3b,
+ 0x0e, 0x73, 0xc4, 0x73, 0x45, 0x41, 0x51, 0xbb,
+ 0x8c, 0xc4, 0x03, 0xd9, 0x33, 0xc9, 0x8a, 0x0f,
+ 0xbf, 0xfe, 0xff, 0xbe, 0xa4, 0xc4, 0xd1, 0xe1,
+ 0x03, 0xf9, 0x03, 0xf1, 0xd1, 0xe9, 0x8b, 0x34,
+ 0x47, 0x26, 0x8b, 0x3d, 0x80, 0x7c, 0x01, 0x00,
+ 0x74, 0x04, 0x26, 0x03, 0x7d, 0x01, 0x59, 0x51,
+ 0xe8, 0x0e, 0xff, 0x26, 0x8b, 0x0d, 0x26, 0x8b,
+ 0x55, 0x02, 0x26, 0x03, 0x75, 0x04, 0x83, 0xc7,
+ 0x06, 0xa1, 0xb1, 0x32, 0xe8, 0x05, 0x00, 0x59,
+ 0xeb, 0xb5, 0x07, 0xc3, 0x1e, 0x8e, 0xd8, 0x8b,
+ 0xd9, 0x8b, 0xcb, 0x26, 0x8a, 0x05, 0x3c, 0xff,
+ 0x74, 0x02, 0x88, 0x04, 0x47, 0x46, 0xe2, 0xf3,
+ 0x81, 0xc6, 0x40, 0x01, 0x2b, 0xf3, 0x4a, 0x75,
+ 0xe8, 0x1f, 0xc3, 0xbb, 0xa0, 0x32, 0xb9, 0x0b,
+ 0x00, 0xe8, 0xaf, 0x85, 0xe8, 0x91, 0x00, 0xe8,
+ 0x20, 0x02, 0xe8, 0x18, 0xfd, 0x72, 0x5b, 0xe8,
+ 0x91, 0x83, 0x72, 0x35, 0xe8, 0x5d, 0x83, 0x73,
+ 0xeb, 0xe8, 0x4f, 0x00, 0x72, 0xe6, 0x83, 0x3e,
+ 0x1f, 0xc4, 0x00, 0x74, 0x14, 0xa1, 0x6f, 0xc4,
+ 0x3b, 0x06, 0x1f, 0xc4, 0x74, 0xd6, 0xa3, 0x21,
+ 0xc4, 0xe8, 0x80, 0x04, 0xe8, 0x45, 0x00, 0xeb,
+ 0xcb, 0xa1, 0x6f, 0xc4, 0xa3, 0x1f, 0xc4, 0xe8,
+ 0x20, 0x04, 0x72, 0x26, 0xe8, 0x27, 0x01, 0xeb,
+ 0xbb, 0xe8, 0x1f, 0x00, 0x72, 0xb6, 0x83, 0x3e,
+ 0x1f, 0xc4, 0x00, 0x75, 0xd0, 0xe8, 0x3f, 0x04,
+ 0x72, 0x10, 0xe8, 0xb9, 0x02, 0xb4, 0xea, 0xe8,
+ 0x9b, 0x00, 0xc7, 0x06, 0x6f, 0xc4, 0x00, 0x00,
+ 0xeb, 0x9a, 0xc3, 0x83, 0x3e, 0x6f, 0xc4, 0x00,
+ 0x74, 0x02, 0xf8, 0xc3, 0xe8, 0x05, 0x00, 0xe8,
+ 0xe9, 0x06, 0xf9, 0xc3, 0x33, 0xc0, 0xa3, 0x6f,
+ 0xc4, 0xa3, 0x1f, 0xc4, 0xa3, 0x21, 0xc4, 0xc3,
+ 0xbb, 0xe2, 0xc3, 0xe8, 0x01, 0x00, 0xc3, 0x53,
+ 0xe8, 0x7e, 0x07, 0x5b, 0xe8, 0x93, 0x02, 0xc3,
+ 0x33, 0xc9, 0x3b, 0x0e, 0x73, 0xc4, 0x73, 0x13,
+ 0x41, 0x51, 0xe8, 0x2c, 0xfe, 0xbb, 0x1a, 0x00,
+ 0xb9, 0x28, 0x00, 0xe8, 0x98, 0x00, 0x59, 0x72,
+ 0x2b, 0xeb, 0xe7, 0x8b, 0x0e, 0x6f, 0xc4, 0x0b,
+ 0xc9, 0x74, 0x20, 0xb4, 0xea, 0xe8, 0x3d, 0x00,
+ 0xc7, 0x06, 0x6f, 0xc4, 0x00, 0x00, 0xc7, 0x06,
+ 0x71, 0xc4, 0x00, 0x00, 0x83, 0x3e, 0x1f, 0xc4,
+ 0x00, 0x74, 0x05, 0xe8, 0x98, 0x00, 0xeb, 0x03,
+ 0xe8, 0x88, 0x06, 0xc3, 0x3b, 0x0e, 0x6f, 0xc4,
+ 0x75, 0x01, 0xc3, 0x51, 0x56, 0xb4, 0xea, 0xe8,
+ 0x13, 0x00, 0x5e, 0x59, 0x89, 0x0e, 0x6f, 0xc4,
+ 0x89, 0x36, 0x71, 0xc4, 0xb4, 0xe9, 0xe8, 0x04,
+ 0x00, 0xe8, 0x72, 0x00, 0xc3, 0x8b, 0x0e, 0xb1,
+ 0x32, 0x50, 0xe8, 0x0b, 0x00, 0x58, 0xb9, 0x00,
+ 0xa0, 0xe8, 0x04, 0x00, 0xe8, 0x98, 0x81, 0xc3,
+ 0x06, 0x8e, 0xc1, 0x8b, 0x36, 0x71, 0xc4, 0x0b,
+ 0xf6, 0x74, 0x29, 0xb9, 0x28, 0x00, 0x26, 0x88,
+ 0x24, 0x46, 0xe2, 0xfa, 0x81, 0xc6, 0x40, 0x01,
+ 0x83, 0xee, 0x28, 0xb9, 0x18, 0x00, 0x26, 0x88,
+ 0x24, 0x26, 0x88, 0x64, 0x27, 0x81, 0xc6, 0x40,
+ 0x01, 0xe2, 0xf3, 0xb9, 0x28, 0x00, 0x26, 0x88,
+ 0x24, 0x46, 0xe2, 0xfa, 0x07, 0xc3, 0x8b, 0xc6,
+ 0x33, 0xd2, 0xf7, 0x36, 0xb6, 0x00, 0x3b, 0x06,
+ 0xc2, 0x00, 0x77, 0x18, 0x3b, 0x16, 0xc0, 0x00,
+ 0x77, 0x12, 0x03, 0xc3, 0x3b, 0x06, 0xc2, 0x00,
+ 0x76, 0x0a, 0x03, 0xd1, 0x3b, 0x16, 0xc0, 0x00,
+ 0x76, 0x02, 0xf9, 0xc3, 0xf8, 0xc3, 0xe8, 0xf2,
+ 0x05, 0xe8, 0x47, 0x05, 0xe8, 0x48, 0x00, 0xbb,
+ 0x28, 0xc4, 0xbe, 0xe8, 0x1c, 0x81, 0xc6, 0x85,
+ 0x02, 0x56, 0xc6, 0x06, 0xe6, 0x1c, 0xd1, 0xe8,
+ 0x9b, 0x7f, 0x8b, 0xc6, 0x5e, 0x2b, 0xc6, 0xbe,
+ 0x05, 0x00, 0x03, 0xc6, 0x03, 0xc6, 0x40, 0x0c,
+ 0x01, 0x3d, 0x40, 0x01, 0x76, 0x03, 0xb8, 0x40,
+ 0x01, 0xa3, 0xe0, 0x1c, 0xb9, 0x40, 0x01, 0x2b,
+ 0xc8, 0xd1, 0xe9, 0xb8, 0xb4, 0x00, 0xbb, 0x40,
+ 0x01, 0xf7, 0xe3, 0x03, 0xc1, 0xa3, 0xde, 0x1c,
+ 0xb8, 0x00, 0xa0, 0xe8, 0x3f, 0x05, 0xc3, 0xbf,
+ 0x28, 0xc4, 0xb9, 0x46, 0x00, 0x32, 0xc0, 0xfc,
+ 0xf3, 0xaa, 0x8b, 0x0e, 0x6f, 0xc4, 0x0b, 0xc9,
+ 0x74, 0x06, 0xe8, 0x44, 0x00, 0x83, 0xc3, 0x02,
+ 0xbe, 0x28, 0xc4, 0x8b, 0x0e, 0x1f, 0xc4, 0x0b,
+ 0xc9, 0x74, 0x2b, 0x53, 0xe8, 0x32, 0x00, 0x83,
+ 0xc3, 0x02, 0xe8, 0x21, 0x00, 0x4e, 0xb0, 0x20,
+ 0xb4, 0x26, 0x88, 0x04, 0x88, 0x64, 0x01, 0x88,
+ 0x44, 0x02, 0x83, 0xc6, 0x03, 0x5b, 0xa1, 0x1f,
+ 0xc4, 0x8b, 0x0e, 0x6f, 0xc4, 0x0b, 0xc9, 0x74,
+ 0x04, 0x3b, 0xc1, 0x75, 0x01, 0xc3, 0x8a, 0x07,
+ 0x88, 0x04, 0x43, 0x46, 0x0a, 0xc0, 0x75, 0xf6,
+ 0xc3, 0xbb, 0x8c, 0xc4, 0x03, 0xd9, 0x8a, 0x0f,
+ 0xbb, 0xa4, 0xc4, 0xd1, 0xe1, 0x03, 0xd9, 0x8b,
+ 0x1f, 0xc3, 0xbb, 0xa0, 0x32, 0xe8, 0x96, 0x83,
+ 0x72, 0x01, 0xc3, 0xb9, 0x0b, 0x00, 0xe8, 0x7a,
+ 0x83, 0x06, 0xa1, 0xbf, 0x32, 0x8e, 0xc0, 0x33,
+ 0xc9, 0x3b, 0x0e, 0x73, 0xc4, 0x73, 0x6d, 0x41,
+ 0x51, 0xbb, 0x8c, 0xc4, 0x03, 0xd9, 0x8a, 0x07,
+ 0xbb, 0x74, 0xc4, 0x03, 0xd9, 0x33, 0xc9, 0x8a,
+ 0xc8, 0xbf, 0xfe, 0xff, 0xbe, 0xa4, 0xc4, 0xd1,
+ 0xe1, 0x03, 0xf9, 0x03, 0xf1, 0x8b, 0x34, 0x47,
+ 0x26, 0x8b, 0x3d, 0x80, 0x7c, 0x01, 0x00, 0x74,
+ 0x40, 0x33, 0xc9, 0x8a, 0x0f, 0xfe, 0xc1, 0x26,
+ 0x3a, 0x0d, 0x76, 0x02, 0xb1, 0x01, 0x88, 0x0f,
+ 0x49, 0xd1, 0xe1, 0x03, 0xf9, 0x26, 0x03, 0x7d,
+ 0x01, 0x2b, 0xf9, 0x59, 0x51, 0xe8, 0x41, 0xfc,
+ 0xe8, 0x23, 0x00, 0x56, 0x26, 0x8b, 0x0d, 0x26,
+ 0x8b, 0x55, 0x02, 0x26, 0x03, 0x75, 0x04, 0x83,
+ 0xc7, 0x06, 0xa1, 0xb1, 0x32, 0xe8, 0x34, 0xfd,
+ 0x5e, 0x56, 0xe8, 0x1e, 0x00, 0x5e, 0xe8, 0x44,
+ 0x00, 0x59, 0xeb, 0x8d, 0x07, 0xc3, 0x57, 0x56,
+ 0x06, 0xa1, 0xb1, 0x32, 0x8e, 0xc0, 0xb9, 0x1a,
+ 0x00, 0xba, 0x28, 0x00, 0xe8, 0x49, 0xfc, 0x07,
+ 0x5e, 0x5f, 0xc3, 0x1e, 0x06, 0x81, 0xc6, 0x41,
+ 0x01, 0x8b, 0xfe, 0xb8, 0x00, 0xa0, 0x8e, 0xc0,
+ 0xa1, 0xb1, 0x32, 0x8e, 0xd8, 0xfc, 0xb9, 0x18,
+ 0x00, 0x51, 0xb9, 0x26, 0x00, 0xf3, 0xa4, 0x81,
+ 0xc6, 0x1a, 0x01, 0x81, 0xc7, 0x1a, 0x01, 0x59,
+ 0xe2, 0xef, 0x07, 0x1f, 0xc3, 0xbb, 0x1a, 0x00,
+ 0xb9, 0x28, 0x00, 0xb8, 0x0c, 0x00, 0x03, 0xd8,
+ 0xf7, 0x26, 0xb6, 0x00, 0x2b, 0xf0, 0xb8, 0x08,
+ 0x00, 0x2b, 0xf0, 0x03, 0xc8, 0xe8, 0x36, 0xfe,
+ 0x73, 0x03, 0xe8, 0x92, 0x7f, 0xc3, 0xe8, 0xf8,
+ 0x04, 0x8b, 0x0e, 0x6f, 0xc4, 0xe8, 0xf9, 0xfe,
+ 0x83, 0xc3, 0x02, 0x43, 0x80, 0x3f, 0x00, 0x75,
+ 0xfa, 0x43, 0x06, 0xb8, 0xd4, 0x19, 0x8e, 0xc0,
+ 0x33, 0xc0, 0x26, 0xa3, 0x0c, 0x00, 0x26, 0xa3,
+ 0x0a, 0x00, 0xbe, 0x04, 0x00, 0x53, 0xe8, 0x37,
+ 0x7e, 0x26, 0x01, 0x0e, 0x0c, 0x00, 0x26, 0x89,
+ 0x04, 0x26, 0xff, 0x06, 0x0a, 0x00, 0x83, 0xc6,
+ 0x02, 0x43, 0x8a, 0x07, 0x0a, 0xc0, 0x75, 0xe6,
+ 0x5b, 0x8b, 0xce, 0x33, 0xc0, 0x83, 0xee, 0x02,
+ 0x81, 0xfe, 0x04, 0x00, 0x72, 0x0b, 0x26, 0x8b,
+ 0x14, 0x3b, 0xc2, 0x73, 0xf0, 0x8b, 0xc2, 0xeb,
+ 0xec, 0x8b, 0xf1, 0xb9, 0x40, 0x01, 0x2b, 0xc8,
+ 0xd1, 0xe9, 0x81, 0xc1, 0xc0, 0xcb, 0x26, 0x89,
+ 0x0e, 0x00, 0x00, 0x83, 0xee, 0x02, 0x81, 0xfe,
+ 0x04, 0x00, 0x72, 0x0e, 0x26, 0x8b, 0x14, 0x8b,
+ 0xc8, 0x2b, 0xca, 0xd1, 0xe9, 0x26, 0x89, 0x0c,
+ 0xeb, 0xe9, 0xbf, 0x04, 0x00, 0xbe, 0x0e, 0x00,
+ 0x57, 0x56, 0x26, 0x03, 0x35, 0xc6, 0x06, 0xe6,
+ 0x1c, 0xd1, 0xe8, 0x78, 0x7d, 0x5e, 0x5f, 0x81,
+ 0xc6, 0xc0, 0x0d, 0x83, 0xc7, 0x02, 0x43, 0x8a,
+ 0x07, 0x0a, 0xc0, 0x75, 0xe3, 0xe8, 0xed, 0x7e,
+ 0xe8, 0x1d, 0x80, 0xe8, 0x9d, 0x03, 0xb8, 0x00,
+ 0xa0, 0xe8, 0xf2, 0x03, 0xbb, 0x92, 0x32, 0xa1,
+ 0x96, 0x32, 0x26, 0x8b, 0x0e, 0x0c, 0x00, 0xf7,
+ 0xe1, 0x8b, 0xc8, 0xc1, 0xe9, 0x03, 0x83, 0xc1,
+ 0x3c, 0xe8, 0xcf, 0x81, 0xe8, 0x43, 0xfe, 0x80,
+ 0x3e, 0x96, 0x32, 0x00, 0x74, 0x08, 0xbb, 0x92,
+ 0x32, 0xe8, 0xd2, 0x81, 0x72, 0x0a, 0xe8, 0xaa,
+ 0x7f, 0x72, 0x05, 0xe8, 0x76, 0x7f, 0x73, 0xe4,
+ 0xe8, 0x04, 0x04, 0xe8, 0xc9, 0x7e, 0x07, 0xc3,
+ 0xbb, 0x8d, 0xc4, 0x8b, 0x0e, 0x73, 0xc4, 0x03,
+ 0xd9, 0x88, 0x07, 0xff, 0x06, 0x73, 0xc4, 0xc3,
+ 0xbb, 0x8d, 0xc4, 0x8b, 0x0e, 0x73, 0xc4, 0x3a,
+ 0x07, 0x74, 0x08, 0x43, 0xe2, 0xf9, 0xb0, 0x3b,
+ 0xe9, 0x0d, 0x8c, 0x8a, 0x47, 0x01, 0x88, 0x07,
+ 0x43, 0xe2, 0xf8, 0xc6, 0x47, 0x01, 0x00, 0xff,
+ 0x0e, 0x73, 0xc4, 0xc3, 0xbb, 0x8d, 0xc4, 0x8b,
+ 0x0e, 0x73, 0xc4, 0x3a, 0x07, 0x74, 0x05, 0x43,
+ 0xe2, 0xf9, 0xf8, 0xc3, 0xf9, 0xc3, 0xbb, 0x8d,
+ 0xc4, 0x8b, 0x0e, 0x73, 0xc4, 0xc6, 0x07, 0x00,
+ 0x43, 0xe2, 0xfa, 0xc7, 0x06, 0x73, 0xc4, 0x00,
+ 0x00, 0xc3, 0xa1, 0x1f, 0xc4, 0xe8, 0xcc, 0x00,
+ 0x3c, 0x03, 0x74, 0x1e, 0x3c, 0x29, 0x74, 0x1a,
+ 0x3c, 0x25, 0x74, 0x16, 0x3c, 0x48, 0x74, 0x12,
+ 0xb0, 0xff, 0x83, 0x3e, 0xf3, 0xb4, 0x18, 0x75,
+ 0x07, 0x80, 0x3e, 0xa4, 0xdb, 0x00, 0x74, 0x02,
+ 0xf8, 0xc3, 0xa2, 0xe1, 0xc3, 0xe8, 0x8a, 0xf8,
+ 0xc6, 0x06, 0x6e, 0xc4, 0x00, 0xf9, 0xc3, 0xa1,
+ 0x6f, 0xc4, 0xe8, 0x97, 0x00, 0x3c, 0x04, 0x74,
+ 0x06, 0x3c, 0x33, 0x74, 0x02, 0xf8, 0xc3, 0xa2,
+ 0xe1, 0xc3, 0xe8, 0x6d, 0xf8, 0xc6, 0x06, 0x6e,
+ 0xc4, 0x00, 0xf9, 0xc3, 0xa1, 0x1f, 0xc4, 0xe8,
+ 0x7a, 0x00, 0x8a, 0xc8, 0xa1, 0x21, 0xc4, 0xe8,
+ 0x72, 0x00, 0x8a, 0xd0, 0xbb, 0x35, 0xc3, 0x8b,
+ 0x07, 0x3a, 0xc1, 0x75, 0x04, 0x3a, 0xe2, 0x74,
+ 0x08, 0x3a, 0xc2, 0x75, 0x53, 0x3a, 0xe1, 0x75,
+ 0x4f, 0x80, 0x7f, 0x02, 0x00, 0x74, 0x42, 0x60,
+ 0xb9, 0x45, 0x00, 0xb0, 0x01, 0xb4, 0x05, 0xff,
+ 0x1e, 0x4a, 0x32, 0xb8, 0x3b, 0x0b, 0x8e, 0xd8,
+ 0x8e, 0xc0, 0xa0, 0x49, 0x32, 0xb4, 0x04, 0xb5,
+ 0x07, 0xff, 0x1e, 0x4a, 0x32, 0xb8, 0x3b, 0x0b,
+ 0x8e, 0xd8, 0x8e, 0xc0, 0x61, 0x53, 0x8a, 0x07,
+ 0xe8, 0x0d, 0xff, 0x5b, 0x53, 0x8a, 0x47, 0x01,
+ 0xe8, 0x05, 0xff, 0x5b, 0x53, 0x8a, 0x47, 0x02,
+ 0xe8, 0xed, 0xfe, 0x5b, 0x53, 0xe8, 0x5d, 0xf9,
+ 0x5b, 0x8b, 0x5f, 0x03, 0xe8, 0x68, 0xfb, 0xc3,
+ 0x83, 0xc3, 0x05, 0x83, 0x3f, 0x00, 0x75, 0x97,
+ 0xe8, 0x55, 0xfb, 0xc3, 0x0b, 0xc0, 0x75, 0x01,
+ 0xc3, 0x53, 0x48, 0xbb, 0x8d, 0xc4, 0x03, 0xd8,
+ 0x8a, 0x07, 0x32, 0xe4, 0x5b, 0xc3, 0x60, 0xe8,
+ 0x52, 0x06, 0xe8, 0x2f, 0x03, 0xe8, 0x85, 0x01,
+ 0xe8, 0x43, 0x02, 0xe8, 0xf2, 0x06, 0xe8, 0x72,
+ 0x03, 0xe8, 0xdb, 0x04, 0xe8, 0x8e, 0x01, 0xe8,
+ 0x4c, 0x02, 0xe8, 0x7b, 0x7e, 0xe8, 0xc1, 0x0b,
+ 0xe8, 0x74, 0x05, 0xe8, 0xc2, 0x01, 0xe8, 0x89,
+ 0x02, 0xe8, 0x33, 0x7d, 0x61, 0xc3, 0xe8, 0x2a,
+ 0x00, 0x0b, 0xc0, 0x74, 0x17, 0x3d, 0x03, 0x00,
+ 0x74, 0x12, 0x3d, 0x01, 0x00, 0x74, 0x0e, 0xc6,
+ 0x06, 0xda, 0x1c, 0x02, 0xe8, 0xb7, 0xff, 0xc6,
+ 0x06, 0xda, 0x1c, 0x03, 0xc3, 0xc6, 0x06, 0xda,
+ 0x1c, 0x01, 0xe8, 0xa9, 0xff, 0xc6, 0x06, 0xda,
+ 0x1c, 0x00, 0xc3, 0xbb, 0x54, 0x72, 0xe8, 0x01,
+ 0x17, 0x8b, 0xf3, 0x8b, 0x1c, 0x0b, 0xdb, 0x74,
+ 0x0a, 0xe8, 0xd3, 0x00, 0x72, 0x20, 0x83, 0xc6,
+ 0x02, 0xeb, 0xf0, 0x83, 0x3e, 0x52, 0x72, 0x00,
+ 0x75, 0x03, 0x33, 0xc0, 0xc3, 0xc7, 0x06, 0x52,
+ 0x72, 0x00, 0x00, 0x83, 0x3e, 0x1f, 0xc4, 0x00,
+ 0x75, 0x11, 0xb8, 0x01, 0x00, 0xc3, 0x3b, 0x06,
+ 0x52, 0x72, 0x75, 0x04, 0xb8, 0x03, 0x00, 0xc3,
+ 0xa3, 0x52, 0x72, 0xa1, 0xde, 0x1c, 0xa3, 0xe2,
+ 0x1c, 0xa1, 0xe0, 0x1c, 0xa3, 0xe4, 0x1c, 0x53,
+ 0xc6, 0x06, 0xda, 0x1c, 0x01, 0xe8, 0xdd, 0x00,
+ 0xe8, 0xc0, 0x00, 0x5b, 0x83, 0xc3, 0x13, 0xe8,
+ 0x45, 0x00, 0xbb, 0x28, 0xc4, 0xbe, 0xe8, 0x1c,
+ 0x81, 0xc6, 0x85, 0x02, 0x56, 0xc6, 0x06, 0xe6,
+ 0x1c, 0xd1, 0xe8, 0x10, 0x7b, 0x8b, 0xc6, 0x5e,
+ 0x2b, 0xc6, 0xbe, 0x05, 0x00, 0x03, 0xc6, 0x03,
+ 0xc6, 0x40, 0x0c, 0x01, 0x3d, 0x40, 0x01, 0x76,
+ 0x03, 0xb8, 0x40, 0x01, 0xa3, 0xe0, 0x1c, 0xb9,
+ 0x40, 0x01, 0x2b, 0xc8, 0xd1, 0xe9, 0xb8, 0xb4,
+ 0x00, 0xbb, 0x40, 0x01, 0xf7, 0xe3, 0x03, 0xc1,
+ 0xa3, 0xde, 0x1c, 0xb8, 0x02, 0x00, 0xc3, 0xbf,
+ 0x28, 0xc4, 0xb9, 0x46, 0x00, 0x32, 0xc0, 0xfc,
+ 0xf3, 0xaa, 0xbe, 0x28, 0xc4, 0x8b, 0x0e, 0x1f,
+ 0xc4, 0x0b, 0xc9, 0x74, 0x26, 0x53, 0xe8, 0xb8,
+ 0xfb, 0x83, 0xc3, 0x02, 0xe8, 0xa7, 0xfb, 0x4e,
+ 0xb0, 0x20, 0xb4, 0x26, 0x88, 0x04, 0x88, 0x64,
+ 0x01, 0x88, 0x44, 0x02, 0x83, 0xc6, 0x03, 0x5b,
+ 0xa1, 0x1f, 0xc4, 0x8b, 0x0e, 0x52, 0x72, 0x0b,
+ 0xc9, 0x74, 0x03, 0xe8, 0x88, 0xfb, 0xc3, 0x8a,
+ 0x47, 0x12, 0x0a, 0xc0, 0x74, 0x29, 0xa1, 0xc0,
+ 0x00, 0x8b, 0x16, 0xc2, 0x00, 0x8b, 0x4f, 0x01,
+ 0x3b, 0xc1, 0x72, 0x1b, 0x8b, 0x4f, 0x03, 0x3b,
+ 0xd1, 0x72, 0x14, 0x8b, 0x4f, 0x05, 0x3b, 0xc1,
+ 0x77, 0x0d, 0x8b, 0x4f, 0x07, 0x3b, 0xd1, 0x77,
+ 0x06, 0x33, 0xc0, 0x8a, 0x07, 0xf9, 0xc3, 0x33,
+ 0xc0, 0xf8, 0xc3, 0xbe, 0xe8, 0x1c, 0xb9, 0x0f,
+ 0x00, 0xb0, 0xff, 0xb4, 0xe0, 0xba, 0x40, 0x01,
+ 0x88, 0x04, 0x86, 0xc4, 0x46, 0x4a, 0x75, 0xf8,
+ 0x86, 0xc4, 0xe2, 0xf1, 0xc3, 0xa0, 0xda, 0x1c,
+ 0x3c, 0x00, 0x75, 0x01, 0xc3, 0x3c, 0x03, 0x75,
+ 0x01, 0xc3, 0xa1, 0xb3, 0x32, 0x8b, 0x1e, 0xb1,
+ 0x32, 0xe8, 0x81, 0x00, 0xc3, 0xa0, 0xda, 0x1c,
+ 0x3c, 0x00, 0x75, 0x01, 0xc3, 0x3c, 0x01, 0x75,
+ 0x01, 0xc3, 0xa1, 0xb1, 0x32, 0x06, 0x8e, 0xc0,
+ 0x8b, 0x36, 0xde, 0x1c, 0x8b, 0x16, 0xe0, 0x1c,
+ 0xbf, 0xe8, 0x1c, 0xb9, 0x0f, 0x00, 0x8b, 0xda,
+ 0x8a, 0x05, 0x3c, 0xff, 0x74, 0x03, 0x26, 0x88,
+ 0x04, 0x46, 0x47, 0x4a, 0x75, 0xf2, 0x8b, 0xd3,
+ 0x81, 0xc6, 0x40, 0x01, 0x2b, 0xf2, 0x81, 0xc7,
+ 0x40, 0x01, 0x2b, 0xfa, 0xe2, 0xe0, 0x07, 0xc3,
+ 0xa0, 0xda, 0x1c, 0x3c, 0x00, 0x75, 0x01, 0xc3,
+ 0x3c, 0x03, 0x75, 0x01, 0xc3, 0xa1, 0xe4, 0x1c,
+ 0x3b, 0x06, 0xe0, 0x1c, 0x72, 0x1d, 0xff, 0x36,
+ 0xe0, 0x1c, 0xff, 0x36, 0xde, 0x1c, 0xa3, 0xe0,
+ 0x1c, 0xa1, 0xe2, 0x1c, 0xa3, 0xde, 0x1c, 0xe8,
+ 0x09, 0x00, 0x8f, 0x06, 0xde, 0x1c, 0x8f, 0x06,
+ 0xe0, 0x1c, 0xc3, 0xa1, 0xb1, 0x32, 0xbb, 0x00,
+ 0xa0, 0xe8, 0x01, 0x00, 0xc3, 0x8b, 0x36, 0xde,
+ 0x1c, 0x8b, 0x16, 0xe0, 0x1c, 0xb9, 0x0f, 0x00,
+ 0x1e, 0x06, 0x8e, 0xdb, 0x8e, 0xc0, 0x8b, 0xda,
+ 0x26, 0x8a, 0x04, 0x88, 0x04, 0x46, 0x4a, 0x75,
+ 0xf7, 0x8b, 0xd3, 0x81, 0xc6, 0x40, 0x01, 0x2b,
+ 0xf2, 0xe2, 0xeb, 0x07, 0x1f, 0xc3, 0xa0, 0xdb,
+ 0x1c, 0x3c, 0x00, 0x75, 0x01, 0xc3, 0x3c, 0x03,
+ 0x75, 0x01, 0xc3, 0xa1, 0xb3, 0x32, 0x8b, 0x1e,
+ 0xb1, 0x32, 0xe8, 0x78, 0x00, 0xc3, 0xa0, 0xdb,
+ 0x1c, 0x3c, 0x00, 0x75, 0x01, 0xc3, 0x3c, 0x01,
+ 0x75, 0x01, 0xc3, 0xa1, 0xb1, 0x32, 0x1e, 0x06,
+ 0xba, 0xd4, 0x19, 0x8e, 0xc2, 0x26, 0x8b, 0x36,
+ 0x00, 0x00, 0x26, 0x8b, 0x16, 0x02, 0x00, 0xbf,
+ 0x0e, 0x00, 0xb9, 0x21, 0x00, 0x8e, 0xd8, 0x8b,
+ 0xda, 0x26, 0x8a, 0x05, 0x3c, 0xff, 0x74, 0x02,
+ 0x88, 0x04, 0x46, 0x47, 0x4a, 0x75, 0xf2, 0x8b,
+ 0xd3, 0x81, 0xc6, 0x40, 0x01, 0x2b, 0xf2, 0x81,
+ 0xc7, 0x40, 0x01, 0x2b, 0xfa, 0xe2, 0xe0, 0x07,
+ 0x1f, 0xc3, 0xa0, 0xdb, 0x1c, 0x3c, 0x00, 0x75,
+ 0x01, 0xc3, 0x3c, 0x03, 0x75, 0x01, 0xc3, 0xa1,
+ 0xb1, 0x32, 0xbb, 0x00, 0xa0, 0xe8, 0x15, 0x00,
+ 0xc3, 0x1e, 0xb9, 0xd4, 0x19, 0x8e, 0xd9, 0xbb,
+ 0x0e, 0x00, 0xb9, 0x40, 0x29, 0xc6, 0x07, 0xff,
+ 0x43, 0xe2, 0xfa, 0x1f, 0xc3, 0x1e, 0xb9, 0xd4,
+ 0x19, 0x8e, 0xd9, 0x8b, 0x36, 0x00, 0x00, 0x8b,
+ 0x16, 0x02, 0x00, 0xb9, 0x21, 0x00, 0x1f, 0x1e,
+ 0x06, 0x8e, 0xdb, 0x8e, 0xc0, 0x8b, 0xda, 0x26,
+ 0x8a, 0x04, 0x88, 0x04, 0x46, 0x4a, 0x75, 0xf7,
+ 0x8b, 0xd3, 0x81, 0xc6, 0x40, 0x01, 0x2b, 0xf2,
+ 0xe2, 0xeb, 0x07, 0x1f, 0xc3, 0xbb, 0xa4, 0x32,
+ 0xe8, 0x6b, 0x7d, 0x73, 0x1e, 0x8b, 0x0e, 0x90,
+ 0x32, 0xe8, 0x4f, 0x7d, 0xc6, 0x06, 0x33, 0x33,
+ 0x01, 0xc6, 0x06, 0xdd, 0x1c, 0x02, 0xe8, 0xd5,
+ 0xfc, 0xc6, 0x06, 0x33, 0x33, 0x00, 0xc6, 0x06,
+ 0xdd, 0x1c, 0x03, 0xc3, 0xb9, 0x01, 0x00, 0xbb,
+ 0xc7, 0x32, 0x53, 0x51, 0x49, 0xb0, 0x1b, 0xf6,
+ 0xe1, 0x03, 0xd8, 0x8b, 0x07, 0x0b, 0xc0, 0x74,
+ 0x0c, 0x8b, 0x7f, 0x12, 0x8b, 0x4f, 0x14, 0x8b,
+ 0x5f, 0x10, 0xe8, 0x09, 0x00, 0x59, 0x5b, 0x41,
+ 0x80, 0xf9, 0x04, 0x76, 0xdd, 0xc3, 0x1e, 0x06,
+ 0xa1, 0xb3, 0x32, 0x8e, 0xc0, 0xa1, 0xb1, 0x32,
+ 0x8e, 0xd8, 0x8b, 0xd1, 0x8b, 0xcf, 0x26, 0x8a,
+ 0x07, 0x88, 0x07, 0x43, 0xe2, 0xf8, 0x8b, 0xca,
+ 0x81, 0xc3, 0x40, 0x01, 0x2b, 0xdf, 0xe2, 0xea,
+ 0x07, 0x1f, 0xc3, 0x80, 0x3e, 0x33, 0x33, 0x01,
+ 0x74, 0x01, 0xc3, 0xb9, 0x01, 0x00, 0xbf, 0xc7,
+ 0x32, 0x57, 0x51, 0x49, 0xb0, 0x1b, 0xf6, 0xe1,
+ 0x03, 0xf8, 0x8b, 0x05, 0x0b, 0xc0, 0x74, 0x06,
+ 0x8b, 0x45, 0x16, 0xe8, 0x09, 0x00, 0x59, 0x5f,
+ 0x41, 0x80, 0xf9, 0x04, 0x76, 0xe3, 0xc3, 0x06,
+ 0x8e, 0xc0, 0x51, 0xbb, 0xff, 0xff, 0x8b, 0x05,
+ 0xb9, 0x03, 0x00, 0xf7, 0xe1, 0x03, 0xd8, 0xbe,
+ 0x00, 0x00, 0x26, 0x8b, 0x34, 0x8b, 0xd6, 0x3b,
+ 0xde, 0x72, 0x06, 0xc7, 0x05, 0x01, 0x00, 0xeb,
+ 0xe2, 0xff, 0x05, 0x33, 0xc9, 0x26, 0x8a, 0x0f,
+ 0x88, 0x4d, 0x1a, 0x26, 0x8b, 0x77, 0x01, 0x89,
+ 0x75, 0x0a, 0x8b, 0xda, 0x43, 0x83, 0xeb, 0x02,
+ 0xd1, 0xe1, 0x03, 0xd9, 0x26, 0x8b, 0x1f, 0x03,
+ 0xda, 0x26, 0x8b, 0x07, 0x89, 0x45, 0x0c, 0x26,
+ 0x8b, 0x47, 0x02, 0x89, 0x45, 0x0e, 0x83, 0xc3,
+ 0x04, 0x89, 0x5d, 0x18, 0x33, 0xd2, 0x8b, 0xc6,
+ 0xf7, 0x36, 0xb6, 0x00, 0x89, 0x16, 0x4f, 0x33,
+ 0xa3, 0x57, 0x33, 0x03, 0x55, 0x0c, 0x03, 0x45,
+ 0x0e, 0x89, 0x16, 0x51, 0x33, 0xa3, 0x59, 0x33,
+ 0x59, 0xe8, 0x85, 0x00, 0x33, 0xd2, 0x8b, 0x45,
+ 0x10, 0xf7, 0x36, 0xb6, 0x00, 0x89, 0x16, 0x53,
+ 0x33, 0xa3, 0x5b, 0x33, 0x03, 0x55, 0x12, 0x03,
+ 0x45, 0x14, 0x89, 0x16, 0x55, 0x33, 0xa3, 0x5d,
+ 0x33, 0xa1, 0x4f, 0x33, 0x8b, 0x1e, 0x53, 0x33,
+ 0x3b, 0xc3, 0x76, 0x04, 0x89, 0x1e, 0x4f, 0x33,
+ 0xa1, 0x51, 0x33, 0x8b, 0x1e, 0x55, 0x33, 0x3b,
+ 0xc3, 0x77, 0x04, 0x89, 0x1e, 0x51, 0x33, 0xa1,
+ 0x57, 0x33, 0x8b, 0x1e, 0x5b, 0x33, 0x3b, 0xc3,
+ 0x76, 0x04, 0x89, 0x1e, 0x57, 0x33, 0xa1, 0x59,
+ 0x33, 0x8b, 0x1e, 0x5d, 0x33, 0x3b, 0xc3, 0x77,
+ 0x04, 0x89, 0x1e, 0x59, 0x33, 0x07, 0xa1, 0x4f,
+ 0x33, 0x89, 0x45, 0x02, 0xa1, 0x57, 0x33, 0x89,
+ 0x45, 0x04, 0xa1, 0x51, 0x33, 0x89, 0x45, 0x06,
+ 0xa1, 0x59, 0x33, 0x89, 0x45, 0x08, 0x8b, 0x45,
+ 0x0c, 0x89, 0x45, 0x12, 0x8b, 0x45, 0x0e, 0x89,
+ 0x45, 0x14, 0x8b, 0x45, 0x0a, 0x89, 0x45, 0x10,
+ 0xc3, 0x80, 0x3e, 0x34, 0x33, 0x01, 0x74, 0x01,
+ 0xc3, 0xbb, 0x9e, 0xd8, 0x8b, 0x16, 0xf3, 0xb4,
+ 0x4a, 0xc1, 0xe2, 0x02, 0x03, 0xda, 0x03, 0xd9,
+ 0x33, 0xc9, 0x8a, 0x0f, 0x80, 0xf9, 0xff, 0x74,
+ 0x25, 0x49, 0xbb, 0x54, 0x72, 0xe8, 0x92, 0x12,
+ 0xd1, 0xe1, 0x03, 0xd9, 0x8b, 0x1f, 0x43, 0xa1,
+ 0x4f, 0x33, 0x89, 0x07, 0xa1, 0x57, 0x33, 0x89,
+ 0x47, 0x02, 0xa1, 0x51, 0x33, 0x89, 0x47, 0x04,
+ 0xa1, 0x59, 0x33, 0x89, 0x47, 0x06, 0xc3, 0xb9,
+ 0x01, 0x00, 0xbf, 0xc7, 0x32, 0x57, 0x51, 0x49,
+ 0xb0, 0x1b, 0xf6, 0xe1, 0x03, 0xf8, 0x8b, 0x05,
+ 0x0b, 0xc0, 0x74, 0x15, 0x8b, 0x45, 0x0a, 0x33,
+ 0xd2, 0xf7, 0x36, 0xb6, 0x00, 0x03, 0x45, 0x0e,
+ 0x3b, 0x06, 0xb1, 0x64, 0x73, 0x03, 0xe8, 0x48,
+ 0x00, 0x59, 0x5f, 0x41, 0x80, 0xf9, 0x04, 0x76,
+ 0xd4, 0x80, 0x3e, 0xdc, 0x1c, 0x01, 0x74, 0x03,
+ 0xe8, 0x6c, 0x03, 0xe8, 0x9f, 0x05, 0xb9, 0x01,
+ 0x00, 0xbf, 0xc7, 0x32, 0x57, 0x51, 0x49, 0xb0,
+ 0x1b, 0xf6, 0xe1, 0x03, 0xf8, 0x8b, 0x05, 0x0b,
+ 0xc0, 0x74, 0x15, 0x8b, 0x45, 0x0a, 0x33, 0xd2,
+ 0xf7, 0x36, 0xb6, 0x00, 0x03, 0x45, 0x0e, 0x3b,
+ 0x06, 0xb1, 0x64, 0x72, 0x03, 0xe8, 0x09, 0x00,
+ 0x59, 0x5f, 0x41, 0x80, 0xf9, 0x04, 0x76, 0xd4,
+ 0xc3, 0x8b, 0x45, 0x16, 0x8b, 0x5d, 0x0a, 0x8b,
+ 0x55, 0x0c, 0x8b, 0x4d, 0x0e, 0x8b, 0x75, 0x18,
+ 0x1e, 0x06, 0x8e, 0xc0, 0xa1, 0xb1, 0x32, 0x8e,
+ 0xd8, 0x8b, 0xf9, 0x8b, 0xca, 0x26, 0x8a, 0x04,
+ 0x3c, 0xff, 0x74, 0x02, 0x88, 0x07, 0x46, 0x43,
+ 0xe2, 0xf3, 0x8b, 0xcf, 0x81, 0xc3, 0x40, 0x01,
+ 0x2b, 0xda, 0xe2, 0xe5, 0x07, 0x1f, 0xc3, 0x80,
+ 0x3e, 0xdd, 0x1c, 0x02, 0x74, 0x01, 0xc3, 0xb9,
+ 0x01, 0x00, 0xbf, 0xc7, 0x32, 0x57, 0x51, 0x49,
+ 0xb0, 0x1b, 0xf6, 0xe1, 0x03, 0xf8, 0x8b, 0x05,
+ 0x0b, 0xc0, 0x74, 0x0f, 0x8b, 0x45, 0x04, 0x8b,
+ 0x5d, 0x02, 0x8b, 0x4d, 0x08, 0x8b, 0x7d, 0x06,
+ 0xe8, 0x09, 0x00, 0x59, 0x5f, 0x41, 0x80, 0xf9,
+ 0x04, 0x76, 0xda, 0xc3, 0x1e, 0x06, 0x8b, 0x16,
+ 0xb1, 0x32, 0x8e, 0xc2, 0x50, 0xba, 0x40, 0x01,
+ 0xf7, 0xe2, 0x03, 0xc3, 0x2b, 0xfb, 0x5a, 0x2b,
+ 0xca, 0x8b, 0xd8, 0xb8, 0x00, 0xa0, 0x8e, 0xd8,
+ 0x8b, 0xd1, 0x8b, 0xcf, 0x26, 0x8a, 0x07, 0x88,
+ 0x07, 0x43, 0xe2, 0xf8, 0x8b, 0xca, 0x81, 0xc3,
+ 0x40, 0x01, 0x2b, 0xdf, 0xe2, 0xea, 0x07, 0x1f,
+ 0xc3, 0x50, 0x32, 0xe4, 0x48, 0xbb, 0x9e, 0xd8,
+ 0x8b, 0x16, 0xf3, 0xb4, 0x4a, 0xc1, 0xe2, 0x02,
+ 0x03, 0xda, 0x03, 0xd8, 0x58, 0x88, 0x27, 0xc3,
+ 0x50, 0xe8, 0x18, 0xfd, 0xe8, 0x35, 0x00, 0x58,
+ 0x32, 0xe4, 0xbb, 0xc7, 0x32, 0xb1, 0x1b, 0x48,
+ 0xf6, 0xe1, 0x03, 0xd8, 0xc7, 0x07, 0x00, 0x00,
+ 0x53, 0xe8, 0xcc, 0x00, 0xe8, 0xb8, 0xfe, 0xe8,
+ 0x5e, 0x78, 0x5b, 0x53, 0xff, 0x07, 0xff, 0x36,
+ 0xdd, 0x1c, 0xc6, 0x06, 0xdd, 0x1c, 0x02, 0xe8,
+ 0x4d, 0xff, 0x8f, 0x06, 0xdd, 0x1c, 0x5b, 0xc7,
+ 0x07, 0x00, 0x00, 0xc3, 0x8b, 0x1e, 0x30, 0x32,
+ 0x8b, 0x3e, 0x2e, 0x32, 0x8b, 0x0e, 0x2c, 0x32,
+ 0x1e, 0x06, 0xa1, 0xb3, 0x32, 0x8e, 0xc0, 0xa1,
+ 0xb1, 0x32, 0x8e, 0xd8, 0x8b, 0xd1, 0x8b, 0xcf,
+ 0x81, 0xfb, 0xff, 0xf9, 0x77, 0x05, 0x26, 0x8a,
+ 0x07, 0x88, 0x07, 0x43, 0xe2, 0xf2, 0x8b, 0xca,
+ 0x81, 0xc3, 0x40, 0x01, 0x2b, 0xdf, 0xe2, 0xe4,
+ 0x07, 0x1f, 0xc3, 0x06, 0xa1, 0xbf, 0x32, 0x8e,
+ 0xc0, 0x33, 0xc0, 0xa3, 0x28, 0x32, 0xa3, 0x2a,
+ 0x32, 0xbb, 0xff, 0xff, 0x8a, 0x0e, 0x07, 0x66,
+ 0xb8, 0x03, 0x00, 0xf6, 0xe1, 0x03, 0xd8, 0xbe,
+ 0x00, 0x00, 0x26, 0x8b, 0x34, 0x8b, 0xd6, 0x3b,
+ 0xde, 0x72, 0x03, 0x07, 0xf9, 0xc3, 0xfe, 0x06,
+ 0x07, 0x66, 0x33, 0xc9, 0x26, 0x8a, 0x0f, 0x26,
+ 0x8b, 0x77, 0x01, 0x8b, 0xda, 0x43, 0x83, 0xeb,
+ 0x02, 0xd1, 0xe1, 0x03, 0xd9, 0x26, 0x8b, 0x1f,
+ 0x03, 0xda, 0x26, 0x8b, 0x3f, 0x26, 0x8b, 0x4f,
+ 0x02, 0x83, 0xc3, 0x04, 0x89, 0x1e, 0xde, 0x64,
+ 0x89, 0x0e, 0xe2, 0x64, 0x89, 0x3e, 0xe0, 0x64,
+ 0x89, 0x36, 0xe4, 0x64, 0x51, 0xe8, 0x31, 0x01,
+ 0x59, 0x89, 0x0e, 0x2c, 0x32, 0x89, 0x3e, 0x2e,
+ 0x32, 0x89, 0x36, 0x30, 0x32, 0x07, 0xf8, 0xc3,
+ 0x06, 0xa1, 0xbf, 0x32, 0x8e, 0xc0, 0x8b, 0x1e,
+ 0xe6, 0x64, 0x26, 0x8b, 0x3f, 0x43, 0x43, 0x26,
+ 0x8b, 0x0f, 0x43, 0x43, 0xa1, 0xb1, 0x64, 0x2d,
+ 0x3e, 0x00, 0xba, 0x40, 0x01, 0xf7, 0xe2, 0x03,
+ 0x06, 0xaf, 0x64, 0x8b, 0xd7, 0xd1, 0xea, 0x52,
+ 0x2b, 0xc2, 0x8b, 0xf0, 0x26, 0x8b, 0x07, 0x03,
+ 0xf0, 0x33, 0xd2, 0xf7, 0x36, 0xb6, 0x00, 0x89,
+ 0x16, 0x28, 0x32, 0xa3, 0x2a, 0x32, 0x5a, 0x43,
+ 0x43, 0x89, 0x1e, 0xde, 0x64, 0x89, 0x0e, 0xe2,
+ 0x64, 0x89, 0x3e, 0xe0, 0x64, 0x89, 0x36, 0xe4,
+ 0x64, 0x51, 0x57, 0x56, 0x51, 0x52, 0xe8, 0xc8,
+ 0x00, 0x5a, 0x59, 0xc6, 0x06, 0xae, 0x64, 0x00,
+ 0xc7, 0x06, 0xba, 0x00, 0x3f, 0x01, 0xc7, 0x06,
+ 0xb8, 0x00, 0x00, 0x00, 0xc7, 0x06, 0xbc, 0x00,
+ 0x00, 0x00, 0xc7, 0x06, 0xbe, 0x00, 0xc7, 0x00,
+ 0xa1, 0xaf, 0x64, 0x2b, 0xc2, 0x72, 0x09, 0x03,
+ 0x06, 0x28, 0x32, 0x3d, 0x00, 0x00, 0x73, 0x1b,
+ 0xc6, 0x06, 0xae, 0x64, 0x01, 0xa1, 0xaf, 0x64,
+ 0x03, 0xc2, 0x03, 0x06, 0x28, 0x32, 0x8b, 0x1e,
+ 0x34, 0x32, 0x3b, 0xc3, 0x76, 0x02, 0x8b, 0xc3,
+ 0xa3, 0xba, 0x00, 0xa1, 0xaf, 0x64, 0x03, 0xc2,
+ 0x03, 0x06, 0x28, 0x32, 0x3d, 0x3f, 0x01, 0x76,
+ 0x16, 0xc6, 0x06, 0xae, 0x64, 0x01, 0x2b, 0xc2,
+ 0x2b, 0xc2, 0x8b, 0x1e, 0x32, 0x32, 0x3b, 0xc3,
+ 0x76, 0x02, 0x8b, 0xc3, 0xa3, 0xb8, 0x00, 0xa1,
+ 0xb1, 0x64, 0x2b, 0xc1, 0x72, 0x09, 0x03, 0x06,
+ 0x2a, 0x32, 0x3d, 0x00, 0x00, 0x73, 0x19, 0xc6,
+ 0x06, 0xae, 0x64, 0x01, 0xa1, 0xb1, 0x64, 0x03,
+ 0x06, 0x2a, 0x32, 0x8b, 0x1e, 0x3c, 0x32, 0x3b,
+ 0xc3, 0x76, 0x02, 0x8b, 0xc3, 0xa3, 0xbe, 0x00,
+ 0xa1, 0xb1, 0x64, 0x03, 0x06, 0x2a, 0x32, 0x3d,
+ 0xc7, 0x00, 0x76, 0x14, 0xc6, 0x06, 0xae, 0x64,
+ 0x01, 0x2b, 0xc1, 0x8b, 0x1e, 0x3a, 0x32, 0x3b,
+ 0xc3, 0x73, 0x02, 0x8b, 0xc3, 0xa3, 0xbc, 0x00,
+ 0x5e, 0x5f, 0x59, 0x89, 0x0e, 0x2c, 0x32, 0x89,
+ 0x3e, 0x2e, 0x32, 0x89, 0x36, 0x30, 0x32, 0x07,
+ 0xc3, 0x33, 0xd2, 0x8b, 0xc6, 0xf7, 0x36, 0xb6,
+ 0x00, 0x89, 0x16, 0x32, 0x32, 0xa3, 0x3a, 0x32,
+ 0x03, 0xd7, 0x03, 0xc1, 0x89, 0x16, 0x34, 0x32,
+ 0xa3, 0x3c, 0x32, 0x33, 0xd2, 0xa1, 0x30, 0x32,
+ 0xf7, 0x36, 0xb6, 0x00, 0x89, 0x16, 0x36, 0x32,
+ 0xa3, 0x3e, 0x32, 0x03, 0x16, 0x2e, 0x32, 0x03,
+ 0x06, 0x2c, 0x32, 0x89, 0x16, 0x38, 0x32, 0xa3,
+ 0x40, 0x32, 0xa1, 0x32, 0x32, 0x8b, 0x1e, 0x36,
+ 0x32, 0x3b, 0xc3, 0x76, 0x04, 0x89, 0x1e, 0x32,
+ 0x32, 0xa1, 0x34, 0x32, 0x8b, 0x1e, 0x38, 0x32,
+ 0x3b, 0xc3, 0x77, 0x04, 0x89, 0x1e, 0x34, 0x32,
+ 0xa1, 0x3a, 0x32, 0x8b, 0x1e, 0x3e, 0x32, 0x3b,
+ 0xc3, 0x76, 0x04, 0x89, 0x1e, 0x3a, 0x32, 0xa1,
+ 0x3c, 0x32, 0x8b, 0x1e, 0x40, 0x32, 0x3b, 0xc3,
+ 0x77, 0x04, 0x89, 0x1e, 0x3c, 0x32, 0xc3, 0x55,
+ 0x1e, 0x06, 0xe8, 0x04, 0x00, 0x07, 0x1f, 0x5d,
+ 0xc3, 0x8b, 0x1e, 0xde, 0x64, 0x8b, 0x0e, 0xe2,
+ 0x64, 0x8b, 0x3e, 0xe0, 0x64, 0x8b, 0x36, 0xe4,
+ 0x64, 0xa1, 0xbf, 0x32, 0x8e, 0xc0, 0x8b, 0xc1,
+ 0x03, 0xdf, 0x81, 0xc6, 0x40, 0x01, 0xe2, 0xf8,
+ 0x8b, 0xc8, 0x81, 0xee, 0x40, 0x01, 0x03, 0xf7,
+ 0x4e, 0x4b, 0x8b, 0xc7, 0xf7, 0x26, 0xd8, 0x64,
+ 0x33, 0xd2, 0xf7, 0x36, 0xda, 0x64, 0xd1, 0xe8,
+ 0x2b, 0xf0, 0xa0, 0xae, 0x64, 0x8a, 0x26, 0xdc,
+ 0x64, 0x8a, 0x16, 0xcb, 0x64, 0x8b, 0x2e, 0xb1,
+ 0x32, 0x8e, 0xdd, 0xbd, 0x00, 0xfa, 0x0a, 0xc0,
+ 0x74, 0x03, 0xe9, 0xa8, 0x00, 0x0a, 0xe4, 0x74,
+ 0x56, 0x80, 0xfa, 0x01, 0x74, 0x51, 0x3e, 0x8b,
+ 0x56, 0x00, 0x3e, 0x03, 0x56, 0x02, 0x43, 0x2b,
+ 0xdf, 0x51, 0x56, 0x8b, 0xcf, 0x83, 0xea, 0x64,
+ 0x77, 0x0c, 0x3e, 0x03, 0x56, 0x00, 0x3e, 0x03,
+ 0x56, 0x02, 0x5e, 0x59, 0xeb, 0x2e, 0x52, 0x3e,
+ 0x8b, 0x56, 0x00, 0x3e, 0x03, 0x56, 0x02, 0x83,
+ 0xea, 0x64, 0x77, 0x0a, 0x3e, 0x03, 0x56, 0x00,
+ 0x3e, 0x03, 0x56, 0x02, 0xeb, 0x0a, 0x26, 0x8a,
+ 0x07, 0x3c, 0xff, 0x74, 0x02, 0x88, 0x04, 0x4e,
+ 0x43, 0xe2, 0xe4, 0x5a, 0x5e, 0x59, 0x81, 0xee,
+ 0x40, 0x01, 0x2b, 0xdf, 0xe2, 0xb9, 0xc3, 0x3e,
+ 0x8b, 0x56, 0x00, 0x3e, 0x03, 0x56, 0x02, 0x51,
+ 0x56, 0x8b, 0xcf, 0x83, 0xea, 0x64, 0x77, 0x0e,
+ 0x3e, 0x03, 0x56, 0x00, 0x3e, 0x03, 0x56, 0x02,
+ 0x2b, 0xd9, 0x5e, 0x59, 0xeb, 0x2c, 0x52, 0x3e,
+ 0x8b, 0x56, 0x00, 0x3e, 0x03, 0x56, 0x02, 0x83,
+ 0xea, 0x64, 0x77, 0x0a, 0x3e, 0x03, 0x56, 0x00,
+ 0x3e, 0x03, 0x56, 0x02, 0xeb, 0x0a, 0x26, 0x8a,
+ 0x07, 0x3c, 0xff, 0x74, 0x02, 0x88, 0x04, 0x4e,
+ 0x4b, 0xe2, 0xe4, 0x5a, 0x5e, 0x59, 0x81, 0xee,
+ 0x40, 0x01, 0xe2, 0xbb, 0xc3, 0x0a, 0xe4, 0x75,
+ 0x03, 0xe9, 0x8d, 0x00, 0x80, 0xfa, 0x01, 0x75,
+ 0x03, 0xe9, 0x85, 0x00, 0xe8, 0x04, 0x01, 0x43,
+ 0xba, 0x3b, 0x0b, 0x8e, 0xda, 0x8b, 0x16, 0xb1,
+ 0x32, 0x8e, 0xda, 0x2b, 0xdf, 0x51, 0x56, 0x8b,
+ 0xcf, 0x3e, 0x83, 0x6e, 0x04, 0x64, 0x77, 0x07,
+ 0xe8, 0xf5, 0x00, 0x5e, 0x59, 0xeb, 0x5f, 0x3e,
+ 0xff, 0x76, 0x04, 0xe8, 0xdd, 0x00, 0x1e, 0x3e,
+ 0x83, 0x6e, 0x04, 0x64, 0x77, 0x05, 0xe8, 0xdf,
+ 0x00, 0xeb, 0x3b, 0x26, 0x8a, 0x07, 0x3c, 0xff,
+ 0x74, 0x33, 0xba, 0x3b, 0x0b, 0x8e, 0xda, 0xa2,
+ 0x27, 0x32, 0x8b, 0xc6, 0x33, 0xd2, 0xf7, 0x36,
+ 0xb6, 0x00, 0x3b, 0x16, 0xba, 0x00, 0x77, 0x1d,
+ 0x3b, 0x16, 0xb8, 0x00, 0x72, 0x17, 0x3b, 0x06,
+ 0xbe, 0x00, 0x77, 0x11, 0x3b, 0x06, 0xbc, 0x00,
+ 0x72, 0x0b, 0xa0, 0x27, 0x32, 0x8b, 0x16, 0xb1,
+ 0x32, 0x8e, 0xda, 0x88, 0x04, 0x4e, 0x43, 0x1f,
+ 0xe2, 0xb4, 0x3e, 0x8f, 0x46, 0x04, 0x5e, 0x59,
+ 0x81, 0xee, 0x40, 0x01, 0x2b, 0xdf, 0xe2, 0x80,
+ 0xc3, 0xe8, 0x7f, 0x00, 0xba, 0x3b, 0x0b, 0x8e,
+ 0xda, 0x8b, 0x16, 0xb1, 0x32, 0x8e, 0xda, 0x51,
+ 0x56, 0x8b, 0xcf, 0x3e, 0x83, 0x6e, 0x04, 0x64,
+ 0x77, 0x09, 0xe8, 0x73, 0x00, 0x2b, 0xd9, 0x5e,
+ 0x59, 0xeb, 0x5d, 0x3e, 0xff, 0x76, 0x04, 0xe8,
+ 0x59, 0x00, 0x1e, 0x3e, 0x83, 0x6e, 0x04, 0x64,
+ 0x77, 0x05, 0xe8, 0x5b, 0x00, 0xeb, 0x3b, 0x26,
+ 0x8a, 0x07, 0x3c, 0xff, 0x74, 0x33, 0xba, 0x3b,
+ 0x0b, 0x8e, 0xda, 0xa2, 0x27, 0x32, 0x8b, 0xc6,
+ 0x33, 0xd2, 0xf7, 0x36, 0xb6, 0x00, 0x3b, 0x16,
+ 0xba, 0x00, 0x77, 0x1d, 0x3b, 0x16, 0xb8, 0x00,
+ 0x72, 0x17, 0x3b, 0x06, 0xbe, 0x00, 0x77, 0x11,
+ 0x3b, 0x06, 0xbc, 0x00, 0x72, 0x0b, 0xa0, 0x27,
+ 0x32, 0x8b, 0x16, 0xb1, 0x32, 0x8e, 0xda, 0x88,
+ 0x04, 0x4e, 0x4b, 0x1f, 0xe2, 0xb4, 0x3e, 0x8f,
+ 0x46, 0x04, 0x5e, 0x59, 0x81, 0xee, 0x40, 0x01,
+ 0xe2, 0x82, 0xc3, 0x3e, 0x8b, 0x56, 0x00, 0x3e,
+ 0x03, 0x56, 0x02, 0x3e, 0x89, 0x56, 0x04, 0xc3,
+ 0x3e, 0x8b, 0x56, 0x00, 0x3e, 0x03, 0x56, 0x02,
+ 0x3e, 0x01, 0x56, 0x04, 0xc3, 0x06, 0xa1, 0xb5,
+ 0x32, 0x8e, 0xc0, 0x33, 0xdb, 0x26, 0x8a, 0x0f,
+ 0xb5, 0x00, 0x43, 0x51, 0x0a, 0xc9, 0x75, 0x03,
+ 0xe9, 0xfb, 0x00, 0x53, 0x26, 0x8b, 0x1f, 0x26,
+ 0x8b, 0x47, 0x04, 0x33, 0xd2, 0xf7, 0x36, 0xb6,
+ 0x00, 0x26, 0x8b, 0x37, 0x03, 0xf2, 0x4e, 0x26,
+ 0x8b, 0x7f, 0x02, 0x03, 0xf8, 0x4f, 0xe8, 0x10,
+ 0x0c, 0x72, 0x03, 0xe9, 0xd0, 0x00, 0x53, 0x8a,
+ 0x1e, 0xae, 0x64, 0x89, 0x16, 0xb7, 0x32, 0x8b,
+ 0x0e, 0x32, 0x32, 0x0a, 0xdb, 0x74, 0x04, 0x8b,
+ 0x0e, 0xb8, 0x00, 0x3b, 0xca, 0x72, 0x04, 0x89,
+ 0x0e, 0xb7, 0x32, 0xa3, 0xb9, 0x32, 0x8b, 0x0e,
+ 0x3a, 0x32, 0x0a, 0xdb, 0x74, 0x04, 0x8b, 0x0e,
+ 0xbc, 0x00, 0x3b, 0xc8, 0x72, 0x04, 0x89, 0x0e,
+ 0xb9, 0x32, 0x89, 0x36, 0xbb, 0x32, 0x8b, 0x0e,
+ 0x34, 0x32, 0x0a, 0xdb, 0x74, 0x04, 0x8b, 0x0e,
+ 0xba, 0x00, 0x3b, 0xce, 0x77, 0x04, 0x89, 0x0e,
+ 0xbb, 0x32, 0x89, 0x3e, 0xbd, 0x32, 0x8b, 0x0e,
+ 0x3c, 0x32, 0x0a, 0xdb, 0x74, 0x04, 0x8b, 0x0e,
+ 0xbe, 0x00, 0x3b, 0xcf, 0x77, 0x04, 0x89, 0x0e,
+ 0xbd, 0x32, 0x5b, 0x26, 0x8b, 0x3f, 0x83, 0xc3,
+ 0x06, 0x8b, 0xc8, 0x3b, 0x0e, 0xb9, 0x32, 0x73,
+ 0x05, 0x03, 0xdf, 0x41, 0xeb, 0xf5, 0x8b, 0xca,
+ 0x3b, 0x0e, 0xb7, 0x32, 0x73, 0x04, 0x43, 0x41,
+ 0xeb, 0xf6, 0xa1, 0xb9, 0x32, 0xf7, 0x26, 0xb6,
+ 0x00, 0x03, 0x06, 0xb7, 0x32, 0x8b, 0xf0, 0x55,
+ 0xa1, 0xbd, 0x32, 0x8b, 0x0e, 0xb9, 0x32, 0x8b,
+ 0x16, 0xbb, 0x32, 0x8b, 0x2e, 0xb7, 0x32, 0x1e,
+ 0x50, 0xa1, 0xb1, 0x32, 0x8e, 0xd8, 0x58, 0x50,
+ 0x53, 0x51, 0x56, 0x8b, 0xcd, 0x26, 0x8a, 0x07,
+ 0x3c, 0xff, 0x74, 0x02, 0x88, 0x04, 0x46, 0x43,
+ 0x41, 0x3b, 0xca, 0x76, 0xf0, 0x5e, 0x59, 0x5b,
+ 0x58, 0x81, 0xc6, 0x40, 0x01, 0x03, 0xdf, 0x41,
+ 0x3b, 0xc8, 0x76, 0xdb, 0x1f, 0x5d, 0x5b, 0x43,
+ 0x43, 0x59, 0x49, 0xe9, 0xfd, 0xfe, 0x59, 0x07,
+ 0xc3, 0xe8, 0x7d, 0x73, 0xa0, 0xdc, 0x1c, 0x3c,
+ 0x02, 0x74, 0x01, 0xc3, 0x1e, 0x06, 0xa1, 0xb1,
+ 0x32, 0x8e, 0xc0, 0xa1, 0x3a, 0x32, 0x8b, 0x1e,
+ 0x32, 0x32, 0x8b, 0x0e, 0x3c, 0x32, 0x8b, 0x3e,
+ 0x34, 0x32, 0xba, 0x40, 0x01, 0xf7, 0xe2, 0x03,
+ 0xc3, 0x2b, 0xfb, 0x2b, 0x0e, 0x3a, 0x32, 0x8b,
+ 0xd8, 0xb8, 0x00, 0xa0, 0x8e, 0xd8, 0x8b, 0xd1,
+ 0x8b, 0xcf, 0x81, 0xfb, 0xff, 0xf9, 0x77, 0x05,
+ 0x26, 0x8a, 0x07, 0x88, 0x07, 0x43, 0xe2, 0xf2,
+ 0x8b, 0xca, 0x81, 0xc3, 0x40, 0x01, 0x2b, 0xdf,
+ 0xe2, 0xe4, 0x07, 0x1f, 0xc3, 0x80, 0x3e, 0x3d,
+ 0x66, 0x02, 0x74, 0x01, 0xc3, 0xbb, 0xce, 0xb5,
+ 0xe8, 0x1f, 0x0b, 0x8b, 0x0e, 0x50, 0x72, 0x49,
+ 0xd1, 0xe1, 0x03, 0xd9, 0x83, 0x3f, 0x00, 0x74,
+ 0x04, 0xff, 0x17, 0xeb, 0x03, 0xe8, 0x68, 0x6b,
+ 0xc6, 0x06, 0x3d, 0x66, 0x00, 0xc7, 0x06, 0x50,
+ 0x72, 0x00, 0x00, 0xc7, 0x06, 0x52, 0x72, 0x00,
+ 0x00, 0xe8, 0x6c, 0x00, 0xc3, 0x80, 0x3e, 0x3d,
+ 0x66, 0x04, 0x74, 0x01, 0xc3, 0xe8, 0xed, 0x70,
+ 0xbb, 0x9c, 0xb8, 0xe8, 0xe4, 0x0a, 0x8b, 0x0e,
+ 0x50, 0x72, 0x49, 0xd1, 0xe1, 0x03, 0xd9, 0xff,
+ 0x17, 0xe8, 0xfb, 0x70, 0xc6, 0x06, 0x3d, 0x66,
+ 0x00, 0xc7, 0x06, 0x50, 0x72, 0x00, 0x00, 0xc7,
+ 0x06, 0x52, 0x72, 0xff, 0x00, 0xe8, 0x38, 0x00,
+ 0xc3, 0xa1, 0xaf, 0x64, 0x3b, 0x06, 0xbb, 0x64,
+ 0x74, 0x04, 0xe8, 0x2b, 0x00, 0xc3, 0xa1, 0xb1,
+ 0x64, 0x3b, 0x06, 0xbd, 0x64, 0x74, 0x04, 0xe8,
+ 0x1e, 0x00, 0xc3, 0xbb, 0x9c, 0x32, 0x8b, 0x07,
+ 0x0b, 0x47, 0x02, 0x75, 0x06, 0xb9, 0xf4, 0x01,
+ 0xe8, 0xa0, 0x73, 0xe8, 0xb0, 0x73, 0x72, 0x01,
+ 0xc3, 0xe8, 0x0f, 0x00, 0xe8, 0x01, 0x00, 0xc3,
+ 0xbb, 0x9c, 0x32, 0x33, 0xc0, 0x89, 0x07, 0x89,
+ 0x47, 0x02, 0xc3, 0xa1, 0xbf, 0x32, 0xa3, 0xac,
+ 0x00, 0x33, 0xc0, 0xa3, 0xaa, 0x00, 0xb9, 0x02,
+ 0x00, 0xba, 0x54, 0x00, 0xe8, 0x01, 0x7a, 0xbb,
+ 0x8a, 0x32, 0x33, 0xc0, 0x89, 0x07, 0x89, 0x47,
+ 0x02, 0xc6, 0x06, 0xcd, 0x64, 0x01, 0xc6, 0x06,
+ 0xcb, 0x64, 0x01, 0xc6, 0x06, 0x3f, 0x65, 0x01,
+ 0xe8, 0x22, 0x08, 0x83, 0x3e, 0xc2, 0x00, 0x00,
+ 0x74, 0x05, 0xe8, 0xb5, 0xea, 0xeb, 0x15, 0xbb,
+ 0x98, 0x32, 0x8b, 0x07, 0x0b, 0x47, 0x02, 0x75,
+ 0x06, 0xb9, 0x32, 0x00, 0xe8, 0x3c, 0x73, 0xe8,
+ 0x4c, 0x73, 0x72, 0x21, 0xe8, 0x32, 0x00, 0xe8,
+ 0xd3, 0xf5, 0xe8, 0xf1, 0xf2, 0xe8, 0x04, 0xd3,
+ 0x80, 0x3e, 0x95, 0x60, 0x01, 0x74, 0x0e, 0x80,
+ 0x3e, 0xca, 0x00, 0x01, 0x74, 0x07, 0x80, 0x3e,
+ 0xcb, 0x00, 0x01, 0x75, 0xbe, 0xe8, 0xc3, 0x75,
+ 0xe8, 0xa6, 0x08, 0xc6, 0x06, 0xdc, 0x1c, 0x02,
+ 0xe8, 0x9b, 0xf2, 0xc6, 0x06, 0xdc, 0x1c, 0x03,
+ 0xc3, 0x06, 0xbb, 0x8a, 0x32, 0xe8, 0x0e, 0x73,
+ 0x73, 0x1a, 0x8b, 0x0e, 0x90, 0x32, 0xe8, 0xf2,
+ 0x72, 0xe8, 0x1a, 0x06, 0xe8, 0x8d, 0x07, 0xc6,
+ 0x06, 0xdc, 0x1c, 0x02, 0xe8, 0x77, 0xf2, 0xc6,
+ 0x06, 0xdc, 0x1c, 0x03, 0x07, 0xc3, 0x06, 0xbb,
+ 0x8a, 0x32, 0xe8, 0xe9, 0x72, 0x73, 0x1a, 0x8b,
+ 0x0e, 0x90, 0x32, 0xe8, 0xcd, 0x72, 0xe8, 0xf5,
+ 0x05, 0xe8, 0xa4, 0x07, 0xc6, 0x06, 0xdc, 0x1c,
+ 0x02, 0xe8, 0x52, 0xf2, 0xc6, 0x06, 0xdc, 0x1c,
+ 0x03, 0x07, 0xc3, 0xe8, 0xcc, 0x6d, 0xe8, 0x54,
+ 0xf5, 0xe8, 0x1c, 0x00, 0x80, 0x3e, 0xc6, 0x64,
+ 0x00, 0x75, 0xf3, 0xc3, 0xe8, 0xbb, 0x6d, 0xe8,
+ 0x43, 0xf5, 0xe8, 0x0b, 0x00, 0xe8, 0x5e, 0xf2,
+ 0x80, 0x3e, 0xc6, 0x64, 0x00, 0x75, 0xf0, 0xc3,
+ 0x06, 0xa0, 0xc6, 0x64, 0x3c, 0x00, 0x75, 0x03,
+ 0xe9, 0xc3, 0x00, 0x3c, 0x03, 0x74, 0x39, 0xe8,
+ 0x0c, 0x02, 0x73, 0x0d, 0xe8, 0x84, 0x01, 0x72,
+ 0xf6, 0xc6, 0x06, 0xc6, 0x64, 0x00, 0xe9, 0xad,
+ 0x00, 0xc6, 0x06, 0xc4, 0x64, 0x00, 0xc6, 0x06,
+ 0xc6, 0x64, 0x03, 0xe8, 0x22, 0x08, 0x73, 0x0e,
+ 0xc6, 0x06, 0xc6, 0x64, 0x02, 0xc6, 0x06, 0xe2,
+ 0x65, 0x01, 0xff, 0x06, 0xce, 0x64, 0xbb, 0x8a,
+ 0x32, 0x33, 0xc0, 0x89, 0x07, 0x89, 0x47, 0x02,
+ 0xbb, 0x8a, 0x32, 0xe8, 0x58, 0x72, 0x72, 0x02,
+ 0xeb, 0x7c, 0x8b, 0x0e, 0x8e, 0x32, 0xe8, 0x3a,
+ 0x72, 0xe8, 0xbd, 0x05, 0xe8, 0x5f, 0x05, 0x72,
+ 0xae, 0xe8, 0xb0, 0x02, 0x72, 0xa9, 0xe8, 0x6f,
+ 0x06, 0xc6, 0x06, 0xc6, 0x64, 0x03, 0xff, 0x0e,
+ 0xce, 0x64, 0x7f, 0x4d, 0x80, 0x3e, 0xc5, 0x64,
+ 0x01, 0x75, 0x2e, 0x8b, 0x3e, 0xb7, 0x64, 0x8b,
+ 0x36, 0xb9, 0x64, 0x8b, 0x0e, 0xbb, 0x64, 0x8b,
+ 0x16, 0xbd, 0x64, 0x3b, 0xf9, 0x75, 0x04, 0x3b,
+ 0xf2, 0x74, 0x16, 0xe8, 0x3a, 0x00, 0x89, 0x3e,
+ 0xaf, 0x64, 0x89, 0x36, 0xb1, 0x64, 0x89, 0x0e,
+ 0xb7, 0x64, 0x89, 0x16, 0xb9, 0x64, 0xe9, 0x66,
+ 0xff, 0xe8, 0xc6, 0x08, 0xe8, 0x7c, 0x00, 0xe8,
+ 0x77, 0x07, 0xa1, 0xb7, 0x64, 0xa3, 0xaf, 0x64,
+ 0xa1, 0xb9, 0x64, 0xa3, 0xb1, 0x64, 0xe8, 0xb4,
+ 0x00, 0xc6, 0x06, 0xdc, 0x1c, 0x02, 0xe8, 0x5d,
+ 0xf1, 0xc6, 0x06, 0xdc, 0x1c, 0x03, 0x07, 0xc3,
+ 0x8b, 0x1e, 0x44, 0x67, 0x43, 0x43, 0xa0, 0x40,
+ 0x67, 0x3c, 0x00, 0x75, 0x1b, 0x3b, 0xd6, 0x76,
+ 0x0e, 0x8b, 0xd6, 0x3b, 0x3f, 0x77, 0x09, 0x8b,
+ 0x4f, 0x04, 0xc6, 0x06, 0x40, 0x67, 0x01, 0xc3,
+ 0x8b, 0x0f, 0xc6, 0x06, 0x40, 0x67, 0x03, 0xc3,
+ 0x3c, 0x02, 0x75, 0x05, 0x3b, 0xd6, 0x72, 0xe1,
+ 0xc3, 0x3c, 0x01, 0x75, 0x1d, 0x3b, 0xcf, 0x73,
+ 0xe6, 0x8b, 0xcf, 0x3b, 0x77, 0x02, 0x77, 0x09,
+ 0x8b, 0x57, 0x06, 0xc6, 0x06, 0x40, 0x67, 0x02,
+ 0xc3, 0x8b, 0x57, 0x02, 0xc6, 0x06, 0x40, 0x67,
+ 0x00, 0xc3, 0x3c, 0x03, 0x75, 0xc9, 0x3b, 0xcf,
+ 0x77, 0xdf, 0xc3, 0xa0, 0xc3, 0x64, 0x0a, 0xc0,
+ 0x74, 0x42, 0x3c, 0x01, 0x75, 0x0a, 0xc6, 0x06,
+ 0xcb, 0x64, 0x01, 0xc6, 0x06, 0xcd, 0x64, 0x00,
+ 0x3c, 0x03, 0x75, 0x0a, 0xc6, 0x06, 0xcb, 0x64,
+ 0x01, 0xc6, 0x06, 0xcd, 0x64, 0x01, 0x3c, 0x02,
+ 0x75, 0x0f, 0xc6, 0x06, 0xcb, 0x64, 0x00, 0xc6,
+ 0x06, 0xcc, 0x64, 0x01, 0xc6, 0x06, 0xdc, 0x64,
+ 0x00, 0x3c, 0x04, 0x75, 0x0f, 0xc6, 0x06, 0xcb,
+ 0x64, 0x00, 0xc6, 0x06, 0xcc, 0x64, 0x00, 0xc6,
+ 0x06, 0xdc, 0x64, 0x01, 0xc3, 0xc6, 0x06, 0xc3,
+ 0x64, 0x00, 0xa0, 0x3d, 0x66, 0x3c, 0x01, 0x75,
+ 0x06, 0xc6, 0x06, 0x3d, 0x66, 0x02, 0xc3, 0x3c,
+ 0x03, 0x75, 0x06, 0xc6, 0x06, 0x3d, 0x66, 0x04,
+ 0xc3, 0x3c, 0x05, 0x75, 0x05, 0xc6, 0x06, 0x3d,
+ 0x66, 0x06, 0xc3, 0x8a, 0x0e, 0xc3, 0x64, 0x0a,
+ 0xc9, 0x74, 0x69, 0xa0, 0xcc, 0x64, 0x8a, 0x26,
+ 0xcd, 0x64, 0x8a, 0x2e, 0xcb, 0x64, 0x80, 0xf9,
+ 0x01, 0x75, 0x13, 0x80, 0xfc, 0x00, 0x75, 0x05,
+ 0x80, 0xfd, 0x01, 0x74, 0x4f, 0xe8, 0x51, 0x00,
+ 0xff, 0x06, 0xb1, 0x64, 0xf9, 0xc3, 0x80, 0xf9,
+ 0x03, 0x75, 0x13, 0x80, 0xfc, 0x01, 0x75, 0x05,
+ 0x80, 0xfd, 0x01, 0x74, 0x37, 0xe8, 0x39, 0x00,
+ 0xff, 0x0e, 0xb1, 0x64, 0xf9, 0xc3, 0x80, 0xf9,
+ 0x02, 0x75, 0x12, 0x3c, 0x01, 0x75, 0x05, 0x80,
+ 0xfd, 0x00, 0x74, 0x20, 0xe8, 0x22, 0x00, 0xff,
+ 0x0e, 0xaf, 0x64, 0xf9, 0xc3, 0x80, 0xf9, 0x04,
+ 0x75, 0x12, 0x3c, 0x00, 0x75, 0x05, 0x80, 0xfd,
+ 0x00, 0x74, 0x09, 0xe8, 0x0b, 0x00, 0xff, 0x06,
+ 0xaf, 0x64, 0xf9, 0xc3, 0xe8, 0x66, 0xff, 0xf8,
+ 0xc3, 0xa1, 0xaf, 0x64, 0xa3, 0xb7, 0x64, 0xa1,
+ 0xb1, 0x64, 0xa3, 0xb9, 0x64, 0xc3, 0x33, 0xc9,
+ 0xa1, 0xb7, 0x64, 0x8b, 0x1e, 0xaf, 0x64, 0x3b,
+ 0xc3, 0x77, 0x03, 0xfe, 0xc1, 0x93, 0x2b, 0xc3,
+ 0xa3, 0xc7, 0x64, 0xa1, 0xb9, 0x64, 0x8b, 0x1e,
+ 0xb1, 0x64, 0x3b, 0xc3, 0x77, 0x03, 0xfe, 0xc5,
+ 0x93, 0x2b, 0xc3, 0xa3, 0xc9, 0x64, 0x8b, 0x1e,
+ 0xc7, 0x64, 0xa1, 0xc9, 0x64, 0x0b, 0xdb, 0x74,
+ 0x0d, 0xc6, 0x06, 0xcc, 0x64, 0x01, 0x0a, 0xc9,
+ 0x74, 0x04, 0xfe, 0x0e, 0xcc, 0x64, 0x0b, 0xc0,
+ 0x74, 0x0d, 0xc6, 0x06, 0xcd, 0x64, 0x01, 0x0a,
+ 0xed, 0x74, 0x04, 0xfe, 0x0e, 0xcd, 0x64, 0x8b,
+ 0xd0, 0x0b, 0xc0, 0x0b, 0xc3, 0x75, 0x02, 0xf9,
+ 0xc3, 0x8b, 0xc2, 0xb9, 0x10, 0x00, 0xf7, 0xe1,
+ 0xb9, 0x0a, 0x00, 0xf7, 0xf1, 0x3b, 0xc3, 0x77,
+ 0x3e, 0xa0, 0xdc, 0x64, 0xa2, 0xdd, 0x64, 0xc6,
+ 0x06, 0xdc, 0x64, 0x00, 0xc6, 0x06, 0xcb, 0x64,
+ 0x00, 0x80, 0x3e, 0xcc, 0x64, 0x01, 0x74, 0x05,
+ 0xc6, 0x06, 0xdc, 0x64, 0x01, 0xa1, 0xc7, 0x64,
+ 0x8b, 0x1e, 0xb5, 0x64, 0x33, 0xd2, 0xf7, 0xf3,
+ 0xa3, 0xce, 0x64, 0xa1, 0xb5, 0x64, 0x8b, 0x1e,
+ 0xc9, 0x64, 0xb9, 0xe8, 0x03, 0xf7, 0xe3, 0xf7,
+ 0xe1, 0x8b, 0x1e, 0xc7, 0x64, 0xeb, 0x25, 0xc6,
+ 0x06, 0xcb, 0x64, 0x01, 0xa1, 0xc9, 0x64, 0x8b,
+ 0x1e, 0xb3, 0x64, 0x33, 0xd2, 0xf7, 0xf3, 0xa3,
+ 0xce, 0x64, 0xa1, 0xb3, 0x64, 0x8b, 0x1e, 0xc7,
+ 0x64, 0xb9, 0xe8, 0x03, 0xf7, 0xe3, 0xf7, 0xe1,
+ 0x8b, 0x1e, 0xc9, 0x64, 0xf7, 0xf3, 0xbb, 0xd0,
+ 0x64, 0x89, 0x07, 0xc7, 0x47, 0x02, 0x00, 0x00,
+ 0xbb, 0xd4, 0x64, 0x89, 0x07, 0xc7, 0x47, 0x02,
+ 0x00, 0x00, 0x80, 0x3e, 0xc4, 0x64, 0x01, 0x75,
+ 0x05, 0xc6, 0x06, 0xe2, 0x65, 0x01, 0xff, 0x06,
+ 0xce, 0x64, 0xf8, 0xc3, 0x83, 0x3e, 0xce, 0x64,
+ 0x01, 0x75, 0x02, 0xf8, 0xc3, 0x8b, 0x36, 0xaf,
+ 0x64, 0x8b, 0x3e, 0xb1, 0x64, 0xe8, 0x2e, 0x02,
+ 0x72, 0x01, 0xc3, 0x8b, 0x36, 0x44, 0x67, 0x3b,
+ 0xde, 0x74, 0x0f, 0x89, 0x1e, 0x44, 0x67, 0x8a,
+ 0x04, 0x3a, 0x07, 0x74, 0x05, 0xc6, 0x06, 0x40,
+ 0x67, 0xff, 0xc6, 0x06, 0xc5, 0x64, 0x01, 0xa0,
+ 0xcc, 0x64, 0x8a, 0x26, 0xcd, 0x64, 0x0a, 0xe4,
+ 0x74, 0x15, 0xc6, 0x06, 0x42, 0x67, 0x01, 0xc6,
+ 0x06, 0x43, 0x67, 0x01, 0x0a, 0xc0, 0x74, 0x1a,
+ 0xc6, 0x06, 0x43, 0x67, 0x00, 0xeb, 0x13, 0xc6,
+ 0x06, 0x42, 0x67, 0x00, 0xc6, 0x06, 0x43, 0x67,
+ 0x01, 0x0a, 0xc0, 0x74, 0x05, 0xc6, 0x06, 0x43,
+ 0x67, 0x00, 0x43, 0x43, 0x53, 0x8b, 0x0f, 0x41,
+ 0x8b, 0x7f, 0x02, 0x47, 0x8b, 0x77, 0x04, 0x4e,
+ 0x8b, 0x5f, 0x06, 0x4b, 0xa1, 0xbf, 0x64, 0x8b,
+ 0x16, 0xc1, 0x64, 0x3b, 0xc1, 0x72, 0x17, 0x3b,
+ 0xc6, 0x77, 0x13, 0xc6, 0x06, 0x41, 0x67, 0x00,
+ 0x80, 0x3e, 0x42, 0x67, 0x01, 0x74, 0x4f, 0xc6,
+ 0x06, 0x41, 0x67, 0x02, 0xeb, 0x48, 0x3b, 0xd7,
+ 0x72, 0x17, 0x3b, 0xd3, 0x77, 0x13, 0xc6, 0x06,
+ 0x41, 0x67, 0x01, 0x80, 0x3e, 0x43, 0x67, 0x01,
+ 0x74, 0x34, 0xc6, 0x06, 0x41, 0x67, 0x03, 0xeb,
+ 0x2d, 0x80, 0x3e, 0xcb, 0x64, 0x00, 0x75, 0x13,
+ 0xc6, 0x06, 0x41, 0x67, 0x01, 0x80, 0x3e, 0x43,
+ 0x67, 0x01, 0x74, 0x1a, 0xc6, 0x06, 0x41, 0x67,
+ 0x03, 0xeb, 0x13, 0xc6, 0x06, 0x41, 0x67, 0x00,
+ 0x80, 0x3e, 0x42, 0x67, 0x01, 0x74, 0x07, 0xc6,
+ 0x06, 0x41, 0x67, 0x02, 0xeb, 0x00, 0x5b, 0x53,
+ 0x83, 0xc3, 0x08, 0xa0, 0x41, 0x67, 0xb4, 0x00,
+ 0x03, 0xd8, 0x8a, 0x07, 0x5b, 0x8a, 0x36, 0x40,
+ 0x67, 0x0a, 0xc0, 0x74, 0x18, 0x3c, 0x01, 0x74,
+ 0x35, 0x3c, 0x02, 0x74, 0x56, 0x3c, 0x03, 0x74,
+ 0x77, 0x3c, 0x04, 0x75, 0x03, 0xe9, 0x95, 0x00,
+ 0xb0, 0x34, 0xe9, 0xf3, 0x78, 0xa0, 0xcd, 0x64,
+ 0x8a, 0x26, 0xcc, 0x64, 0x8a, 0x16, 0x41, 0x67,
+ 0x80, 0xfa, 0x01, 0x74, 0x05, 0x80, 0xfa, 0x03,
+ 0x75, 0x06, 0x0a, 0xc0, 0x74, 0x08, 0xeb, 0x50,
+ 0x0a, 0xe4, 0x75, 0x27, 0xeb, 0x6f, 0x80, 0xfe,
+ 0x02, 0x75, 0x09, 0x80, 0x3e, 0xcc, 0x64, 0x01,
+ 0x74, 0x19, 0xeb, 0x61, 0x80, 0xfe, 0x00, 0x74,
+ 0xf2, 0xa1, 0xbf, 0x64, 0xa3, 0xb7, 0x64, 0x83,
+ 0xc3, 0x02, 0x8b, 0x07, 0xa3, 0xb9, 0x64, 0xb0,
+ 0x00, 0xeb, 0x6a, 0x80, 0xfe, 0x03, 0x75, 0x09,
+ 0x80, 0x3e, 0xcd, 0x64, 0x01, 0x75, 0xcf, 0xeb,
+ 0x17, 0x80, 0xfe, 0x01, 0x74, 0xf2, 0xa1, 0xc1,
+ 0x64, 0xa3, 0xb9, 0x64, 0x83, 0xc3, 0x04, 0x8b,
+ 0x07, 0xa3, 0xb7, 0x64, 0xb0, 0x01, 0xeb, 0x45,
+ 0x80, 0xfe, 0x00, 0x75, 0x09, 0x80, 0x3e, 0xcc,
+ 0x64, 0x01, 0x75, 0x19, 0xeb, 0xcd, 0x80, 0xfe,
+ 0x02, 0x74, 0xf2, 0xa1, 0xbf, 0x64, 0xa3, 0xb7,
+ 0x64, 0x83, 0xc3, 0x06, 0x8b, 0x07, 0xa3, 0xb9,
+ 0x64, 0xb0, 0x02, 0xeb, 0x20, 0x80, 0xfe, 0x01,
+ 0x75, 0x09, 0x80, 0x3e, 0xcd, 0x64, 0x01, 0x74,
+ 0xcf, 0xeb, 0x83, 0x80, 0xfe, 0x03, 0x74, 0xf2,
+ 0xa1, 0xc1, 0x64, 0xa3, 0xb9, 0x64, 0x8b, 0x07,
+ 0xa3, 0xb7, 0x64, 0xb0, 0x03, 0xa2, 0x40, 0x67,
+ 0xa1, 0xbf, 0x64, 0xa3, 0xaf, 0x64, 0xa1, 0xc1,
+ 0x64, 0xa3, 0xb1, 0x64, 0xf9, 0xc3, 0x81, 0xfe,
+ 0x3f, 0x01, 0x75, 0x01, 0x4e, 0x0b, 0xf6, 0x75,
+ 0x01, 0x46, 0x81, 0xff, 0xc7, 0x00, 0x75, 0x01,
+ 0x4f, 0x0b, 0xff, 0x75, 0x01, 0x47, 0xe8, 0x89,
+ 0x00, 0x73, 0x29, 0x43, 0x8a, 0x07, 0x0a, 0xc0,
+ 0x74, 0x08, 0xe8, 0x20, 0x00, 0xe8, 0x7a, 0x00,
+ 0x73, 0x1a, 0xe8, 0x14, 0x03, 0xc6, 0x06, 0xdc,
+ 0x1c, 0x02, 0xe8, 0x09, 0xed, 0xc6, 0x06, 0xdc,
+ 0x1c, 0x03, 0xa1, 0xaf, 0x64, 0x8b, 0xf0, 0xa1,
+ 0xb1, 0x64, 0x8b, 0xf8, 0xc3, 0x43, 0x3c, 0x01,
+ 0x75, 0x05, 0x8b, 0x7f, 0x02, 0x4f, 0xc3, 0x3c,
+ 0x03, 0x75, 0x05, 0x8b, 0x7f, 0x06, 0x47, 0xc3,
+ 0x3c, 0x02, 0x75, 0x05, 0x8b, 0x77, 0x04, 0x46,
+ 0xc3, 0x3c, 0x04, 0x75, 0x04, 0x8b, 0x37, 0x4e,
+ 0xc3, 0xb0, 0x3a, 0xe9, 0xc2, 0x77, 0xbb, 0x46,
+ 0x67, 0xe8, 0x2e, 0x04, 0x8a, 0x0f, 0x0a, 0xc9,
+ 0x74, 0x24, 0xb5, 0x00, 0x43, 0x8b, 0x47, 0x02,
+ 0x8b, 0x57, 0x06, 0x3b, 0xf0, 0x76, 0x12, 0x3b,
+ 0xf2, 0x73, 0x0e, 0x8b, 0x47, 0x04, 0x8b, 0x57,
+ 0x08, 0x3b, 0xf8, 0x76, 0x04, 0x3b, 0xfa, 0x72,
+ 0x07, 0x83, 0xc3, 0x0e, 0xe2, 0xdf, 0xf8, 0xc3,
+ 0xf9, 0xc3, 0xbb, 0x46, 0x67, 0xe8, 0xfa, 0x03,
+ 0x8a, 0x0f, 0x0a, 0xc9, 0x74, 0x24, 0xb5, 0x00,
+ 0x43, 0x8b, 0x47, 0x02, 0x8b, 0x57, 0x06, 0x3b,
+ 0xf0, 0x72, 0x12, 0x3b, 0xf2, 0x77, 0x0e, 0x8b,
+ 0x47, 0x04, 0x8b, 0x57, 0x08, 0x3b, 0xf8, 0x72,
+ 0x04, 0x3b, 0xfa, 0x76, 0x07, 0x83, 0xc3, 0x0e,
+ 0xe2, 0xdf, 0xf8, 0xc3, 0xf9, 0xc3, 0xbb, 0xf4,
+ 0x70, 0xe8, 0xc6, 0x03, 0x8b, 0x07, 0x3d, 0xff,
+ 0xff, 0x74, 0x4c, 0x43, 0x43, 0x8b, 0x0e, 0xb1,
+ 0x64, 0x3a, 0xc8, 0x77, 0xef, 0x8a, 0xc4, 0xb4,
+ 0x00, 0xa3, 0xd8, 0x64, 0xe8, 0x25, 0x03, 0x83,
+ 0x3e, 0xce, 0x64, 0x02, 0x76, 0x31, 0x83, 0x3e,
+ 0xd8, 0x64, 0x1e, 0x72, 0x15, 0x83, 0x3e, 0xb3,
+ 0x64, 0x01, 0x74, 0x23, 0xc7, 0x06, 0xb3, 0x64,
+ 0x01, 0x00, 0xc7, 0x06, 0xb5, 0x64, 0x04, 0x00,
+ 0xf9, 0xc3, 0x83, 0x3e, 0xb3, 0x64, 0x03, 0x74,
+ 0x0e, 0xc7, 0x06, 0xb3, 0x64, 0x03, 0x00, 0xc7,
+ 0x06, 0xb5, 0x64, 0x08, 0x00, 0xf9, 0xc3, 0xf8,
+ 0xc3, 0x80, 0x3e, 0xc6, 0x64, 0x02, 0x75, 0x01,
+ 0xc3, 0xa1, 0xaf, 0x64, 0xa3, 0xbf, 0x64, 0xa1,
+ 0xb1, 0x64, 0xa3, 0xc1, 0x64, 0x80, 0x3e, 0xcb,
+ 0x64, 0x00, 0x75, 0x36, 0xa1, 0xb5, 0x64, 0x80,
+ 0x3e, 0xcc, 0x64, 0x01, 0x75, 0x06, 0x01, 0x06,
+ 0xaf, 0x64, 0xeb, 0x04, 0x29, 0x06, 0xaf, 0x64,
+ 0xbb, 0xd4, 0x64, 0x8b, 0x07, 0x8b, 0x57, 0x02,
+ 0xb9, 0xe8, 0x03, 0xf7, 0xf1, 0x80, 0x3e, 0xcd,
+ 0x64, 0x01, 0x75, 0x06, 0x01, 0x06, 0xb1, 0x64,
+ 0xeb, 0x04, 0x29, 0x06, 0xb1, 0x64, 0xe8, 0x37,
+ 0x00, 0xc3, 0xa1, 0xb3, 0x64, 0x80, 0x3e, 0xcd,
+ 0x64, 0x01, 0x75, 0x06, 0x01, 0x06, 0xb1, 0x64,
+ 0xeb, 0x04, 0x29, 0x06, 0xb1, 0x64, 0xbb, 0xd4,
+ 0x64, 0x8b, 0x07, 0x8b, 0x57, 0x02, 0xb9, 0xe8,
+ 0x03, 0xf7, 0xf1, 0x80, 0x3e, 0xcc, 0x64, 0x01,
+ 0x75, 0x06, 0x01, 0x06, 0xaf, 0x64, 0xeb, 0x04,
+ 0x29, 0x06, 0xaf, 0x64, 0xe8, 0x01, 0x00, 0xc3,
+ 0x50, 0xbb, 0xd4, 0x64, 0x8b, 0x07, 0x8b, 0x57,
+ 0x02, 0xbe, 0xd0, 0x64, 0x8b, 0x1c, 0x8b, 0x4c,
+ 0x02, 0x03, 0xc3, 0x83, 0xd2, 0x00, 0x03, 0xd1,
+ 0xbb, 0xd4, 0x64, 0x89, 0x07, 0x89, 0x57, 0x02,
+ 0x58, 0xb9, 0xe8, 0x03, 0xf7, 0xe1, 0x8b, 0xc8,
+ 0x8b, 0x07, 0x8b, 0x57, 0x02, 0x2b, 0xc1, 0x83,
+ 0xda, 0x00, 0x89, 0x07, 0x89, 0x57, 0x02, 0xc3,
+ 0x8a, 0x0e, 0x07, 0x66, 0x80, 0x3e, 0xc6, 0x64,
+ 0x02, 0x74, 0x4d, 0x80, 0x3e, 0xcb, 0x64, 0x00,
+ 0x75, 0x0f, 0xbb, 0xed, 0x65, 0x80, 0x3e, 0xcc,
+ 0x64, 0x01, 0x74, 0x1e, 0xbb, 0xe3, 0x65, 0xeb,
+ 0x19, 0x80, 0x3e, 0xe2, 0x65, 0x07, 0x76, 0x05,
+ 0xc6, 0x06, 0xe2, 0x65, 0x01, 0xbb, 0xff, 0x65,
+ 0x80, 0x3e, 0xcd, 0x64, 0x01, 0x74, 0x03, 0xbb,
+ 0xf7, 0x65, 0x8a, 0x0e, 0xe2, 0x65, 0xb5, 0x00,
+ 0x49, 0x03, 0xd9, 0x8a, 0x0f, 0x0a, 0xc9, 0x75,
+ 0x07, 0xc6, 0x06, 0xe2, 0x65, 0x01, 0xeb, 0xbb,
+ 0x88, 0x0e, 0x07, 0x66, 0xfe, 0x06, 0xe2, 0x65,
+ 0xe8, 0xdd, 0x00, 0xc3, 0x8b, 0x1e, 0x3d, 0x65,
+ 0x8a, 0x0e, 0x3f, 0x65, 0xb5, 0x00, 0x49, 0x03,
+ 0xd9, 0x8a, 0x0f, 0x0a, 0xc9, 0x75, 0x0a, 0xc6,
+ 0x06, 0x3f, 0x65, 0x04, 0xe8, 0x0e, 0x00, 0xeb,
+ 0xe3, 0x88, 0x0e, 0x07, 0x66, 0xfe, 0x06, 0x3f,
+ 0x65, 0xe8, 0xb4, 0x00, 0xc3, 0xb8, 0x03, 0x00,
+ 0xe8, 0xb0, 0x73, 0xbb, 0x40, 0x65, 0xd1, 0xe0,
+ 0x03, 0xd8, 0x8b, 0x07, 0xa3, 0x3d, 0x65, 0xc3,
+ 0x80, 0x3e, 0xcb, 0x64, 0x00, 0x75, 0x13, 0xbb,
+ 0xfe, 0x64, 0xb2, 0x01, 0x80, 0x3e, 0xcc, 0x64,
+ 0x01, 0x74, 0x18, 0xbb, 0xe9, 0x64, 0xb2, 0x01,
+ 0xeb, 0x11, 0xbb, 0x28, 0x65, 0xb2, 0x0b, 0x80,
+ 0x3e, 0xcd, 0x64, 0x01, 0x74, 0x05, 0xbb, 0x13,
+ 0x65, 0xb2, 0x13, 0x8a, 0x0e, 0xe8, 0x64, 0xb5,
+ 0x00, 0x49, 0x03, 0xd9, 0x8a, 0x0f, 0x0a, 0xc9,
+ 0x75, 0x07, 0xc6, 0x06, 0xe8, 0x64, 0x01, 0xeb,
+ 0xbf, 0xfe, 0x06, 0xe8, 0x64, 0xe8, 0x58, 0x00,
+ 0x1e, 0x53, 0x8a, 0xca, 0x88, 0x0e, 0x07, 0x66,
+ 0xe8, 0x4d, 0x00, 0x8b, 0xf3, 0x5b, 0xa1, 0xbf,
+ 0x32, 0x8e, 0xd8, 0x8b, 0x07, 0x8b, 0x4f, 0x02,
+ 0xf7, 0xe1, 0x8b, 0xc8, 0xb8, 0x06, 0x00, 0x03,
+ 0xd8, 0x03, 0xf0, 0x8a, 0x07, 0x88, 0x04, 0x43,
+ 0x46, 0xe2, 0xf8, 0x1f, 0xc3, 0x33, 0xc9, 0x80,
+ 0x3e, 0xcb, 0x64, 0x00, 0x75, 0x11, 0xb2, 0x01,
+ 0xb1, 0x28, 0x80, 0x3e, 0xcc, 0x64, 0x01, 0x74,
+ 0xb8, 0xb2, 0x01, 0xb1, 0x28, 0xeb, 0xb2, 0xb2,
+ 0x0b, 0xb1, 0x29, 0x80, 0x3e, 0xcd, 0x64, 0x01,
+ 0x74, 0xa7, 0xb2, 0x13, 0xb1, 0x2a, 0xeb, 0xa1,
+ 0x06, 0xa1, 0xbf, 0x32, 0x8e, 0xc0, 0x32, 0xed,
+ 0xbb, 0x01, 0x00, 0x49, 0xd1, 0xe1, 0x03, 0xd9,
+ 0x26, 0x8b, 0x1f, 0x89, 0x1e, 0xe6, 0x64, 0x07,
+ 0xc3, 0x80, 0x3e, 0xcb, 0x64, 0x00, 0x75, 0x0d,
+ 0xb1, 0x01, 0x80, 0x3e, 0xcc, 0x64, 0x01, 0x74,
+ 0x0f, 0xb1, 0x01, 0xeb, 0x0b, 0xb1, 0x0b, 0x80,
+ 0x3e, 0xcd, 0x64, 0x01, 0x74, 0x02, 0xb1, 0x13,
+ 0x88, 0x0e, 0x07, 0x66, 0xe8, 0xc1, 0xff, 0xc3,
+ 0xa0, 0x07, 0x66, 0x8a, 0x26, 0xcb, 0x64, 0x8a,
+ 0x1e, 0xcc, 0x64, 0x8a, 0x3e, 0xcd, 0x64, 0x83,
+ 0x3e, 0xce, 0x64, 0x01, 0x75, 0x44, 0x3c, 0x13,
+ 0x75, 0x0f, 0x80, 0xfc, 0x01, 0x75, 0x3b, 0x80,
+ 0xff, 0x00, 0x75, 0x36, 0xb1, 0x14, 0xe9, 0x85,
+ 0x00, 0x3c, 0x0b, 0x75, 0x0e, 0x80, 0xfc, 0x01,
+ 0x75, 0x28, 0x80, 0xff, 0x01, 0x75, 0x23, 0xb1,
+ 0x0c, 0xeb, 0x73, 0x3c, 0x01, 0x75, 0x1b, 0xa0,
+ 0xdd, 0x64, 0x3a, 0x06, 0xdc, 0x64, 0x75, 0x12,
+ 0x80, 0xfc, 0x00, 0x75, 0x0d, 0x80, 0xfb, 0x01,
+ 0x75, 0x04, 0xb1, 0x02, 0xeb, 0x58, 0xb1, 0x02,
+ 0xeb, 0x54, 0xa0, 0x07, 0x66, 0x3c, 0x13, 0x72,
+ 0x12, 0x3c, 0x1a, 0x77, 0x0e, 0x80, 0xfc, 0x01,
+ 0x75, 0x42, 0x80, 0xff, 0x01, 0x75, 0x3d, 0xb1,
+ 0x02, 0xeb, 0x3b, 0x3c, 0x01, 0x72, 0x1f, 0x3c,
+ 0x0a, 0x77, 0x1b, 0x80, 0xfc, 0x00, 0x75, 0x2c,
+ 0xa0, 0xdd, 0x64, 0x38, 0x06, 0xdc, 0x64, 0x74,
+ 0x23, 0x80, 0xfb, 0x01, 0x75, 0x04, 0xb1, 0x0c,
+ 0xeb, 0x1c, 0xb1, 0x0c, 0xeb, 0x18, 0x3c, 0x0b,
+ 0x72, 0x12, 0x3c, 0x12, 0x77, 0x0e, 0x80, 0xfc,
+ 0x01, 0x75, 0x09, 0x80, 0xff, 0x00, 0x75, 0x04,
+ 0xb1, 0x02, 0xeb, 0x02, 0xf8, 0xc3, 0x88, 0x0e,
+ 0x07, 0x66, 0xf9, 0xc3, 0xa1, 0xd8, 0x64, 0x3d,
+ 0x64, 0x00, 0x77, 0x28, 0x53, 0x1e, 0x8b, 0x16,
+ 0xb1, 0x32, 0x8e, 0xda, 0xbb, 0x00, 0xfa, 0xba,
+ 0xff, 0xff, 0x0b, 0xc0, 0x74, 0x09, 0x8b, 0xc8,
+ 0xb8, 0x64, 0x00, 0x33, 0xd2, 0xf7, 0xf1, 0x89,
+ 0x57, 0x02, 0xb9, 0x64, 0x00, 0xf7, 0xe1, 0x89,
+ 0x07, 0x1f, 0x5b, 0xc3, 0xb0, 0x35, 0xe9, 0xdf,
+ 0x73, 0x80, 0x3e, 0xae, 0x64, 0x01, 0x75, 0x08,
+ 0x81, 0x3e, 0xba, 0x00, 0x3f, 0x01, 0x75, 0x18,
+ 0x8b, 0x0e, 0x32, 0x32, 0x3b, 0xca, 0x77, 0x0a,
+ 0x8b, 0x0e, 0x34, 0x32, 0x3b, 0xca, 0x73, 0x08,
+ 0xf8, 0xc3, 0x3b, 0xce, 0x76, 0x02, 0xf8, 0xc3,
+ 0x8b, 0x0e, 0xb1, 0x64, 0x3b, 0xcf, 0x76, 0x02,
+ 0xf8, 0xc3, 0x3b, 0xc8, 0x73, 0x02, 0xf8, 0xc3,
+ 0xf9, 0xc3, 0xc6, 0x06, 0xc6, 0x64, 0x00, 0xc6,
+ 0x06, 0x40, 0x67, 0xff, 0xc6, 0x06, 0xc4, 0x64,
+ 0x01, 0xc6, 0x06, 0xc5, 0x64, 0x00, 0xe8, 0x77,
+ 0xf5, 0xc3, 0x51, 0x8b, 0x0e, 0xf3, 0xb4, 0x49,
+ 0xd1, 0xe1, 0x03, 0xd9, 0x8b, 0x1f, 0x59, 0xc3,
+ 0xbb, 0xf5, 0xb4, 0xeb, 0xed, 0xc7, 0x06, 0xf3,
+ 0xb4, 0x03, 0x00, 0xb8, 0x3f, 0x01, 0xbb, 0x68,
+ 0x00, 0xbf, 0x22, 0x01, 0xbe, 0x76, 0x00, 0xb1,
+ 0x01, 0xb5, 0x04, 0xe8, 0xdd, 0x6b, 0xc3, 0xc7,
+ 0x06, 0xf3, 0xb4, 0x05, 0x00, 0xb8, 0x2c, 0x01,
+ 0xbb, 0x83, 0x00, 0xbf, 0x2c, 0x01, 0xbe, 0x87,
+ 0x00, 0xb1, 0x0b, 0xb5, 0x03, 0xe8, 0xc3, 0x6b,
+ 0xc3, 0x80, 0x3e, 0xe1, 0xdb, 0x01, 0x74, 0x07,
+ 0xbb, 0x0f, 0x57, 0xe8, 0x27, 0x60, 0xc3, 0xb9,
+ 0x4c, 0x03, 0xe8, 0xba, 0xda, 0xb9, 0x4e, 0x03,
+ 0xe8, 0xb7, 0xda, 0xb9, 0x4d, 0x03, 0xe8, 0xd6,
+ 0xda, 0xbb, 0x96, 0x56, 0xe8, 0x0e, 0x60, 0xc3,
+ 0xbb, 0xac, 0x56, 0xe8, 0x07, 0x60, 0xc3, 0xbb,
+ 0xf7, 0x56, 0xe8, 0x00, 0x60, 0xc3, 0xbb, 0x7a,
+ 0xdb, 0xe8, 0x51, 0xd1, 0xe8, 0x66, 0xd1, 0xc3,
+ 0xc7, 0x06, 0xf3, 0xb4, 0x02, 0x00, 0xb8, 0x00,
+ 0x00, 0xbb, 0xb4, 0x00, 0xbf, 0x38, 0x00, 0xbe,
+ 0xb4, 0x00, 0xb1, 0x01, 0xb5, 0x02, 0xe8, 0x6a,
+ 0x6b, 0xc3, 0xc7, 0x06, 0xf3, 0xb4, 0x04, 0x00,
+ 0xb8, 0x3f, 0x01, 0xbb, 0x80, 0x00, 0xbf, 0x13,
+ 0x01, 0xbe, 0x89, 0x00, 0xb1, 0x01, 0xb5, 0x04,
+ 0xe8, 0x50, 0x6b, 0xc3, 0x80, 0x3e, 0xe4, 0xdb,
+ 0x01, 0x75, 0x07, 0xbb, 0xb2, 0x57, 0xe8, 0xb4,
+ 0x5f, 0xc3, 0xb9, 0x4c, 0x00, 0xb0, 0x0b, 0xb4,
+ 0x07, 0xe8, 0x51, 0x69, 0xb0, 0x0f, 0xe8, 0x55,
+ 0x69, 0xb0, 0x13, 0xe8, 0x57, 0x69, 0xb0, 0x17,
+ 0xe8, 0x59, 0x69, 0xb0, 0x1b, 0xe8, 0x5b, 0x69,
+ 0xb9, 0x38, 0x00, 0xb0, 0x23, 0xe8, 0x5a, 0x69,
+ 0xb9, 0x13, 0x00, 0xb0, 0x3b, 0xe8, 0x59, 0x69,
+ 0xb9, 0x60, 0x03, 0xe8, 0x19, 0xda, 0xe8, 0xba,
+ 0x6a, 0xc6, 0x06, 0xdc, 0x1c, 0x01, 0xbb, 0x47,
+ 0x33, 0xc7, 0x47, 0x02, 0x61, 0x03, 0xb0, 0x02,
+ 0xe8, 0x3c, 0xd9, 0xc6, 0x06, 0xb0, 0x32, 0x01,
+ 0xe8, 0x91, 0xdd, 0xc6, 0x06, 0xb0, 0x32, 0x00,
+ 0x9c, 0xe8, 0xa2, 0x69, 0xb9, 0x62, 0x03, 0xc6,
+ 0x06, 0xdc, 0x1c, 0x02, 0xe8, 0xeb, 0xd9, 0x9d,
+ 0x73, 0x4c, 0xa1, 0x1f, 0xc4, 0xe8, 0x54, 0xe7,
+ 0x3c, 0x55, 0x75, 0x42, 0x83, 0x3e, 0x52, 0x72,
+ 0x05, 0x75, 0x3b, 0xc6, 0x06, 0xcf, 0x00, 0x00,
+ 0xc7, 0x06, 0x1f, 0xc4, 0x00, 0x00, 0xb9, 0x05,
+ 0x00, 0xb0, 0x04, 0xb4, 0x06, 0xe8, 0xcd, 0x68,
+ 0xb0, 0x13, 0xe8, 0xd8, 0x68, 0xb9, 0x40, 0x00,
+ 0xb0, 0x0b, 0xe8, 0xc9, 0x68, 0xb9, 0x63, 0x03,
+ 0xe8, 0xaf, 0xd9, 0xb0, 0x55, 0xe8, 0x00, 0xe6,
+ 0xb0, 0x56, 0xe8, 0xeb, 0xe5, 0xc6, 0x06, 0xe4,
+ 0xdb, 0x01, 0xe8, 0x1e, 0x00, 0xc3, 0xe8, 0x1a,
+ 0x00, 0xff, 0x36, 0xcf, 0x00, 0xc6, 0x06, 0xcf,
+ 0x00, 0x00, 0xbb, 0x72, 0xdb, 0xe8, 0x45, 0xd0,
+ 0xe8, 0x5a, 0xd0, 0x8f, 0x06, 0xcf, 0x00, 0xe8,
+ 0xdc, 0xdd, 0xc3, 0xc7, 0x06, 0xaf, 0x64, 0x56,
+ 0x00, 0xc7, 0x06, 0xb1, 0x64, 0xc3, 0x00, 0xc6,
+ 0x06, 0xcc, 0x64, 0x00, 0xc6, 0x06, 0xcd, 0x64,
+ 0x01, 0xc6, 0x06, 0xcb, 0x64, 0x01, 0xb9, 0x64,
+ 0x03, 0xe8, 0x83, 0xd9, 0xc3, 0xbb, 0xb7, 0x58,
+ 0xe8, 0xba, 0x5e, 0xc3, 0xb9, 0x38, 0x00, 0xb0,
+ 0x0a, 0xb4, 0x09, 0xe8, 0x57, 0x68, 0xe8, 0xae,
+ 0xd9, 0xe8, 0x3c, 0xfe, 0xc6, 0x07, 0x00, 0xe8,
+ 0xc2, 0x6c, 0xb9, 0x6b, 0x03, 0xe8, 0x6d, 0xd9,
+ 0xb0, 0x06, 0xe8, 0x28, 0xd8, 0xb0, 0x5c, 0xe8,
+ 0x76, 0xe5, 0xc3, 0xbb, 0x0f, 0x57, 0xe8, 0x8c,
+ 0x5e, 0xc3, 0xe8, 0x09, 0x63, 0xc3, 0xe8, 0x86,
+ 0xd9, 0xbb, 0x46, 0x67, 0xe8, 0x03, 0xfe, 0x83,
+ 0xc3, 0x03, 0xff, 0x37, 0x53, 0xc7, 0x07, 0x3f,
+ 0x01, 0xbe, 0xc5, 0x00, 0xbf, 0x9f, 0x00, 0xc6,
+ 0x06, 0xc3, 0x64, 0x04, 0xe8, 0x3c, 0xf4, 0xe8,
+ 0xf6, 0xfd, 0xc6, 0x07, 0x00, 0xe8, 0x7c, 0x6c,
+ 0xb9, 0x47, 0x00, 0xb0, 0x08, 0xb4, 0x07, 0xe8,
+ 0xfb, 0x67, 0xb9, 0x05, 0x00, 0xb0, 0x0d, 0xe8,
+ 0xfc, 0x67, 0xb9, 0x41, 0x03, 0xe8, 0x15, 0xd9,
+ 0xbe, 0xe1, 0x00, 0xbf, 0x9f, 0x00, 0xc6, 0x06,
+ 0xc3, 0x64, 0x04, 0xe8, 0x0d, 0xf4, 0x5b, 0x8f,
+ 0x07, 0xb0, 0x4e, 0xe8, 0x12, 0xe5, 0xb0, 0x03,
+ 0xe8, 0xba, 0xd7, 0xc3, 0xbb, 0xc8, 0x58, 0xe8,
+ 0x23, 0x5e, 0xc3, 0xc7, 0x06, 0xf3, 0xb4, 0x03,
+ 0x00, 0xb8, 0xd6, 0x00, 0xbb, 0xc7, 0x00, 0xbf,
+ 0xda, 0x00, 0xbe, 0xbf, 0x00, 0xb1, 0x13, 0xb5,
+ 0x01, 0xe8, 0x97, 0x69, 0xc3, 0xc7, 0x06, 0xf3,
+ 0xb4, 0x05, 0x00, 0xb8, 0x00, 0x00, 0xbb, 0xae,
+ 0x00, 0xbf, 0x23, 0x00, 0xbe, 0xae, 0x00, 0xb1,
+ 0x01, 0xb5, 0x02, 0xe8, 0x7d, 0x69, 0xc3, 0xe8,
+ 0xed, 0xd8, 0xc6, 0x06, 0xdc, 0x64, 0x00, 0xb9,
+ 0x17, 0x00, 0xb0, 0x08, 0xb4, 0x07, 0xe8, 0x84,
+ 0x67, 0xb9, 0x18, 0x00, 0xb0, 0x0d, 0xe8, 0x85,
+ 0x67, 0xe8, 0x64, 0xfd, 0xc6, 0x47, 0x01, 0x00,
+ 0x53, 0xe8, 0xe8, 0x6b, 0xb9, 0x49, 0x03, 0xe8,
+ 0x60, 0xd8, 0x5b, 0xc6, 0x47, 0x01, 0x61, 0xc6,
+ 0x47, 0x02, 0x00, 0xe8, 0x92, 0x6b, 0xe8, 0x84,
+ 0x00, 0xe8, 0xb1, 0xdc, 0xb9, 0x3f, 0x00, 0xb0,
+ 0x0c, 0xb4, 0x07, 0xe8, 0x4f, 0x67, 0xb9, 0x05,
+ 0x00, 0xb0, 0x1a, 0xe8, 0x50, 0x67, 0xb9, 0x4a,
+ 0x03, 0xe8, 0x36, 0xd8, 0xe8, 0x66, 0x00, 0xe8,
+ 0x93, 0xdc, 0xc6, 0x06, 0xe6, 0x1c, 0xd1, 0xbb,
+ 0x56, 0x56, 0xbe, 0x10, 0x55, 0xe8, 0x2e, 0x60,
+ 0xe8, 0x7b, 0xdc, 0xbb, 0x7a, 0x56, 0xbe, 0x5c,
+ 0x55, 0xe8, 0x22, 0x60, 0xe8, 0x6f, 0xdc, 0xbb,
+ 0x82, 0x56, 0xbe, 0x3e, 0x55, 0xe8, 0x16, 0x60,
+ 0xe8, 0x63, 0xdc, 0xb9, 0x4b, 0x03, 0xe8, 0x01,
+ 0xd8, 0xc7, 0x06, 0xaf, 0x64, 0xdf, 0x00, 0xc7,
+ 0x06, 0xb1, 0x64, 0x95, 0x00, 0xc6, 0x06, 0xcb,
+ 0x64, 0x00, 0xc6, 0x06, 0xcc, 0x64, 0x01, 0xc6,
+ 0x06, 0xcd, 0x64, 0x00, 0xe8, 0x1d, 0xd8, 0xb0,
+ 0x07, 0xe8, 0xd1, 0xd6, 0xb0, 0x01, 0xe8, 0xcc,
+ 0xd6, 0xb0, 0x51, 0xe8, 0x1a, 0xe4, 0xbb, 0x46,
+ 0x56, 0xe8, 0x31, 0x5d, 0xc3, 0xe8, 0x6b, 0x68,
+ 0xc6, 0x06, 0xdc, 0x1c, 0x01, 0xe8, 0x9c, 0xeb,
+ 0xe8, 0x45, 0xec, 0xe8, 0xda, 0x63, 0xe8, 0x2b,
+ 0xf1, 0xc3, 0xc7, 0x06, 0xf3, 0xb4, 0x0a, 0x00,
+ 0xb8, 0x3f, 0x01, 0xbb, 0xb7, 0x00, 0xbf, 0x0d,
+ 0x01, 0xbe, 0xaf, 0x00, 0xb1, 0x01, 0xb5, 0x04,
+ 0xe8, 0x90, 0x68, 0xc3, 0xc7, 0x06, 0xf3, 0xb4,
+ 0x04, 0x00, 0xb8, 0x3f, 0x01, 0xbb, 0xb9, 0x00,
+ 0xbf, 0x18, 0x01, 0xbe, 0xb9, 0x00, 0xb1, 0x01,
+ 0xb5, 0x04, 0xe8, 0x76, 0x68, 0xc3, 0xc7, 0x06,
+ 0xf3, 0xb4, 0x02, 0x00, 0xb8, 0xdd, 0x00, 0xbb,
+ 0xc7, 0x00, 0xbf, 0xd9, 0x00, 0xbe, 0xc1, 0x00,
+ 0xb1, 0x13, 0xb5, 0x01, 0xe8, 0x5c, 0x68, 0xc3,
+ 0xb9, 0x50, 0x00, 0xb0, 0x04, 0xb4, 0x02, 0xe8,
+ 0x6b, 0x66, 0xb9, 0xc1, 0x03, 0xe8, 0x57, 0xd7,
+ 0xe8, 0xf8, 0x67, 0xc7, 0x06, 0xf3, 0xb4, 0x08,
+ 0x00, 0xb8, 0x9b, 0x00, 0xbb, 0xc7, 0x00, 0xbf,
+ 0x9e, 0x00, 0xbe, 0xb8, 0x00, 0xb1, 0x13, 0xb5,
+ 0x01, 0xe8, 0x2f, 0x68, 0xc3, 0xb9, 0x46, 0x00,
+ 0xb0, 0x06, 0xb4, 0x09, 0xe8, 0x3e, 0x66, 0xb9,
+ 0xc2, 0x03, 0xe8, 0x2a, 0xd7, 0xe8, 0xcb, 0x67,
+ 0xc7, 0x06, 0xf3, 0xb4, 0x07, 0x00, 0xb8, 0x1e,
+ 0x00, 0xbb, 0xb8, 0x00, 0xbf, 0x32, 0x00, 0xbe,
+ 0xb8, 0x00, 0xb1, 0x01, 0xb5, 0x02, 0xe8, 0x02,
+ 0x68, 0x80, 0x3e, 0xdf, 0xdb, 0x02, 0x72, 0x01,
+ 0xc3, 0xb8, 0x96, 0x00, 0xe8, 0x4b, 0xdb, 0xbe,
+ 0x86, 0x00, 0xbf, 0xa7, 0x00, 0xc6, 0x06, 0xc3,
+ 0x64, 0x02, 0xe8, 0x2e, 0xf2, 0xbb, 0xf7, 0x54,
+ 0xe8, 0x52, 0x5c, 0xbb, 0x47, 0x33, 0xc7, 0x07,
+ 0x2c, 0x03, 0xb9, 0x2b, 0x03, 0xe8, 0xdf, 0xd6,
+ 0xe8, 0x80, 0x67, 0xbb, 0x47, 0x33, 0xc7, 0x07,
+ 0x2d, 0x03, 0xb0, 0x01, 0xe8, 0x08, 0xd6, 0xe8,
+ 0x11, 0xd3, 0xbb, 0x17, 0x61, 0xe8, 0x9d, 0xcd,
+ 0xc7, 0x06, 0xaf, 0x64, 0xe6, 0x00, 0xc7, 0x06,
+ 0xb1, 0x64, 0xb8, 0x00, 0xbb, 0x47, 0x33, 0xc7,
+ 0x07, 0x2e, 0x03, 0xc7, 0x06, 0xf3, 0xb4, 0x06,
+ 0x00, 0xe8, 0xd1, 0x68, 0xe8, 0x0f, 0xd3, 0xbb,
+ 0x6a, 0x62, 0xe8, 0x78, 0xcd, 0xb9, 0x04, 0x00,
+ 0xb0, 0x0e, 0xb4, 0x0e, 0xe8, 0xa6, 0x65, 0xbb,
+ 0x47, 0x33, 0xc7, 0x07, 0x2f, 0x03, 0xb0, 0x01,
+ 0xe8, 0xbd, 0xd5, 0xe8, 0x82, 0xfb, 0xc6, 0x47,
+ 0x01, 0x00, 0xe8, 0x07, 0x6a, 0xe8, 0x2e, 0x66,
+ 0xbb, 0xdc, 0x62, 0xe8, 0x4f, 0xcd, 0xc6, 0x06,
+ 0xdf, 0xdb, 0x01, 0xb9, 0x05, 0x00, 0xe8, 0xca,
+ 0x6c, 0xc3, 0x80, 0x3e, 0xdf, 0xdb, 0x00, 0x75,
+ 0x0d, 0xb9, 0xc8, 0x03, 0xe8, 0x8f, 0xd6, 0xbb,
+ 0x11, 0x55, 0xe8, 0xc0, 0x5b, 0xc3, 0xb9, 0x50,
+ 0x00, 0xb0, 0x03, 0xb4, 0x0c, 0xe8, 0x5d, 0x65,
+ 0xb9, 0x4f, 0x00, 0xb0, 0x04, 0xe8, 0x5e, 0x65,
+ 0xb9, 0xc8, 0x03, 0xe8, 0x51, 0xd6, 0xe8, 0xe2,
+ 0x66, 0xc7, 0x06, 0xf3, 0xb4, 0x06, 0x00, 0xb8,
+ 0x18, 0x01, 0xbb, 0xba, 0x00, 0xbf, 0x09, 0x01,
+ 0xbe, 0xb4, 0x00, 0xb1, 0x01, 0xb5, 0x04, 0xe8,
+ 0x19, 0x67, 0xc3, 0x80, 0x3e, 0xe5, 0xdb, 0x01,
+ 0x75, 0x07, 0xbb, 0xc0, 0x57, 0xe8, 0x7d, 0x5b,
+ 0xc3, 0xb9, 0x31, 0x00, 0xb0, 0x0e, 0xb4, 0x07,
+ 0xe8, 0x1a, 0x65, 0xb9, 0x05, 0x00, 0xb0, 0x15,
+ 0xe8, 0x1b, 0x65, 0xb9, 0x65, 0x03, 0xe8, 0x2d,
+ 0xd6, 0xb0, 0x58, 0xe8, 0x42, 0xe2, 0xc6, 0x06,
+ 0xe5, 0xdb, 0x01, 0xc3, 0xb9, 0x35, 0x00, 0xb0,
+ 0x14, 0xb4, 0x05, 0xe8, 0xf7, 0x64, 0xb9, 0x18,
+ 0x00, 0xb0, 0x1b, 0xb4, 0x0e, 0xe8, 0xf6, 0x64,
+ 0xb9, 0x05, 0x00, 0xb0, 0x24, 0xe8, 0xf5, 0x64,
+ 0xb9, 0x47, 0x03, 0xe8, 0xe1, 0xd5, 0xc7, 0x06,
+ 0xaf, 0x64, 0x16, 0x01, 0xe8, 0x05, 0xd6, 0xb0,
+ 0x50, 0xe8, 0x0c, 0xe2, 0xb0, 0x01, 0xe8, 0xb4,
+ 0xd4, 0xc3, 0xbb, 0xe3, 0x58, 0xe8, 0x1d, 0x5b,
+ 0xc3, 0x80, 0x3e, 0xdd, 0xdb, 0x02, 0x74, 0x7f,
+ 0xbb, 0x5c, 0xdb, 0xe8, 0x67, 0xcc, 0x53, 0xe8,
+ 0x7b, 0xcc, 0x5b, 0x81, 0xfb, 0x6b, 0x63, 0x75,
+ 0x6d, 0xe8, 0x01, 0xda, 0xb9, 0x34, 0x00, 0xb0,
+ 0x08, 0xb4, 0x0c, 0xe8, 0x9f, 0x64, 0xb0, 0x0d,
+ 0xe8, 0xa3, 0x64, 0xbb, 0x47, 0x33, 0xc7, 0x07,
+ 0x34, 0x03, 0xb0, 0x01, 0xe8, 0xb1, 0xd4, 0xe8,
+ 0x76, 0xfa, 0xc6, 0x47, 0x03, 0x59, 0xe8, 0xfb,
+ 0x68, 0xe8, 0x22, 0x65, 0xc6, 0x06, 0x33, 0x33,
+ 0x01, 0xc6, 0x06, 0xdd, 0x1c, 0x02, 0xe8, 0xc5,
+ 0xd9, 0x8b, 0x36, 0xaf, 0x64, 0x8b, 0x3e, 0xb1,
+ 0x64, 0x56, 0x57, 0xc6, 0x06, 0xc3, 0x64, 0x03,
+ 0xe8, 0x90, 0xf0, 0xe8, 0xb7, 0xd9, 0xe8, 0xad,
+ 0xd9, 0x5f, 0x5e, 0xc6, 0x06, 0xc3, 0x64, 0x02,
+ 0xe8, 0x80, 0xf0, 0xe8, 0xa7, 0xd9, 0xbb, 0x1f,
+ 0x55, 0xe8, 0xa1, 0x5a, 0xb0, 0x04, 0xe8, 0x20,
+ 0xd4, 0xc6, 0x06, 0xdc, 0xdb, 0x01, 0xc3, 0xbb,
+ 0xc0, 0x55, 0xe8, 0x90, 0x5a, 0xbe, 0x32, 0x01,
+ 0xbf, 0xc4, 0x00, 0xc6, 0x06, 0xc3, 0x64, 0x02,
+ 0xe8, 0x58, 0xf0, 0xe8, 0x78, 0xd9, 0xbb, 0x47,
+ 0x33, 0xc7, 0x07, 0x39, 0x03, 0xb0, 0x01, 0xe8,
+ 0x45, 0xd4, 0xe8, 0x07, 0x65, 0xe8, 0x66, 0xd9,
+ 0xb9, 0x47, 0x00, 0xb0, 0x04, 0xb4, 0x0e, 0xe8,
+ 0x0b, 0x64, 0xb9, 0x37, 0x03, 0xe8, 0x1f, 0xd5,
+ 0xb9, 0x4a, 0x00, 0xb0, 0x01, 0xb4, 0x0a, 0xe8,
+ 0xfb, 0x63, 0xb0, 0x03, 0xe8, 0xff, 0x63, 0xb0,
+ 0x06, 0xe8, 0x01, 0x64, 0xbb, 0x47, 0x33, 0xc7,
+ 0x07, 0x3a, 0x03, 0xc7, 0x06, 0xf3, 0xb4, 0x05,
+ 0x00, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x3a, 0x03,
+ 0xe8, 0xe9, 0x66, 0xb0, 0x01, 0xe8, 0x3a, 0xd4,
+ 0xe8, 0x73, 0x64, 0xc7, 0x06, 0xf3, 0xb4, 0x06,
+ 0x00, 0xe8, 0xb4, 0xf9, 0xc6, 0x47, 0x03, 0x5b,
+ 0xe8, 0xda, 0x66, 0x8b, 0x36, 0xaf, 0x64, 0x8b,
+ 0x3e, 0xb1, 0x64, 0xc6, 0x06, 0xc3, 0x64, 0x01,
+ 0xe8, 0xe0, 0xef, 0xe8, 0x00, 0xd9, 0xbb, 0xdb,
+ 0x55, 0xe8, 0x01, 0x5a, 0xc6, 0x06, 0xdd, 0xdb,
+ 0x03, 0xb0, 0x04, 0xbe, 0xc7, 0x78, 0xe8, 0x90,
+ 0xd3, 0xc3, 0x80, 0x3e, 0xdd, 0xdb, 0x03, 0x74,
+ 0x07, 0xbb, 0x05, 0x59, 0xe8, 0xe6, 0x59, 0xc3,
+ 0x80, 0x3e, 0xde, 0xdb, 0x01, 0x74, 0x31, 0xbe,
+ 0x18, 0x01, 0xbf, 0xb3, 0x00, 0xc6, 0x06, 0xc3,
+ 0x64, 0x02, 0xe8, 0xa6, 0xef, 0xb9, 0x31, 0x00,
+ 0xb0, 0x07, 0xb4, 0x0c, 0xe8, 0x6e, 0x63, 0xb9,
+ 0x05, 0x00, 0xb0, 0x11, 0xe8, 0x6f, 0x63, 0xb9,
+ 0x3b, 0x03, 0xe8, 0x73, 0xd4, 0xb0, 0x4d, 0xe8,
+ 0x96, 0xe0, 0xc6, 0x06, 0xde, 0xdb, 0x01, 0xc3,
+ 0xbb, 0x08, 0x56, 0xe8, 0xa7, 0x59, 0xc3, 0x80,
+ 0x3e, 0xdc, 0xdb, 0x01, 0x74, 0x07, 0xbb, 0x28,
+ 0x55, 0xe8, 0x99, 0x59, 0xc3, 0xe8, 0x97, 0xd4,
+ 0xbb, 0x5d, 0x55, 0xe8, 0x8f, 0x59, 0xe8, 0x1f,
+ 0xf9, 0xc6, 0x47, 0x02, 0x00, 0xe8, 0xa4, 0x67,
+ 0xb9, 0x35, 0x03, 0xe8, 0x1c, 0xd4, 0xe8, 0x0f,
+ 0xf9, 0xc6, 0x47, 0x02, 0x5a, 0xc6, 0x47, 0x03,
+ 0x00, 0xe8, 0x4c, 0x67, 0xb9, 0x16, 0x00, 0xb0,
+ 0x02, 0xb4, 0x0b, 0xe8, 0x0f, 0x63, 0xb9, 0x36,
+ 0x03, 0xe8, 0x23, 0xd4, 0xbb, 0x77, 0x55, 0xe8,
+ 0x5b, 0x59, 0xb0, 0x05, 0xe8, 0xe6, 0xd2, 0xc6,
+ 0x06, 0xdd, 0xdb, 0x01, 0xc3, 0xe8, 0x4f, 0xd4,
+ 0xe8, 0x43, 0xd8, 0xbe, 0x90, 0x00, 0xbf, 0xb9,
+ 0x00, 0xc6, 0x06, 0xc3, 0x64, 0x04, 0xe8, 0x12,
+ 0xef, 0xe8, 0xcc, 0xf8, 0xc6, 0x07, 0x56, 0xe8,
+ 0x52, 0x67, 0xb9, 0x38, 0x00, 0xb0, 0x0f, 0xb4,
+ 0x07, 0xe8, 0xd1, 0x62, 0xbb, 0x47, 0x33, 0xc7,
+ 0x07, 0x31, 0x03, 0xb9, 0x30, 0x03, 0xe8, 0xc9,
+ 0xd3, 0xe8, 0xac, 0xf8, 0xc6, 0x07, 0x57, 0xe8,
+ 0xee, 0x66, 0xb9, 0x22, 0x00, 0xb0, 0x01, 0xb4,
+ 0x08, 0xe8, 0xb1, 0x62, 0xb9, 0x05, 0x00, 0xb0,
+ 0x0f, 0xe8, 0xb2, 0x62, 0xbb, 0x47, 0x33, 0xc7,
+ 0x07, 0x33, 0x03, 0xb9, 0x32, 0x03, 0xe8, 0xa1,
+ 0xd3, 0xe8, 0x84, 0xf8, 0xc6, 0x47, 0x02, 0x58,
+ 0xe8, 0xc5, 0x66, 0xc7, 0x06, 0xaf, 0x64, 0xa0,
+ 0x00, 0xc7, 0x06, 0xb1, 0x64, 0xbc, 0x00, 0xc6,
+ 0x06, 0xcc, 0x64, 0x01, 0xc6, 0x06, 0xdc, 0x64,
+ 0x00, 0xe8, 0xa8, 0xd3, 0xb0, 0x06, 0xe8, 0x5c,
+ 0xd2, 0xb0, 0x05, 0xe8, 0x4b, 0xd2, 0xb0, 0x4c,
+ 0xe8, 0xa5, 0xdf, 0xc3, 0x80, 0x3e, 0xdf, 0xdb,
+ 0x02, 0x73, 0x07, 0xbb, 0x2f, 0x59, 0xe8, 0xb4,
+ 0x58, 0xc3, 0xc7, 0x06, 0xf3, 0xb4, 0x05, 0x00,
+ 0xb8, 0x1f, 0x01, 0xbb, 0x8f, 0x00, 0xbf, 0x22,
+ 0x01, 0xbe, 0x8f, 0x00, 0xb1, 0x01, 0xb5, 0x02,
+ 0xe8, 0x28, 0x64, 0xc3, 0xb9, 0x4f, 0x00, 0xb0,
+ 0x05, 0xb4, 0x0b, 0xe8, 0x37, 0x62, 0xb9, 0x01,
+ 0x00, 0xb0, 0x0e, 0xe8, 0x38, 0x62, 0xb9, 0xc6,
+ 0x03, 0xe8, 0x3c, 0xd3, 0xbb, 0x55, 0x59, 0xe8,
+ 0x7b, 0x58, 0xc3, 0x80, 0x3e, 0xdf, 0xdb, 0x01,
+ 0x74, 0x07, 0xbb, 0xf6, 0x52, 0xe8, 0x6d, 0x58,
+ 0xc3, 0xb9, 0x47, 0x00, 0xb0, 0x04, 0xb4, 0x0e,
+ 0xe8, 0x0a, 0x62, 0xb9, 0x37, 0x03, 0xe8, 0x17,
+ 0xd3, 0x80, 0x3e, 0xdd, 0xdb, 0x00, 0x75, 0x07,
+ 0xbb, 0x80, 0x4d, 0xe8, 0x4f, 0x58, 0xc3, 0xb9,
+ 0x4a, 0x00, 0xb0, 0x01, 0xb4, 0x0e, 0xe8, 0xec,
+ 0x61, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x38, 0x03,
+ 0xb0, 0x01, 0xe8, 0x03, 0xd2, 0xe8, 0x7e, 0x62,
+ 0x80, 0x3e, 0xdd, 0xdb, 0x01, 0x75, 0x0e, 0xe8,
+ 0x2b, 0xd7, 0xbb, 0x9a, 0x55, 0xe8, 0x25, 0x58,
+ 0xc6, 0x06, 0xdd, 0xdb, 0x02, 0xc3, 0xe8, 0x9d,
+ 0x5c, 0xc3, 0xbb, 0x82, 0xdb, 0xe8, 0x6d, 0xc9,
+ 0xe8, 0x82, 0xc9, 0xc3, 0xb9, 0x50, 0x00, 0xb0,
+ 0x04, 0xb4, 0x02, 0xe8, 0xaf, 0x61, 0xb9, 0xc3,
+ 0x03, 0xe8, 0xab, 0xd2, 0xe8, 0x3c, 0x63, 0xc7,
+ 0x06, 0xf3, 0xb4, 0x05, 0x00, 0xb8, 0xa6, 0x00,
+ 0xbb, 0x9e, 0x00, 0xbf, 0xa6, 0x00, 0xbe, 0xa1,
+ 0x00, 0xb1, 0x0b, 0xb5, 0x03, 0xe8, 0x73, 0x63,
+ 0xc3, 0xb9, 0xc5, 0x03, 0xe8, 0x99, 0xd2, 0xbb,
+ 0x11, 0x55, 0xe8, 0xd8, 0x57, 0xc3, 0xbb, 0x62,
+ 0x59, 0xe8, 0xd1, 0x57, 0xc3, 0xbb, 0x9d, 0x59,
+ 0xe8, 0xca, 0x57, 0xc3, 0xbb, 0xb6, 0x59, 0xe8,
+ 0xc3, 0x57, 0xc3, 0x80, 0x3e, 0xe6, 0xdb, 0x01,
+ 0x75, 0x2d, 0xc6, 0x06, 0xe6, 0xdb, 0x02, 0xe8,
+ 0xb5, 0xd2, 0xe8, 0x43, 0xf7, 0xc6, 0x47, 0x01,
+ 0x67, 0xe8, 0xc8, 0x65, 0xb9, 0x05, 0x00, 0xb0,
+ 0x09, 0xb4, 0x09, 0xe8, 0x47, 0x61, 0xb9, 0x68,
+ 0x03, 0xe8, 0x5b, 0xd2, 0xb0, 0x5a, 0xe8, 0x77,
+ 0xde, 0xb0, 0x07, 0xe8, 0x1f, 0xd1, 0xc3, 0xb9,
+ 0xc4, 0x03, 0xe8, 0x43, 0xd2, 0xbb, 0x11, 0x55,
+ 0xe8, 0x82, 0x57, 0xc3, 0xbb, 0xdb, 0x59, 0xe8,
+ 0x7b, 0x57, 0xc3, 0xbb, 0x01, 0x5a, 0xe8, 0x74,
+ 0x57, 0xc3, 0xe8, 0xf1, 0x5b, 0xc3, 0xe8, 0xed,
+ 0x5b, 0xc3, 0xe8, 0x6a, 0xd2, 0xe8, 0xf8, 0xf6,
+ 0xc6, 0x07, 0x00, 0xe8, 0x7e, 0x65, 0xb9, 0x05,
+ 0x00, 0xb0, 0x09, 0xb4, 0x07, 0xe8, 0xfd, 0x60,
+ 0xb9, 0x44, 0x03, 0xe8, 0x11, 0xd2, 0xb0, 0x4f,
+ 0xe8, 0x2d, 0xde, 0xb0, 0x0c, 0xe8, 0xd5, 0xd0,
+ 0xc3, 0xbb, 0x20, 0x5a, 0xe8, 0x3e, 0x57, 0xc3,
+ 0x80, 0x3e, 0xe7, 0xdb, 0x01, 0x74, 0x03, 0xe9,
+ 0x83, 0x00, 0xbe, 0x8c, 0x00, 0xbf, 0x98, 0x00,
+ 0xc6, 0x06, 0xc3, 0x64, 0x01, 0xe8, 0xfb, 0xec,
+ 0x80, 0x3e, 0xe8, 0xdb, 0x01, 0x74, 0x07, 0xbb,
+ 0x55, 0x58, 0xe8, 0x18, 0x57, 0xc3, 0xbb, 0x20,
+ 0x6f, 0xe8, 0x81, 0xc8, 0xc6, 0x06, 0xe6, 0x1c,
+ 0xef, 0xbe, 0xe0, 0x53, 0xbb, 0x83, 0x58, 0xe8,
+ 0xac, 0x59, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x72,
+ 0x03, 0xb0, 0x01, 0xe8, 0xc2, 0xd0, 0xe8, 0x87,
+ 0xf6, 0xc6, 0x47, 0x02, 0x00, 0xe8, 0x0c, 0x65,
+ 0xb9, 0x4b, 0x00, 0xb0, 0x0a, 0xb4, 0x0a, 0xe8,
+ 0x8b, 0x60, 0xb9, 0x18, 0x00, 0xb0, 0x0f, 0xe8,
+ 0x8c, 0x60, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x73,
+ 0x03, 0xb0, 0x01, 0xe8, 0x9a, 0xd0, 0xe8, 0x63,
+ 0x61, 0xe8, 0x87, 0x00, 0xb8, 0x01, 0x00, 0xe8,
+ 0xe7, 0xe4, 0xe8, 0xfb, 0xe4, 0xb0, 0x02, 0xe8,
+ 0x4b, 0xd0, 0xb0, 0x01, 0xe8, 0x46, 0xd0, 0xc6,
+ 0x06, 0xe9, 0xdb, 0x01, 0xc3, 0xe8, 0x68, 0xcd,
+ 0x80, 0x3e, 0xdf, 0xdb, 0x03, 0x74, 0x0a, 0xbb,
+ 0x68, 0xdb, 0xe8, 0xf8, 0xc7, 0xe8, 0x0d, 0xc8,
+ 0xc3, 0x80, 0x3e, 0xe3, 0xdb, 0x01, 0x75, 0x07,
+ 0xbb, 0xd6, 0x6b, 0xe8, 0xff, 0xc7, 0xc3, 0xbb,
+ 0xb5, 0x69, 0xe8, 0xf8, 0xc7, 0xbb, 0x47, 0x33,
+ 0xc7, 0x07, 0x5a, 0x03, 0xb9, 0x5b, 0x03, 0xe8,
+ 0x18, 0xd1, 0xe8, 0xc1, 0x60, 0xb9, 0x4b, 0x00,
+ 0xb0, 0x06, 0xb4, 0x08, 0xe8, 0x16, 0x60, 0xb0,
+ 0x0a, 0xe8, 0x1a, 0x60, 0xb9, 0x05, 0x00, 0xb0,
+ 0x0f, 0xe8, 0x19, 0x60, 0xb9, 0x5c, 0x03, 0xe8,
+ 0x1d, 0xd1, 0xe8, 0x13, 0xcd, 0xbb, 0xc2, 0x69,
+ 0xe8, 0xc2, 0xc7, 0xb0, 0x55, 0xe8, 0x30, 0xdd,
+ 0xc6, 0x06, 0xe3, 0xdb, 0x01, 0xc6, 0x06, 0xf0,
+ 0xdb, 0x00, 0xc3, 0xe8, 0x00, 0x00, 0x1e, 0x06,
+ 0xa1, 0xb1, 0x32, 0x8e, 0xd8, 0xb8, 0x00, 0xa0,
+ 0x8e, 0xc0, 0xfc, 0xe8, 0xea, 0x5c, 0xe8, 0xe7,
+ 0x5c, 0xbe, 0x00, 0x0a, 0x33, 0xff, 0xb9, 0x00,
+ 0x78, 0xf3, 0xa5, 0xe8, 0xda, 0x5c, 0xe8, 0xd7,
+ 0x5c, 0x33, 0xf6, 0x33, 0xff, 0xb9, 0x00, 0x7d,
+ 0xf3, 0xa5, 0xe8, 0xcb, 0x5c, 0xe8, 0xc8, 0x5c,
+ 0xbe, 0x00, 0x05, 0x33, 0xff, 0xb9, 0x80, 0x7a,
+ 0xf3, 0xa5, 0xe8, 0xbb, 0x5c, 0xe8, 0xb8, 0x5c,
+ 0x33, 0xf6, 0x33, 0xff, 0xb9, 0x00, 0x7d, 0xf3,
+ 0xa5, 0x07, 0x1f, 0xc3, 0x80, 0x3e, 0xf0, 0xdb,
+ 0x01, 0x75, 0x07, 0xbb, 0x25, 0x5e, 0xe8, 0xe4,
+ 0x55, 0xc3, 0xc7, 0x06, 0xf3, 0xb4, 0x05, 0x00,
+ 0xb8, 0x23, 0x00, 0xbb, 0xa2, 0x00, 0xbf, 0x23,
+ 0x00, 0xbe, 0xae, 0x00, 0xb1, 0x0b, 0xb5, 0x03,
+ 0xe8, 0x58, 0x61, 0xc3, 0x80, 0x3e, 0xe9, 0xdb,
+ 0x01, 0x75, 0x3f, 0xb9, 0x59, 0x00, 0xb0, 0x05,
+ 0xb4, 0x02, 0xe8, 0x60, 0x5f, 0xb9, 0xbe, 0x03,
+ 0xe8, 0x4c, 0xd0, 0xe8, 0xed, 0x60, 0xc6, 0x06,
+ 0xcc, 0x64, 0x00, 0xc6, 0x06, 0xdc, 0x64, 0x01,
+ 0xc6, 0x06, 0xcb, 0x64, 0x00, 0xe8, 0xc1, 0xf3,
+ 0xc7, 0x06, 0xf3, 0xb4, 0x09, 0x00, 0xb8, 0xf0,
+ 0x00, 0xbb, 0xb6, 0x00, 0xbf, 0xe0, 0x00, 0xbe,
+ 0xb6, 0x00, 0xb1, 0x01, 0xb5, 0x04, 0xe8, 0x12,
+ 0x61, 0xc3, 0x80, 0x3e, 0xe7, 0xdb, 0x01, 0x74,
+ 0x0d, 0xe8, 0x34, 0xcc, 0xbb, 0x8a, 0xdb, 0xe8,
+ 0xcb, 0xc6, 0xe8, 0xe0, 0xc6, 0xc3, 0xbb, 0x94,
+ 0x58, 0xe8, 0x69, 0x55, 0xc3, 0xbb, 0x1e, 0x43,
+ 0xe8, 0x62, 0x55, 0xc3, 0xe8, 0x60, 0xd0, 0xe8,
+ 0xee, 0xf4, 0xc6, 0x07, 0x00, 0xe8, 0x74, 0x63,
+ 0xb9, 0x31, 0x00, 0xb0, 0x06, 0xb4, 0x0b, 0xe8,
+ 0xf3, 0x5e, 0xb9, 0x05, 0x00, 0xb0, 0x0d, 0xe8,
+ 0xf4, 0x5e, 0xb9, 0x5d, 0x03, 0xe8, 0xff, 0xcf,
+ 0xb0, 0x57, 0xe8, 0x1b, 0xdc, 0xb0, 0x06, 0xe8,
+ 0xc3, 0xce, 0xc3, 0xe8, 0xb0, 0x59, 0xc3, 0xbb,
+ 0x51, 0x5a, 0xe8, 0x28, 0x55, 0xc3, 0xbb, 0x98,
+ 0x5a, 0xe8, 0x21, 0x55, 0xc3, 0xb9, 0x0f, 0x00,
+ 0xb0, 0x07, 0xb4, 0x04, 0xe8, 0xbe, 0x5e, 0xb9,
+ 0x74, 0x03, 0xe8, 0xcb, 0xcf, 0xb9, 0x37, 0x00,
+ 0xb0, 0x01, 0xb4, 0x04, 0xe8, 0xae, 0x5e, 0xb9,
+ 0x18, 0x00, 0xb0, 0x0c, 0xe8, 0xaf, 0x5e, 0xbb,
+ 0x47, 0x33, 0xc7, 0x07, 0x75, 0x03, 0xb0, 0x01,
+ 0xe8, 0xbd, 0xce, 0xc6, 0x06, 0x45, 0x33, 0xd0,
+ 0xb0, 0x01, 0xbe, 0x76, 0x03, 0xbb, 0xe5, 0x67,
+ 0xe8, 0x84, 0xca, 0xc7, 0x06, 0xaf, 0x64, 0xc6,
+ 0x00, 0xc7, 0x06, 0xb1, 0x64, 0xba, 0x00, 0xc6,
+ 0x06, 0xcd, 0x64, 0x00, 0xc6, 0x06, 0xdc, 0x64,
+ 0x00, 0xc6, 0x06, 0xcb, 0x64, 0x01, 0xe8, 0xe8,
+ 0xf2, 0xb9, 0x03, 0x00, 0xe8, 0xb4, 0x65, 0xe8,
+ 0xab, 0x50, 0xe8, 0x2e, 0xba, 0xb8, 0x64, 0x00,
+ 0xe8, 0xb9, 0xd3, 0xc7, 0x06, 0xf3, 0xb4, 0x28,
+ 0x00, 0xe8, 0x69, 0x61, 0xe8, 0x28, 0xcb, 0xbb,
+ 0x20, 0x7f, 0xe8, 0x10, 0xc6, 0xe8, 0xc6, 0xdb,
+ 0xb0, 0x1d, 0xe8, 0x7b, 0xdb, 0xbb, 0x5c, 0xe4,
+ 0xe8, 0x1b, 0xba, 0xb9, 0x06, 0x00, 0xe8, 0x82,
+ 0x65, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0xbc, 0x03,
+ 0xc7, 0x06, 0xf3, 0xb4, 0x01, 0x00, 0xe8, 0x33,
+ 0x61, 0xb0, 0x01, 0xe8, 0x84, 0xce, 0xc6, 0x06,
+ 0x45, 0x33, 0xd1, 0xb0, 0x01, 0xbe, 0xbd, 0x03,
+ 0xbb, 0xc4, 0x8b, 0xe8, 0x09, 0xca, 0xe8, 0xad,
+ 0x5e, 0xe8, 0x60, 0x0c, 0xc3, 0xb9, 0xbf, 0x03,
+ 0xe8, 0xf4, 0xce, 0xe8, 0x95, 0x5f, 0xc7, 0x06,
+ 0xf3, 0xb4, 0x08, 0x00, 0xb8, 0x28, 0x00, 0xbb,
+ 0x98, 0x00, 0xbf, 0x28, 0x00, 0xbe, 0x9b, 0x00,
+ 0xb1, 0x0b, 0xb5, 0x03, 0xe8, 0xcc, 0x5f, 0xc3,
+ 0xe8, 0xbb, 0x58, 0xc3, 0xb9, 0xc0, 0x03, 0xe8,
+ 0xee, 0xce, 0xbb, 0x11, 0x55, 0xe8, 0x2d, 0x54,
+ 0xc3, 0xbb, 0xc6, 0x5a, 0xe8, 0x26, 0x54, 0xc3,
+ 0xbb, 0xed, 0x5a, 0xe8, 0x1f, 0x54, 0xc3, 0xbb,
+ 0xed, 0x5a, 0xe8, 0x18, 0x54, 0xc3, 0xb9, 0x20,
+ 0x00, 0xb0, 0x18, 0xb4, 0x05, 0xe8, 0xb5, 0x5d,
+ 0xb9, 0x5e, 0x03, 0xe8, 0xa1, 0xce, 0xe8, 0x42,
+ 0x5f, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x5f, 0x03,
+ 0xb0, 0x01, 0xe8, 0xca, 0xcd, 0xe8, 0x8c, 0x5e,
+ 0xb0, 0x54, 0xe8, 0xd3, 0xda, 0xb0, 0x01, 0xe8,
+ 0x7b, 0xcd, 0xc6, 0x06, 0xe2, 0xdb, 0x02, 0xc3,
+ 0x80, 0x3e, 0xe2, 0xdb, 0x00, 0x74, 0x10, 0xbb,
+ 0x22, 0x57, 0xe8, 0xd8, 0x53, 0xe8, 0xd5, 0xd2,
+ 0xbb, 0x2a, 0x57, 0xe8, 0xcf, 0x53, 0xc3, 0xe8,
+ 0x10, 0xcb, 0x80, 0x3e, 0xda, 0xdb, 0x01, 0x74,
+ 0x0a, 0xbb, 0x40, 0xdb, 0xe8, 0x16, 0xc5, 0xe8,
+ 0x2b, 0xc5, 0xc3, 0xbb, 0x4c, 0xdb, 0xe8, 0x0c,
+ 0xc5, 0xe8, 0x21, 0xc5, 0xc3, 0xbb, 0x27, 0x5b,
+ 0xe8, 0xaa, 0x53, 0xc3, 0x80, 0x3e, 0xda, 0xdb,
+ 0x01, 0x75, 0x1a, 0xc7, 0x06, 0xf3, 0xb4, 0x05,
+ 0x00, 0xb8, 0x78, 0x00, 0xbb, 0xc7, 0x00, 0xbf,
+ 0x80, 0x00, 0xbe, 0xb0, 0x00, 0xb1, 0x13, 0xb5,
+ 0x01, 0xe8, 0x17, 0x5f, 0xc3, 0xe8, 0xca, 0xca,
+ 0xbb, 0xe9, 0x5f, 0xe8, 0xef, 0xc4, 0xbe, 0x0d,
+ 0x01, 0xbf, 0xaf, 0x00, 0xc6, 0x06, 0xc3, 0x64,
+ 0x04, 0xe8, 0x47, 0xe9, 0xe8, 0xb3, 0xca, 0xbb,
+ 0x56, 0xdb, 0xe8, 0xc0, 0xc4, 0xe8, 0xd5, 0xc4,
+ 0xc3, 0xe8, 0x32, 0xcb, 0xbb, 0xa6, 0xda, 0xe8,
+ 0xb3, 0xc4, 0x53, 0xe8, 0xc7, 0xc4, 0x5b, 0x81,
+ 0xfb, 0xb4, 0x01, 0x75, 0x50, 0x8b, 0x3e, 0xb1,
+ 0x64, 0x8b, 0x36, 0xaf, 0x64, 0x57, 0x56, 0xbf,
+ 0x9f, 0x00, 0xbe, 0xbd, 0x00, 0xe8, 0x13, 0xe9,
+ 0xb8, 0x01, 0x01, 0xe8, 0xf0, 0xd1, 0xb9, 0x05,
+ 0x00, 0xb0, 0x02, 0xb4, 0x0a, 0xe8, 0xd5, 0x5c,
+ 0xb0, 0x13, 0xe8, 0xd9, 0x5c, 0xbb, 0x47, 0x33,
+ 0xc7, 0x07, 0x27, 0x02, 0xb9, 0x26, 0x02, 0xe8,
+ 0xd6, 0xcd, 0x5e, 0x5f, 0xc6, 0x06, 0xc3, 0x64,
+ 0x02, 0xe8, 0xe7, 0xe8, 0xb0, 0x13, 0xe8, 0xef,
+ 0xd9, 0xe8, 0xda, 0xca, 0xbb, 0xa6, 0xda, 0xe8,
+ 0x5b, 0xc4, 0xe8, 0x70, 0xc4, 0xc3, 0xe8, 0xfe,
+ 0xcd, 0xb0, 0x10, 0xe8, 0xda, 0xd9, 0xb0, 0x02,
+ 0xe8, 0x82, 0xcc, 0xe8, 0x82, 0xf2, 0xc6, 0x07,
+ 0x00, 0xe8, 0x08, 0x61, 0xb9, 0x05, 0x00, 0xb0,
+ 0x0c, 0xb4, 0x06, 0xe8, 0x87, 0x5c, 0xb9, 0x23,
+ 0x02, 0xe8, 0x9b, 0xcd, 0xc3, 0xe8, 0x56, 0x57,
+ 0xc3, 0xe8, 0x52, 0x57, 0xc3, 0xe8, 0x4e, 0x57,
+ 0xc3, 0xbb, 0xd6, 0x3e, 0xe8, 0xc6, 0x52, 0xc3,
+ 0xe8, 0x43, 0x57, 0xc3, 0xe8, 0x1d, 0xcb, 0xbb,
+ 0xbd, 0x33, 0xe8, 0x28, 0xc4, 0xc6, 0x06, 0xe6,
+ 0x1c, 0xd0, 0xbe, 0xe4, 0x61, 0xbb, 0xae, 0x49,
+ 0xe8, 0xd5, 0x54, 0xb9, 0x05, 0x00, 0xb0, 0x03,
+ 0xb4, 0x07, 0xe8, 0x48, 0x5c, 0xbb, 0x47, 0x33,
+ 0xc7, 0x47, 0x02, 0x9b, 0x02, 0xb0, 0x02, 0xe8,
+ 0x5e, 0xcc, 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x02,
+ 0x9c, 0x02, 0xb0, 0x02, 0xe8, 0x51, 0xcc, 0xe8,
+ 0xcc, 0x5c, 0xc6, 0x06, 0x33, 0x33, 0x01, 0xc6,
+ 0x06, 0xdd, 0x1c, 0x02, 0xc6, 0x06, 0xdb, 0x1c,
+ 0x01, 0xe8, 0x04, 0xf2, 0xc6, 0x47, 0x02, 0x32,
+ 0xe8, 0x89, 0x60, 0xc7, 0x06, 0x30, 0x32, 0x78,
+ 0x00, 0xc7, 0x06, 0x2e, 0x32, 0x5a, 0x00, 0xc7,
+ 0x06, 0x2c, 0x32, 0xae, 0x00, 0xe8, 0x76, 0xda,
+ 0xe8, 0xbd, 0x5a, 0xe8, 0xae, 0xca, 0xbb, 0xc7,
+ 0x36, 0xe8, 0xb9, 0xc3, 0xb9, 0x52, 0x00, 0xb0,
+ 0x13, 0xb4, 0x0e, 0xe8, 0xe7, 0x5b, 0xbb, 0x47,
+ 0x33, 0xc7, 0x47, 0x02, 0x9d, 0x02, 0xb0, 0x02,
+ 0xe8, 0x3f, 0xcc, 0xe8, 0xc2, 0xf1, 0xc6, 0x47,
+ 0x03, 0x00, 0xe8, 0x75, 0x60, 0xc7, 0x06, 0xec,
+ 0xdb, 0x00, 0x00, 0xe8, 0x68, 0x5c, 0xbb, 0x79,
+ 0x37, 0xe8, 0x89, 0xc3, 0xb0, 0x0f, 0xe8, 0x98,
+ 0xcb, 0xb0, 0x08, 0xe8, 0x9f, 0xcb, 0xc3, 0xc7,
+ 0x06, 0xf3, 0xb4, 0x0d, 0x00, 0xb8, 0x00, 0x00,
+ 0xbb, 0xac, 0x00, 0xbf, 0x12, 0x00, 0xbe, 0xad,
+ 0x00, 0xb1, 0x01, 0xb5, 0x02, 0xe8, 0x83, 0x5d,
+ 0xc3, 0xc6, 0x06, 0xdc, 0x64, 0x01, 0xc6, 0x06,
+ 0xcb, 0x64, 0x00, 0xc7, 0x06, 0xf3, 0xb4, 0x0e,
+ 0x00, 0xb8, 0x18, 0x01, 0xbb, 0xc6, 0x00, 0xbf,
+ 0xe3, 0x00, 0xbe, 0xb8, 0x00, 0xb1, 0x01, 0xb5,
+ 0x04, 0xe8, 0x5f, 0x5d, 0xc3, 0xc7, 0x06, 0xf3,
+ 0xb4, 0x0f, 0x00, 0xb8, 0x3f, 0x01, 0xbb, 0xa2,
+ 0x00, 0xbf, 0x06, 0x01, 0xbe, 0xb0, 0x00, 0xb1,
+ 0x01, 0xb5, 0x04, 0xe8, 0x45, 0x5d, 0xc3, 0xc7,
+ 0x06, 0xf3, 0xb4, 0x0c, 0x00, 0xb8, 0x3f, 0x01,
+ 0xbb, 0x98, 0x00, 0xbf, 0x2d, 0x01, 0xbe, 0xaf,
+ 0x00, 0xb1, 0x01, 0xb5, 0x04, 0xe8, 0x2b, 0x5d,
+ 0xc3, 0xe8, 0x9b, 0xcc, 0xb9, 0x05, 0x00, 0xb0,
+ 0x0c, 0xb4, 0x09, 0xe8, 0x37, 0x5b, 0xb0, 0x12,
+ 0xe8, 0x6d, 0xd8, 0xb0, 0x0d, 0xe8, 0x15, 0xcb,
+ 0xe8, 0x15, 0xf1, 0xc6, 0x47, 0x01, 0x00, 0xe8,
+ 0x9a, 0x5f, 0xb9, 0x25, 0x02, 0xe8, 0x37, 0xcc,
+ 0xc3, 0xe8, 0xf2, 0x55, 0xc3, 0xe8, 0x6f, 0xcc,
+ 0xe8, 0xfd, 0xf0, 0xc6, 0x47, 0x02, 0x00, 0xe8,
+ 0x82, 0x5f, 0xb9, 0x05, 0x00, 0xb0, 0x0c, 0xb4,
+ 0x07, 0xe8, 0x01, 0x5b, 0xb9, 0xa4, 0x02, 0xe8,
+ 0x15, 0xcc, 0xbb, 0xb0, 0x4a, 0xe8, 0x4d, 0x51,
+ 0xb0, 0x0f, 0xe8, 0xd8, 0xca, 0xb0, 0x33, 0xe8,
+ 0x26, 0xd8, 0xc3, 0xc3, 0xbb, 0x0f, 0x37, 0x80,
+ 0x3e, 0xa1, 0xdb, 0x01, 0x74, 0x03, 0xbb, 0xc2,
+ 0x36, 0xe8, 0x31, 0x51, 0xc3, 0xb9, 0xc7, 0x03,
+ 0xe8, 0xe5, 0xcb, 0xbb, 0x42, 0x35, 0xe8, 0x24,
+ 0x51, 0xc3, 0x80, 0x3e, 0xa1, 0xdb, 0x01, 0x74,
+ 0x53, 0xb9, 0x38, 0x00, 0xb0, 0x08, 0xb4, 0x0e,
+ 0xe8, 0xba, 0x5a, 0xb0, 0x0c, 0xe8, 0xc5, 0x5a,
+ 0xb9, 0x31, 0x00, 0xb0, 0x0a, 0xe8, 0xb6, 0x5a,
+ 0xc6, 0x06, 0x35, 0x33, 0x10, 0xc6, 0x06, 0x36,
+ 0x33, 0x18, 0xb8, 0x52, 0x46, 0xa3, 0x37, 0x33,
+ 0xb8, 0x5b, 0x7b, 0xa3, 0x39, 0x33, 0xe8, 0xee,
+ 0xcb, 0xb9, 0x4b, 0x02, 0xe8, 0x00, 0xcc, 0xe8,
+ 0xba, 0xcb, 0x8b, 0x36, 0xaf, 0x64, 0x8b, 0x3e,
+ 0xb1, 0x64, 0xc6, 0x06, 0xc3, 0x64, 0x02, 0xe8,
+ 0xa9, 0xe6, 0xe8, 0xd0, 0xcf, 0xbb, 0x68, 0x36,
+ 0xe8, 0xca, 0x50, 0xc3, 0x80, 0x3e, 0xa2, 0xdb,
+ 0x01, 0x74, 0x73, 0xb9, 0x1a, 0x00, 0xb0, 0x0d,
+ 0xb4, 0x0c, 0xe8, 0x60, 0x5a, 0xb0, 0x0f, 0xe8,
+ 0x64, 0x5a, 0xb0, 0x17, 0xe8, 0x66, 0x5a, 0xb0,
+ 0x19, 0xe8, 0x68, 0x5a, 0xb0, 0x20, 0xe8, 0x6a,
+ 0x5a, 0xb0, 0x22, 0xe8, 0x6c, 0x5a, 0xb0, 0x24,
+ 0xe8, 0x6e, 0x5a, 0xb9, 0x4e, 0x02, 0xe8, 0x2e,
+ 0xcb, 0xc7, 0x06, 0xaf, 0x64, 0xcc, 0x00, 0xc7,
+ 0x06, 0xb1, 0x64, 0xb2, 0x00, 0xc6, 0x06, 0xc3,
+ 0x64, 0x03, 0xc6, 0x06, 0xcb, 0x64, 0x01, 0xc6,
+ 0x06, 0xcd, 0x64, 0x01, 0xb9, 0x3b, 0x00, 0xb0,
+ 0x01, 0xb4, 0x0a, 0xe8, 0x17, 0x5a, 0xb9, 0x3c,
+ 0x00, 0xb0, 0x10, 0xe8, 0x18, 0x5a, 0xb9, 0x4f,
+ 0x02, 0xe8, 0x23, 0xcb, 0xe8, 0x57, 0xcf, 0xbb,
+ 0x2e, 0x37, 0xe8, 0x58, 0x50, 0xc6, 0x06, 0xa2,
+ 0xdb, 0x01, 0xe8, 0x40, 0x4d, 0xc3, 0xbb, 0x66,
+ 0x37, 0xe8, 0x49, 0x50, 0xc3, 0x80, 0x3e, 0x9e,
+ 0xdb, 0x01, 0x75, 0x07, 0xbb, 0xe8, 0x35, 0xe8,
+ 0x3b, 0x50, 0xc3, 0xc6, 0x06, 0x9e, 0xdb, 0x01,
+ 0xe8, 0x34, 0xcb, 0xe8, 0xc2, 0xef, 0xc6, 0x47,
+ 0x02, 0x00, 0x53, 0xe8, 0x46, 0x5e, 0xb9, 0x15,
+ 0x00, 0xb0, 0x09, 0xb4, 0x02, 0xe8, 0xc5, 0x59,
+ 0xb9, 0x22, 0x00, 0xb0, 0x15, 0xe8, 0xc6, 0x59,
+ 0xb9, 0x1a, 0x00, 0xb0, 0x1e, 0xe8, 0xc5, 0x59,
+ 0xb9, 0x28, 0x02, 0xe8, 0xb4, 0xca, 0x5b, 0xc6,
+ 0x47, 0x02, 0x12, 0xe8, 0xda, 0x5d, 0xe8, 0xd3,
+ 0xca, 0xb0, 0x14, 0xe8, 0xda, 0xd6, 0xc3, 0xbb,
+ 0x2a, 0x3f, 0xe8, 0xf0, 0x4f, 0xc3, 0xc7, 0x06,
+ 0xf3, 0xb4, 0x0b, 0x00, 0xb8, 0xe4, 0x00, 0xbb,
+ 0x6d, 0x00, 0xbf, 0x8a, 0x00, 0xbe, 0xa3, 0x00,
+ 0xb1, 0x0b, 0xb5, 0x03, 0xe8, 0x64, 0x5b, 0xc3,
+ 0xc7, 0x06, 0xf3, 0xb4, 0x0d, 0x00, 0xb8, 0x3f,
+ 0x01, 0xbb, 0xb5, 0x00, 0xbf, 0x05, 0x01, 0xbe,
+ 0xb7, 0x00, 0xb1, 0x01, 0xb5, 0x04, 0xe8, 0x4a,
+ 0x5b, 0xc3, 0xe8, 0x28, 0x00, 0xe8, 0xb7, 0xca,
+ 0xe8, 0x45, 0xef, 0xc6, 0x47, 0x01, 0x00, 0xe8,
+ 0xca, 0x5d, 0xb9, 0x05, 0x00, 0xb0, 0x0a, 0xb4,
+ 0x09, 0xe8, 0x49, 0x59, 0xb9, 0x1f, 0x02, 0xe8,
+ 0x5d, 0xca, 0xb0, 0x0f, 0xe8, 0x79, 0xd6, 0xb0,
+ 0x09, 0xe8, 0x21, 0xc9, 0xc3, 0xbe, 0xcb, 0x00,
+ 0xbf, 0xa9, 0x00, 0x81, 0x3e, 0xaf, 0x64, 0xcb,
+ 0x00, 0x75, 0x1a, 0x81, 0x3e, 0xb1, 0x64, 0xab,
+ 0x00, 0x75, 0x12, 0xc6, 0x06, 0xc3, 0x64, 0x01,
+ 0x57, 0x56, 0xe8, 0x46, 0xe5, 0xb8, 0x09, 0x00,
+ 0xe8, 0x4f, 0xce, 0x5e, 0x5f, 0xc6, 0x06, 0xc3,
+ 0x64, 0x02, 0xe8, 0x36, 0xe5, 0xc3, 0xbb, 0x54,
+ 0x3f, 0xe8, 0x59, 0x4f, 0xc3, 0xbb, 0x85, 0x3f,
+ 0xe8, 0x52, 0x4f, 0xc3, 0xc7, 0x06, 0xf3, 0xb4,
+ 0x0b, 0x00, 0xb8, 0x3f, 0x01, 0xbb, 0xc6, 0x00,
+ 0xbf, 0x2c, 0x01, 0xbe, 0xc4, 0x00, 0xb1, 0x01,
+ 0xb5, 0x04, 0xe8, 0xc6, 0x5a, 0x80, 0x3e, 0x9c,
+ 0xdb, 0x01, 0x74, 0x64, 0xe8, 0xd8, 0x54, 0xe8,
+ 0x26, 0xe5, 0x80, 0x3e, 0xc6, 0x64, 0x00, 0x75,
+ 0xf6, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x20, 0x02,
+ 0xb0, 0x01, 0xc7, 0x06, 0x23, 0xc4, 0x01, 0x00,
+ 0xc7, 0x06, 0x3b, 0x33, 0x15, 0x00, 0xc7, 0x06,
+ 0x3d, 0x33, 0x2a, 0x00, 0xc6, 0x06, 0xce, 0x00,
+ 0x02, 0xe8, 0x29, 0xc9, 0x72, 0x33, 0xa1, 0x3f,
+ 0x33, 0x0b, 0xc0, 0x74, 0x10, 0x3d, 0x30, 0x00,
+ 0x77, 0x0b, 0xb0, 0x01, 0xb9, 0x2c, 0x00, 0xba,
+ 0x33, 0x00, 0xe8, 0x81, 0xc1, 0xe8, 0x2e, 0x59,
+ 0x80, 0x3e, 0x27, 0xc4, 0x01, 0x75, 0x11, 0xc6,
+ 0x06, 0xcf, 0x00, 0x00, 0xe8, 0xca, 0xc6, 0xbb,
+ 0xb2, 0xda, 0xe8, 0x28, 0xc0, 0xe8, 0x3d, 0xc0,
+ 0xc3, 0xc6, 0x06, 0x9c, 0xdb, 0x01, 0xbb, 0x63,
+ 0x35, 0xb9, 0x3c, 0x00, 0xe8, 0xbd, 0x4f, 0xe8,
+ 0x04, 0x59, 0xb9, 0x11, 0x00, 0xb0, 0x05, 0xb4,
+ 0x08, 0xe8, 0x59, 0x58, 0xbb, 0x47, 0x33, 0xc7,
+ 0x07, 0x21, 0x02, 0xb0, 0x01, 0xe8, 0xb9, 0xc8,
+ 0xe8, 0x35, 0xee, 0xc6, 0x07, 0x10, 0xe8, 0xbb,
+ 0x5c, 0xb0, 0x02, 0xe8, 0x1b, 0xc8, 0xe8, 0x88,
+ 0xc6, 0xbb, 0x17, 0x09, 0xe8, 0xfe, 0xbf, 0xc3,
+ 0xbb, 0x2a, 0x3f, 0xe8, 0x87, 0x4e, 0xc3, 0xc7,
+ 0x06, 0xf3, 0xb4, 0x0c, 0x00, 0xb8, 0x00, 0x00,
+ 0xbb, 0xbd, 0x00, 0xbf, 0x1e, 0x00, 0xbe, 0xbd,
+ 0x00, 0xb1, 0x01, 0xb5, 0x02, 0xe8, 0xfb, 0x59,
+ 0xc3, 0xbb, 0xec, 0x3f, 0xe8, 0x66, 0x4e, 0xc3,
+ 0xe8, 0x64, 0xc9, 0xe8, 0xf2, 0xed, 0xc6, 0x07,
+ 0x00, 0xe8, 0x78, 0x5c, 0xb9, 0x05, 0x00, 0xb0,
+ 0x0b, 0xb4, 0x09, 0xe8, 0xf7, 0x57, 0xb9, 0x7d,
+ 0x02, 0xe8, 0x0b, 0xc9, 0xb0, 0x07, 0xe8, 0xd4,
+ 0xc7, 0xb0, 0x31, 0xe8, 0x22, 0xd5, 0xc3, 0x80,
+ 0x3e, 0x9f, 0xdb, 0x01, 0x74, 0x07, 0xbb, 0xe1,
+ 0x34, 0xe8, 0x31, 0x4e, 0xc3, 0xbb, 0x2e, 0x40,
+ 0xe8, 0x2a, 0x4e, 0xc3, 0xbb, 0xe1, 0x34, 0xe8,
+ 0x23, 0x4e, 0xc3, 0xe8, 0xa0, 0x52, 0xc3, 0x80,
+ 0x3e, 0x9f, 0xdb, 0x01, 0x74, 0x07, 0xbb, 0xe1,
+ 0x34, 0xe8, 0x11, 0x4e, 0xc3, 0x80, 0x3e, 0xa0,
+ 0xdb, 0x01, 0x75, 0x07, 0xbb, 0x31, 0x3e, 0xe8,
+ 0x03, 0x4e, 0xc3, 0xbe, 0xad, 0x00, 0xbf, 0x8a,
+ 0x00, 0xc6, 0x06, 0xc3, 0x64, 0x02, 0xe8, 0xca,
+ 0xe3, 0xb9, 0x1c, 0x00, 0xb0, 0x05, 0xb4, 0x08,
+ 0xe8, 0x92, 0x57, 0xb9, 0x47, 0x02, 0xe8, 0x7e,
+ 0xc8, 0xb9, 0x48, 0x02, 0xe8, 0x7b, 0xc8, 0xe8,
+ 0x52, 0x5a, 0xb8, 0x00, 0xa0, 0xb9, 0x00, 0x7d,
+ 0xe8, 0x7d, 0x5a, 0xa1, 0xb1, 0x32, 0xb9, 0x00,
+ 0x7d, 0xe8, 0x74, 0x5a, 0xa1, 0xb3, 0x32, 0xb9,
+ 0x00, 0x7d, 0xe8, 0x6b, 0x5a, 0xa1, 0xb5, 0x32,
+ 0xb9, 0x00, 0x7d, 0xe8, 0x62, 0x5a, 0xb8, 0x64,
+ 0x00, 0xe8, 0xb8, 0xcc, 0xe8, 0x32, 0x5a, 0xb9,
+ 0x48, 0x00, 0xb0, 0x12, 0xb4, 0x08, 0xe8, 0x4c,
+ 0x57, 0xb9, 0x49, 0x00, 0xb0, 0x27, 0xe8, 0x4d,
+ 0x57, 0xb9, 0x49, 0x02, 0xe8, 0x33, 0xc8, 0xe8,
+ 0xd1, 0x58, 0xc7, 0x06, 0xf3, 0xb4, 0x0b, 0x00,
+ 0xc6, 0x06, 0xdc, 0x1c, 0x01, 0xe8, 0x57, 0x59,
+ 0xc7, 0x06, 0xaf, 0x64, 0xc2, 0x00, 0xc7, 0x06,
+ 0xb1, 0x64, 0xa0, 0x00, 0xc6, 0x06, 0xc3, 0x64,
+ 0x02, 0xc6, 0x06, 0xcb, 0x64, 0x00, 0xc6, 0x06,
+ 0xcd, 0x64, 0x00, 0xe8, 0x20, 0xe9, 0xb9, 0x1c,
+ 0x00, 0xb0, 0x02, 0xb4, 0x08, 0xe8, 0x05, 0x57,
+ 0xb9, 0x4a, 0x02, 0xc6, 0x06, 0xdc, 0x1c, 0x01,
+ 0xe8, 0x0d, 0xc8, 0xbe, 0x8a, 0x00, 0xbf, 0xa3,
+ 0x00, 0xc6, 0x06, 0xc3, 0x64, 0x03, 0xe8, 0x1a,
+ 0xe3, 0xbb, 0x50, 0x36, 0xe8, 0x3e, 0x4d, 0xc6,
+ 0x06, 0xa0, 0xdb, 0x01, 0xe8, 0x26, 0x4a, 0xc3,
+ 0xc7, 0x06, 0xf3, 0xb4, 0x0b, 0x00, 0xb8, 0x00,
+ 0x00, 0xbb, 0x7c, 0x00, 0xbf, 0x3c, 0x00, 0xbe,
+ 0xaa, 0x00, 0xb1, 0x01, 0xb5, 0x02, 0xe8, 0xaa,
+ 0x58, 0xc3, 0xbb, 0x47, 0x40, 0xe8, 0x15, 0x4d,
+ 0xc3, 0xbb, 0x6d, 0x40, 0xe8, 0x0e, 0x4d, 0xc3,
+ 0x80, 0x3e, 0x99, 0xdb, 0x01, 0x75, 0x07, 0xbb,
+ 0x1f, 0x35, 0xe8, 0x00, 0x4d, 0xc3, 0xc6, 0x06,
+ 0x99, 0xdb, 0x01, 0xb9, 0x39, 0x00, 0xb0, 0x06,
+ 0xb4, 0x06, 0xe8, 0x98, 0x56, 0xb0, 0x0c, 0xe8,
+ 0x9c, 0x56, 0xb9, 0x3a, 0x00, 0xb0, 0x11, 0xe8,
+ 0x9b, 0x56, 0xb9, 0x05, 0x00, 0xb0, 0x25, 0xe8,
+ 0x9a, 0x56, 0xb9, 0x18, 0x02, 0xe8, 0x7f, 0xc7,
+ 0xe8, 0xa9, 0xc7, 0xb8, 0x0a, 0x00, 0xe8, 0xb1,
+ 0xcb, 0x8b, 0x3e, 0xb1, 0x64, 0x47, 0x8b, 0x36,
+ 0xaf, 0x64, 0xe8, 0x96, 0xe2, 0xbb, 0xc3, 0x30,
+ 0xe8, 0x2a, 0xbe, 0xb0, 0x08, 0xe8, 0x98, 0xd3,
+ 0xc3, 0x80, 0x3e, 0xb2, 0xdb, 0x01, 0x75, 0x0a,
+ 0xbb, 0x1d, 0x41, 0xe8, 0xa7, 0x4c, 0xe8, 0x43,
+ 0x00, 0xc3, 0xbb, 0x8a, 0x40, 0xe8, 0x9d, 0x4c,
+ 0xe8, 0x39, 0x00, 0xbb, 0x98, 0x40, 0xe8, 0x94,
+ 0x4c, 0xbb, 0xa7, 0x40, 0xbe, 0xe1, 0xcd, 0xe8,
+ 0x30, 0x00, 0xbb, 0xb6, 0x40, 0xe8, 0x85, 0x4c,
+ 0xbb, 0xce, 0x40, 0xbe, 0xac, 0xcd, 0xe8, 0x21,
+ 0x00, 0xbb, 0xe8, 0x40, 0xe8, 0x76, 0x4c, 0xbb,
+ 0x0f, 0x41, 0xbe, 0xe8, 0xcd, 0xe8, 0x12, 0x00,
+ 0xe8, 0x6a, 0xcb, 0xe8, 0x06, 0x00, 0xc6, 0x06,
+ 0xb2, 0xdb, 0x01, 0xc3, 0xbb, 0x91, 0x40, 0xbe,
+ 0xf8, 0xcd, 0xc6, 0x06, 0xe6, 0x1c, 0xe5, 0xe8,
+ 0xfc, 0x4e, 0xc3, 0xbb, 0x33, 0x41, 0xe8, 0x4c,
+ 0x4c, 0xc3, 0xc7, 0x06, 0xf3, 0xb4, 0x14, 0x00,
+ 0xb8, 0x00, 0x00, 0xbb, 0xb9, 0x00, 0xbf, 0x14,
+ 0x00, 0xbe, 0xb9, 0x00, 0xb1, 0x01, 0xb5, 0x02,
+ 0xe8, 0xc0, 0x57, 0xc3, 0xc7, 0x06, 0xf3, 0xb4,
+ 0x0b, 0x00, 0xb8, 0x00, 0x00, 0xbb, 0xaa, 0x00,
+ 0xbf, 0x3c, 0x00, 0xbe, 0xaa, 0x00, 0xb1, 0x01,
+ 0xb5, 0x02, 0xe8, 0xa6, 0x57, 0xc3, 0xc7, 0x06,
+ 0xf3, 0xb4, 0x12, 0x00, 0xb8, 0xf6, 0x00, 0xbb,
+ 0xc7, 0x00, 0xbf, 0xc9, 0x00, 0xbe, 0xc0, 0x00,
+ 0xb1, 0x01, 0xb5, 0x04, 0xe8, 0x8c, 0x57, 0xc3,
+ 0xe8, 0xfc, 0xc6, 0xe8, 0x8a, 0xeb, 0xc6, 0x47,
+ 0x02, 0x00, 0xe8, 0x0f, 0x5a, 0xb9, 0x22, 0x00,
+ 0xb0, 0x06, 0xb4, 0x06, 0xe8, 0x8e, 0x55, 0xb9,
+ 0x17, 0x02, 0xe8, 0xa2, 0xc6, 0xb0, 0x0b, 0xe8,
+ 0xbe, 0xd2, 0xb0, 0x01, 0xe8, 0x66, 0xc5, 0xc7,
+ 0x06, 0xf3, 0xb4, 0x0f, 0x00, 0xe8, 0x60, 0xeb,
+ 0xc6, 0x07, 0x00, 0xc7, 0x06, 0xf3, 0xb4, 0x10,
+ 0x00, 0xe8, 0x01, 0x00, 0xc3, 0xfe, 0x06, 0x98,
+ 0xdb, 0x80, 0x3e, 0x98, 0xdb, 0x02, 0x73, 0x01,
+ 0xc3, 0xc7, 0x06, 0xf3, 0xb4, 0x0f, 0x00, 0xb0,
+ 0x01, 0xe8, 0x39, 0xc5, 0xc7, 0x06, 0xf3, 0xb4,
+ 0x10, 0x00, 0xc3, 0xe8, 0xa1, 0xc6, 0xe8, 0x2f,
+ 0xeb, 0xc6, 0x47, 0x01, 0x00, 0xc6, 0x47, 0x03,
+ 0x00, 0xe8, 0xb0, 0x59, 0xb9, 0x21, 0x00, 0xb0,
+ 0x07, 0xb4, 0x09, 0xe8, 0x2f, 0x55, 0xb9, 0x16,
+ 0x02, 0xe8, 0x2e, 0xc6, 0xb0, 0x0a, 0xe8, 0x5f,
+ 0xd2, 0xb0, 0x02, 0xe8, 0x07, 0xc5, 0xe8, 0x07,
+ 0xeb, 0xc6, 0x47, 0x01, 0x0a, 0xe8, 0x48, 0x59,
+ 0xe8, 0x41, 0xc6, 0xc7, 0x06, 0xf3, 0xb4, 0x0f,
+ 0x00, 0xe8, 0xf4, 0xea, 0xc6, 0x47, 0x01, 0x00,
+ 0xc7, 0x06, 0xf3, 0xb4, 0x10, 0x00, 0xe8, 0x94,
+ 0xff, 0xc3, 0xe8, 0xe3, 0xea, 0xb0, 0x00, 0x88,
+ 0x07, 0xc7, 0x06, 0xf3, 0xb4, 0x0f, 0x00, 0xc6,
+ 0x06, 0xdc, 0x1c, 0x01, 0xe8, 0x10, 0x57, 0xb9,
+ 0x38, 0x02, 0xc6, 0x06, 0xdc, 0x1c, 0x01, 0xe8,
+ 0xcd, 0xc5, 0xc7, 0x06, 0xaf, 0x64, 0x73, 0x00,
+ 0xc7, 0x06, 0xb1, 0x64, 0xb4, 0x00, 0xc6, 0x06,
+ 0xc3, 0x64, 0x03, 0xc6, 0x06, 0xcb, 0x64, 0x01,
+ 0xc6, 0x06, 0xcd, 0x64, 0x01, 0xe8, 0xec, 0xc5,
+ 0xb9, 0x06, 0x00, 0xe8, 0x05, 0x5c, 0xc3, 0xc7,
+ 0x06, 0xf3, 0xb4, 0x0f, 0x00, 0xb8, 0x00, 0x00,
+ 0xbb, 0xac, 0x00, 0xbf, 0x1e, 0x00, 0xbe, 0xac,
+ 0x00, 0xb1, 0x01, 0xb5, 0x02, 0xe8, 0x83, 0x56,
+ 0xc3, 0xe8, 0x1a, 0x00, 0xc7, 0x06, 0xf3, 0xb4,
+ 0x13, 0x00, 0xb8, 0xdf, 0x00, 0xbb, 0xc7, 0x00,
+ 0xbf, 0xdf, 0x00, 0xbe, 0xc1, 0x00, 0xb1, 0x13,
+ 0xb5, 0x01, 0xe8, 0x66, 0x56, 0xc3, 0xe8, 0x7e,
+ 0x50, 0x81, 0x3e, 0xb1, 0x64, 0x95, 0x00, 0x76,
+ 0x09, 0xbe, 0x33, 0x00, 0xbf, 0x95, 0x00, 0xe8,
+ 0xaa, 0xe0, 0xbe, 0x5e, 0x00, 0xbf, 0x73, 0x00,
+ 0xc6, 0x06, 0xc3, 0x64, 0x04, 0xe8, 0x9c, 0xe0,
+ 0xc3, 0xe8, 0xda, 0xff, 0xe8, 0x2f, 0x4f, 0xc3,
+ 0xbb, 0x08, 0xdb, 0xe8, 0xff, 0xbb, 0x53, 0xe8,
+ 0x13, 0xbc, 0x5b, 0x81, 0xfb, 0x5d, 0x2c, 0x74,
+ 0x2e, 0x81, 0xfb, 0x9b, 0x2c, 0x75, 0x01, 0xc3,
+ 0xb8, 0x23, 0x01, 0xe8, 0x48, 0xc9, 0xb9, 0x34,
+ 0x00, 0xb0, 0x09, 0xb4, 0x0a, 0xe8, 0x2d, 0x54,
+ 0xb0, 0x0b, 0xe8, 0x31, 0x54, 0xb0, 0x0d, 0xe8,
+ 0x33, 0x54, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x39,
+ 0x02, 0xb0, 0x01, 0xe8, 0x83, 0xc4, 0xc3, 0xb8,
+ 0x23, 0x01, 0xe8, 0x21, 0xc9, 0xe8, 0xf8, 0xe9,
+ 0xc6, 0x07, 0x00, 0xe8, 0x7e, 0x58, 0xb9, 0x34,
+ 0x00, 0xb0, 0x09, 0xb4, 0x0a, 0xe8, 0xfd, 0x53,
+ 0xb0, 0x0b, 0xe8, 0x01, 0x54, 0xb0, 0x0d, 0xe8,
+ 0x03, 0x54, 0xb9, 0x35, 0x00, 0xb0, 0x20, 0xb4,
+ 0x0a, 0xe8, 0x00, 0x54, 0xbb, 0x47, 0x33, 0xc7,
+ 0x07, 0x3a, 0x02, 0xb0, 0x01, 0xe8, 0x49, 0xc4,
+ 0xe8, 0x2b, 0xc9, 0xbb, 0x1f, 0x55, 0xe8, 0x2c,
+ 0x4a, 0xb0, 0x05, 0xe8, 0xb7, 0xc3, 0xc6, 0x06,
+ 0xb0, 0xdb, 0x01, 0xc3, 0xbb, 0x0f, 0x57, 0xe8,
+ 0x1b, 0x4a, 0xc3, 0xe8, 0x19, 0xc5, 0xe8, 0xa7,
+ 0xe9, 0xc6, 0x47, 0x01, 0x00, 0xe8, 0x2c, 0x58,
+ 0xb9, 0x05, 0x00, 0xb0, 0x0a, 0xb4, 0x08, 0xe8,
+ 0xab, 0x53, 0xb9, 0x31, 0x02, 0xe8, 0xcd, 0xc4,
+ 0xb0, 0x1a, 0xe8, 0xdb, 0xd0, 0xb0, 0x06, 0xe8,
+ 0x83, 0xc3, 0xc3, 0xbb, 0x7e, 0x41, 0x80, 0x3e,
+ 0xb0, 0xdb, 0x01, 0x75, 0x03, 0xbb, 0xb1, 0x41,
+ 0xe8, 0xe2, 0x49, 0xc3, 0xc7, 0x06, 0xf3, 0xb4,
+ 0x12, 0x00, 0xb8, 0x5e, 0x00, 0xbb, 0x73, 0x00,
+ 0xbf, 0x5e, 0x00, 0xbe, 0x73, 0x00, 0xb1, 0x0b,
+ 0xb5, 0x03, 0xe8, 0x56, 0x55, 0xc3, 0xbb, 0xef,
+ 0x41, 0xe8, 0xc1, 0x49, 0xc3, 0xbb, 0x64, 0x41,
+ 0xe8, 0xba, 0x49, 0xc3, 0xb9, 0x43, 0x00, 0xb0,
+ 0x05, 0xb4, 0x03, 0xe8, 0x57, 0x53, 0xb9, 0xd7,
+ 0x03, 0xe8, 0x64, 0xc4, 0xbb, 0x55, 0x59, 0xe8,
+ 0xa3, 0x49, 0xc3, 0xe8, 0x20, 0x4e, 0xc3, 0xb9,
+ 0x42, 0x00, 0xb0, 0x05, 0xb4, 0x08, 0xe8, 0x3c,
+ 0x53, 0xb9, 0x43, 0x00, 0xb0, 0x0b, 0xe8, 0x3d,
+ 0x53, 0xb9, 0xd8, 0x03, 0xe8, 0x41, 0xc4, 0xbb,
+ 0x55, 0x59, 0xe8, 0x80, 0x49, 0xc3, 0xbb, 0xff,
+ 0x41, 0xe8, 0x79, 0x49, 0xc3, 0xbb, 0x3f, 0x42,
+ 0xe8, 0x72, 0x49, 0xc3, 0xbb, 0x51, 0x42, 0xe8,
+ 0x6b, 0x49, 0xc3, 0xbb, 0x67, 0x42, 0xe8, 0x64,
+ 0x49, 0xc3, 0xe8, 0xe1, 0x4d, 0xc3, 0xb9, 0x20,
+ 0x00, 0xb0, 0x07, 0xb4, 0x04, 0xe8, 0xfd, 0x52,
+ 0xb9, 0x72, 0x02, 0xe8, 0x0a, 0xc4, 0xe8, 0xdf,
+ 0xe8, 0xc6, 0x47, 0x01, 0x00, 0xe8, 0x64, 0x57,
+ 0xb0, 0x0c, 0xe8, 0xd0, 0xc2, 0xb0, 0x2d, 0xe8,
+ 0x1e, 0xd0, 0xbb, 0x04, 0x3b, 0xe8, 0x35, 0x49,
+ 0xc3, 0xbb, 0x3f, 0x42, 0xe8, 0x2e, 0x49, 0xc3,
+ 0xe8, 0x2c, 0xc4, 0xb0, 0x0d, 0xe8, 0x08, 0xd0,
+ 0xb0, 0x0e, 0xe8, 0xb0, 0xc2, 0xb9, 0x05, 0x00,
+ 0xb0, 0x0a, 0xb4, 0x08, 0xe8, 0xbe, 0x52, 0xe8,
+ 0xa6, 0xe8, 0xc6, 0x07, 0x00, 0xe8, 0x2c, 0x57,
+ 0xb9, 0x36, 0x02, 0xe8, 0xd7, 0xc3, 0xc3, 0xbb,
+ 0x89, 0x42, 0xe8, 0x00, 0x49, 0xc3, 0xb9, 0x0b,
+ 0x00, 0xb0, 0x04, 0xb4, 0x0c, 0xe8, 0x9d, 0x52,
+ 0xb9, 0x02, 0x02, 0xe8, 0x89, 0xc3, 0xe8, 0x7f,
+ 0xe8, 0xb0, 0x05, 0x88, 0x47, 0x02, 0x53, 0xe8,
+ 0x88, 0x57, 0x5b, 0xb0, 0x08, 0x88, 0x47, 0x04,
+ 0xe8, 0xa6, 0x57, 0xe8, 0xae, 0xc3, 0xb0, 0x0e,
+ 0xe8, 0x56, 0xc2, 0xb0, 0x0f, 0xe8, 0x51, 0xc2,
+ 0xb0, 0x10, 0xe8, 0x4c, 0xc2, 0xb0, 0x01, 0xe8,
+ 0x53, 0xc2, 0xc3, 0x80, 0x3e, 0x94, 0xdb, 0x01,
+ 0x74, 0x07, 0xbb, 0x63, 0x3e, 0xe8, 0xb5, 0x48,
+ 0xc3, 0x80, 0x3e, 0x95, 0xdb, 0x01, 0x75, 0x07,
+ 0xbb, 0x75, 0x3e, 0xe8, 0xa7, 0x48, 0xc3, 0xc6,
+ 0x06, 0x95, 0xdb, 0x01, 0xbb, 0x46, 0x67, 0xe8,
+ 0x20, 0xe8, 0x83, 0xc3, 0x03, 0xff, 0x37, 0x53,
+ 0xc7, 0x07, 0x3f, 0x01, 0xbe, 0xbc, 0x00, 0xbf,
+ 0xb3, 0x00, 0xe8, 0x5e, 0xde, 0xb9, 0x07, 0x00,
+ 0xb0, 0x10, 0xb4, 0x07, 0xe8, 0x26, 0x52, 0xb9,
+ 0x07, 0x02, 0xe8, 0x33, 0xc3, 0xb8, 0x96, 0x00,
+ 0xe8, 0x57, 0xc7, 0xbe, 0xa8, 0x00, 0xbf, 0xb3,
+ 0x00, 0xc6, 0x06, 0xc3, 0x64, 0x02, 0xe8, 0x3a,
+ 0xde, 0x5b, 0x8f, 0x07, 0xb0, 0x03, 0xe8, 0x3f,
+ 0xcf, 0xc3, 0xbb, 0x3f, 0x42, 0xe8, 0x55, 0x48,
+ 0xc3, 0xe8, 0xd2, 0x4c, 0xc3, 0xb9, 0x46, 0x00,
+ 0xb0, 0x06, 0xb4, 0x06, 0xe8, 0xee, 0x51, 0xb9,
+ 0x01, 0x02, 0xe8, 0xda, 0xc2, 0xe8, 0x7b, 0x53,
+ 0xc7, 0x06, 0xf3, 0xb4, 0x16, 0x00, 0xb8, 0x33,
+ 0x00, 0xbb, 0xb4, 0x00, 0xbf, 0x4e, 0x00, 0xbe,
+ 0xb4, 0x00, 0xb1, 0x01, 0xb5, 0x02, 0xe8, 0xb2,
+ 0x53, 0xc3, 0xb9, 0xfd, 0x01, 0xe8, 0xd8, 0xc2,
+ 0xbb, 0xce, 0x5d, 0xe8, 0x17, 0x48, 0xc3, 0xbb,
+ 0x64, 0x41, 0xe8, 0x10, 0x48, 0xc3, 0xbb, 0x64,
+ 0x41, 0xe8, 0x09, 0x48, 0xc3, 0xbb, 0x0f, 0x57,
+ 0xe8, 0x02, 0x48, 0xc3, 0xc7, 0x06, 0xf3, 0xb4,
+ 0x0f, 0x00, 0xb8, 0x9d, 0x00, 0xbb, 0xc7, 0x00,
+ 0xbf, 0x9d, 0x00, 0xbe, 0xb4, 0x00, 0xb1, 0x13,
+ 0xb5, 0x01, 0xe8, 0x76, 0x53, 0xc3, 0xc7, 0x06,
+ 0xf3, 0xb4, 0x15, 0x00, 0xb8, 0x00, 0x00, 0xbb,
+ 0xbb, 0x00, 0xbf, 0x30, 0x00, 0xbe, 0xbe, 0x00,
+ 0xb1, 0x01, 0xb5, 0x02, 0xe8, 0x5c, 0x53, 0xc3,
+ 0xc7, 0x06, 0xf3, 0xb4, 0x1b, 0x00, 0xb8, 0x54,
+ 0x00, 0xbb, 0xc7, 0x00, 0xbf, 0x84, 0x00, 0xbe,
+ 0xbe, 0x00, 0xb1, 0x01, 0xb5, 0x02, 0xe8, 0x42,
+ 0x53, 0xc3, 0xe8, 0x5e, 0xbf, 0xbb, 0xba, 0xda,
+ 0xe8, 0x02, 0xb9, 0xe8, 0x17, 0xb9, 0xbe, 0xe5,
+ 0x92, 0xb0, 0x0d, 0xe8, 0x3b, 0xc1, 0xc3, 0xb0,
+ 0x0e, 0xe8, 0x29, 0xc1, 0xb0, 0x06, 0xe8, 0x77,
+ 0xce, 0xb9, 0x05, 0x00, 0xb0, 0x07, 0xb4, 0x0c,
+ 0xe8, 0x32, 0x51, 0xb9, 0x09, 0x02, 0xe8, 0x1e,
+ 0xc2, 0xe8, 0x14, 0xe7, 0xc6, 0x47, 0x04, 0x00,
+ 0xe8, 0x4e, 0x55, 0xe8, 0x4e, 0xc2, 0xc3, 0xc6,
+ 0x06, 0x94, 0xdb, 0x01, 0xb9, 0x06, 0x00, 0xb0,
+ 0x04, 0xb4, 0x0b, 0xe8, 0x0f, 0x51, 0xb9, 0x03,
+ 0x02, 0xe8, 0xfb, 0xc1, 0xe8, 0xf1, 0xe6, 0xb0,
+ 0x06, 0x88, 0x47, 0x03, 0xe8, 0x22, 0x56, 0xe8,
+ 0x2a, 0xc2, 0xc3, 0xbb, 0xac, 0x42, 0xe8, 0x4c,
+ 0x47, 0xc3, 0xc7, 0x06, 0xf3, 0xb4, 0x14, 0x00,
+ 0xb8, 0x3f, 0x01, 0xbb, 0xbe, 0x00, 0xbf, 0x21,
+ 0x01, 0xbe, 0xbe, 0x00, 0xb1, 0x01, 0xb5, 0x04,
+ 0xe8, 0xc0, 0x52, 0xc3, 0xc7, 0x06, 0xf3, 0xb4,
+ 0x19, 0x00, 0xb8, 0x3f, 0x01, 0xbb, 0x92, 0x00,
+ 0xbf, 0x14, 0x01, 0xbe, 0x92, 0x00, 0xb1, 0x01,
+ 0xb5, 0x04, 0xe8, 0xa6, 0x52, 0xc3, 0xb9, 0x59,
+ 0x00, 0xb0, 0x04, 0xb4, 0x06, 0xe8, 0xb5, 0x50,
+ 0xb9, 0xd4, 0x03, 0xe8, 0xa1, 0xc1, 0xe8, 0x42,
+ 0x52, 0x80, 0x3e, 0xee, 0xdb, 0x01, 0x75, 0x06,
+ 0xb9, 0x07, 0x00, 0xe8, 0xed, 0x57, 0xc7, 0x06,
+ 0xf3, 0xb4, 0x17, 0x00, 0xb8, 0x4c, 0x00, 0xbb,
+ 0xc7, 0x00, 0xbf, 0x5e, 0x00, 0xbe, 0xbe, 0x00,
+ 0xb1, 0x13, 0xb5, 0x01, 0xe8, 0x6c, 0x52, 0xc3,
+ 0xbb, 0xc7, 0x42, 0xe8, 0xd7, 0x46, 0xc3, 0xbb,
+ 0x64, 0x41, 0xe8, 0xd0, 0x46, 0xc3, 0xbb, 0x64,
+ 0x41, 0xe8, 0xc9, 0x46, 0xc3, 0xbb, 0x64, 0x41,
+ 0xe8, 0xc2, 0x46, 0xc3, 0xe8, 0x04, 0x00, 0xe8,
+ 0x87, 0x00, 0xc3, 0xc7, 0x06, 0xf3, 0xb4, 0x18,
+ 0x00, 0xc6, 0x06, 0xdc, 0x1c, 0x01, 0xc6, 0x06,
+ 0xc5, 0x64, 0x00, 0xc6, 0x06, 0x3d, 0x66, 0x00,
+ 0xc6, 0x06, 0x40, 0x67, 0xff, 0xc6, 0x06, 0xc4,
+ 0x64, 0x01, 0xe8, 0x93, 0xdb, 0x80, 0x3e, 0xad,
+ 0x64, 0x01, 0x75, 0x05, 0xe8, 0x05, 0x53, 0xeb,
+ 0x03, 0xe8, 0x1a, 0x53, 0xe8, 0x3e, 0x54, 0x80,
+ 0x3e, 0xa4, 0xdb, 0x01, 0x74, 0x1c, 0xa1, 0xb3,
+ 0x32, 0xbb, 0x00, 0xfa, 0x1e, 0x53, 0x8e, 0xd8,
+ 0xb9, 0x70, 0x02, 0xe8, 0x2d, 0x00, 0x5b, 0x81,
+ 0xc3, 0xd6, 0x02, 0xb9, 0x27, 0x00, 0xe8, 0x22,
+ 0x00, 0x1f, 0xe8, 0x7a, 0x52, 0x80, 0x3e, 0xad,
+ 0x64, 0x01, 0x75, 0x04, 0xe8, 0xda, 0x52, 0xc3,
+ 0xb8, 0x00, 0xa0, 0xb9, 0x00, 0x7d, 0xe8, 0xf7,
+ 0x52, 0xe8, 0xe7, 0x52, 0xe8, 0xb2, 0x52, 0xe8,
+ 0xae, 0x4e, 0xc3, 0x8a, 0x07, 0x2c, 0x20, 0x73,
+ 0x02, 0xb0, 0x00, 0x88, 0x07, 0x43, 0xe2, 0xf3,
+ 0xc3, 0xc7, 0x06, 0xaf, 0x64, 0xe6, 0x00, 0xc7,
+ 0x06, 0xb1, 0x64, 0xaa, 0x00, 0xc6, 0x06, 0xc3,
+ 0x64, 0x01, 0xc6, 0x06, 0xcb, 0x64, 0x01, 0xc6,
+ 0x06, 0xcd, 0x64, 0x01, 0xb9, 0x34, 0x00, 0xb0,
+ 0x03, 0xb4, 0x0b, 0xe8, 0xb7, 0x4f, 0xb0, 0x07,
+ 0xe8, 0xbb, 0x4f, 0xb0, 0x0b, 0xe8, 0xbd, 0x4f,
+ 0xb0, 0x0e, 0xe8, 0xbf, 0x4f, 0xb0, 0x12, 0xe8,
+ 0xc1, 0x4f, 0xb0, 0x15, 0xe8, 0xc3, 0x4f, 0xb0,
+ 0x19, 0xe8, 0xc5, 0x4f, 0xb9, 0x59, 0x02, 0xc6,
+ 0x06, 0xdc, 0x1c, 0x01, 0xe8, 0xa1, 0xc0, 0xbe,
+ 0xe6, 0x00, 0xbf, 0xb3, 0x00, 0xc6, 0x06, 0xc3,
+ 0x64, 0x03, 0xe8, 0xae, 0xdb, 0x80, 0x3e, 0xa4,
+ 0xdb, 0x01, 0x74, 0x06, 0xbb, 0xea, 0x37, 0xe8,
+ 0xcb, 0x45, 0xc3, 0x80, 0x3e, 0xad, 0xdb, 0x01,
+ 0x74, 0x32, 0xb9, 0x2b, 0x00, 0xb0, 0x04, 0xb4,
+ 0x0b, 0xe8, 0x61, 0x4f, 0xb9, 0x2a, 0x00, 0xb0,
+ 0x0f, 0xe8, 0x62, 0x4f, 0xb0, 0x11, 0xe8, 0x64,
+ 0x4f, 0xb0, 0x13, 0xe8, 0x66, 0x4f, 0xbb, 0x47,
+ 0x33, 0xc7, 0x07, 0x90, 0x02, 0xb0, 0x01, 0xe8,
+ 0xaf, 0xbf, 0xe8, 0x91, 0xc4, 0xbb, 0x16, 0x3c,
+ 0xe8, 0x92, 0x45, 0xc3, 0x80, 0x3e, 0xa3, 0xdb,
+ 0x01, 0x74, 0x29, 0xb9, 0x1c, 0x00, 0xb0, 0x03,
+ 0xb4, 0x0e, 0xe8, 0x28, 0x4f, 0xb9, 0x54, 0x02,
+ 0xe8, 0x14, 0xc0, 0xe8, 0x0a, 0xe5, 0xb0, 0x1e,
+ 0x88, 0x47, 0x01, 0xe8, 0x3b, 0x54, 0xe8, 0x43,
+ 0xc0, 0xc6, 0x06, 0xa3, 0xdb, 0x01, 0xb0, 0x08,
+ 0xe8, 0xe6, 0xbe, 0xc3, 0xe8, 0x60, 0xc0, 0xe8,
+ 0xee, 0xe4, 0xc6, 0x47, 0x01, 0x00, 0xe8, 0x73,
+ 0x53, 0xb9, 0x04, 0x00, 0xb0, 0x04, 0xb4, 0x0e,
+ 0xe8, 0xf2, 0x4e, 0xb9, 0x55, 0x02, 0xe8, 0x06,
+ 0xc0, 0xc6, 0x06, 0xa3, 0xdb, 0x00, 0xb0, 0x08,
+ 0xe8, 0xca, 0xbe, 0xbb, 0xb8, 0x37, 0xe8, 0x34,
+ 0x45, 0xc7, 0x06, 0xf3, 0xb4, 0x18, 0x00, 0xe8,
+ 0xbe, 0xe4, 0xc6, 0x47, 0x01, 0x20, 0xb0, 0x04,
+ 0xe8, 0xa6, 0xbe, 0xc7, 0x06, 0xf3, 0xb4, 0x15,
+ 0x00, 0xc3, 0xbb, 0x14, 0xdb, 0xe8, 0x6d, 0xb6,
+ 0xe8, 0x82, 0xb6, 0xc3, 0xb9, 0xfe, 0x01, 0xe8,
+ 0xc6, 0xbf, 0xc6, 0x06, 0xe6, 0x1c, 0xe5, 0xbb,
+ 0xc2, 0x5d, 0xbe, 0x8c, 0x7d, 0xe8, 0xa6, 0x47,
+ 0xc3, 0xbb, 0xbd, 0x2c, 0xe8, 0x66, 0xb6, 0xb8,
+ 0x96, 0x00, 0xe8, 0xd5, 0xc3, 0xbb, 0xc2, 0x2d,
+ 0xe8, 0x5a, 0xb6, 0x8b, 0x36, 0xaf, 0x64, 0x8b,
+ 0x3e, 0xb1, 0x64, 0x83, 0xef, 0x0c, 0xe8, 0xb2,
+ 0xda, 0xb9, 0x22, 0x00, 0xb0, 0x05, 0xb4, 0x03,
+ 0xe8, 0x7a, 0x4e, 0xb9, 0x5f, 0x02, 0xe8, 0x66,
+ 0xbf, 0xe8, 0x5c, 0xe4, 0xc6, 0x07, 0x00, 0xe8,
+ 0x9e, 0x52, 0xb9, 0x60, 0x02, 0xe8, 0x5a, 0xbf,
+ 0xb9, 0x61, 0x02, 0xe8, 0x54, 0xbf, 0xb9, 0x62,
+ 0x02, 0xe8, 0x4e, 0xbf, 0xb9, 0x05, 0x00, 0xb0,
+ 0x19, 0xb4, 0x00, 0xe8, 0x4f, 0x4e, 0xb9, 0x63,
+ 0x02, 0xe8, 0x3e, 0xbf, 0xc7, 0x06, 0xaf, 0x64,
+ 0x10, 0x00, 0xc6, 0x06, 0xcc, 0x64, 0x00, 0xc6,
+ 0x06, 0xcd, 0x64, 0x00, 0xc6, 0x06, 0xcb, 0x64,
+ 0x00, 0xc6, 0x06, 0xc3, 0x64, 0x04, 0xc6, 0x06,
+ 0xdc, 0x64, 0x01, 0xe8, 0x56, 0xbf, 0xb0, 0x26,
+ 0xe8, 0x5d, 0xcb, 0xb0, 0x0c, 0xe8, 0x05, 0xbe,
+ 0xc3, 0xe8, 0xfc, 0xbb, 0xbb, 0xc4, 0xda, 0xe8,
+ 0xc3, 0xb5, 0xe8, 0xd8, 0xb5, 0xc3, 0xb9, 0x59,
+ 0x00, 0xb0, 0x05, 0xb4, 0x06, 0xe8, 0x05, 0x4e,
+ 0xb9, 0x43, 0x00, 0xb0, 0x0b, 0xe8, 0x06, 0x4e,
+ 0xb9, 0xd6, 0x03, 0xe8, 0x0a, 0xbf, 0xbb, 0x55,
+ 0x59, 0xe8, 0x49, 0x44, 0xc3, 0x80, 0x3e, 0xa7,
+ 0xdb, 0x01, 0x75, 0x07, 0xbb, 0xac, 0x3b, 0xe8,
+ 0x3b, 0x44, 0xc3, 0x80, 0x3e, 0x92, 0xdb, 0x01,
+ 0x74, 0x25, 0x8b, 0x36, 0xaf, 0x64, 0x8b, 0x3e,
+ 0xb1, 0x64, 0x56, 0x57, 0xc6, 0x06, 0xc3, 0x64,
+ 0x03, 0xe8, 0xf7, 0xd9, 0xe8, 0xa9, 0xbb, 0xbb,
+ 0xa0, 0x15, 0xe8, 0x88, 0xb5, 0x5f, 0x5e, 0xc6,
+ 0x06, 0xc3, 0x64, 0x01, 0xe8, 0xe4, 0xd9, 0xb9,
+ 0x42, 0x00, 0xb0, 0x05, 0xb4, 0x07, 0xe8, 0xac,
+ 0x4d, 0xb9, 0x43, 0x00, 0xb0, 0x14, 0xe8, 0xad,
+ 0x4d, 0xb9, 0x05, 0x00, 0xb0, 0x17, 0xe8, 0xac,
+ 0x4d, 0xb9, 0x77, 0x02, 0xe8, 0xa9, 0xbe, 0xb0,
+ 0x2f, 0xe8, 0xcc, 0xca, 0xc6, 0x06, 0xa7, 0xdb,
+ 0x01, 0xc3, 0xbb, 0x06, 0x43, 0xe8, 0xdd, 0x43,
+ 0xc3, 0xbb, 0x64, 0x41, 0xe8, 0xd6, 0x43, 0xc3,
+ 0xe8, 0x53, 0x48, 0xc3, 0x80, 0x3e, 0x92, 0xdb,
+ 0x01, 0x74, 0x29, 0x8b, 0x36, 0xaf, 0x64, 0x8b,
+ 0x3e, 0xb1, 0x64, 0xc6, 0x06, 0xc3, 0x64, 0x03,
+ 0x57, 0x56, 0xe8, 0x8e, 0xd9, 0xe8, 0x40, 0xbb,
+ 0xbb, 0xce, 0xda, 0xe8, 0x07, 0xb5, 0xe8, 0x1c,
+ 0xb5, 0x5e, 0x5f, 0xc6, 0x06, 0xc3, 0x64, 0x01,
+ 0xe8, 0x78, 0xd9, 0xc3, 0xe8, 0xa0, 0xbe, 0xb0,
+ 0x02, 0xe8, 0x7c, 0xca, 0xb0, 0x07, 0xe8, 0x24,
+ 0xbd, 0xe8, 0x24, 0xe3, 0xc6, 0x07, 0x00, 0xe8,
+ 0xaa, 0x51, 0xb9, 0x20, 0x00, 0xb0, 0x07, 0xb4,
+ 0x09, 0xe8, 0x29, 0x4d, 0xb9, 0x08, 0x02, 0xe8,
+ 0x3d, 0xbe, 0xc3, 0xbb, 0x3f, 0x42, 0xe8, 0x74,
+ 0x43, 0xc3, 0xbb, 0x3f, 0x42, 0xe8, 0x6d, 0x43,
+ 0xc3, 0xbb, 0x1e, 0x43, 0xe8, 0x66, 0x43, 0xc3,
+ 0xb9, 0x58, 0x00, 0xb0, 0x05, 0xb4, 0x03, 0xe8,
+ 0x03, 0x4d, 0xb9, 0xd5, 0x03, 0xe8, 0xff, 0xbd,
+ 0xe8, 0x90, 0x4e, 0xc7, 0x06, 0xf3, 0xb4, 0x14,
+ 0x00, 0xb8, 0xa0, 0x00, 0xbb, 0xa5, 0x00, 0xbf,
+ 0xa0, 0x00, 0xbe, 0xb9, 0x00, 0xb1, 0x0b, 0xb5,
+ 0x03, 0xe8, 0xc7, 0x4e, 0xc3, 0xbb, 0xff, 0x41,
+ 0xe8, 0x32, 0x43, 0xc3, 0x80, 0x3e, 0x92, 0xdb,
+ 0x01, 0x74, 0x29, 0x8b, 0x36, 0xaf, 0x64, 0x8b,
+ 0x3e, 0xb1, 0x64, 0x56, 0x57, 0xc6, 0x06, 0xc3,
+ 0x64, 0x03, 0xe8, 0xee, 0xd8, 0xe8, 0xa0, 0xba,
+ 0xbb, 0xd4, 0xda, 0xe8, 0x67, 0xb4, 0xe8, 0x7c,
+ 0xb4, 0x5f, 0x5e, 0xc6, 0x06, 0xc3, 0x64, 0x01,
+ 0xe8, 0xd8, 0xd8, 0xc3, 0xe8, 0x00, 0xbe, 0xb8,
+ 0x02, 0x00, 0xe8, 0x1c, 0xd1, 0x32, 0xe4, 0xbb,
+ 0xc7, 0x32, 0xb1, 0x1b, 0x48, 0xf6, 0xe1, 0x03,
+ 0xd8, 0xc7, 0x07, 0x00, 0x00, 0xb9, 0x20, 0x00,
+ 0xb0, 0x07, 0xb4, 0x08, 0xe8, 0x86, 0x4c, 0xb9,
+ 0xfc, 0x01, 0xe8, 0x9a, 0xbd, 0xb0, 0x0d, 0xe8,
+ 0x63, 0xbc, 0xb0, 0x07, 0xe8, 0xb1, 0xc9, 0xc3,
+ 0x80, 0x3e, 0xa5, 0xdb, 0x01, 0x74, 0x37, 0xe8,
+ 0x2b, 0xba, 0xbb, 0xda, 0xda, 0xe8, 0x15, 0xb4,
+ 0x53, 0xe8, 0x29, 0xb4, 0x5b, 0x81, 0xfb, 0x13,
+ 0x19, 0x75, 0x22, 0xb8, 0x64, 0x00, 0xe8, 0x91,
+ 0xc1, 0x8b, 0x3e, 0xb1, 0x64, 0x8b, 0x36, 0xaf,
+ 0x64, 0xc6, 0x06, 0xc3, 0x64, 0x03, 0xe8, 0x72,
+ 0xd8, 0xe8, 0x92, 0xc1, 0xbb, 0xd5, 0x34, 0xe8,
+ 0x93, 0x42, 0xe8, 0x89, 0xc1, 0xc3, 0xc6, 0x06,
+ 0xa5, 0xdb, 0x02, 0xe8, 0xef, 0xb9, 0xbb, 0x4f,
+ 0x1f, 0xe8, 0xf1, 0xb3, 0xb8, 0x01, 0x01, 0xe8,
+ 0x34, 0xc1, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x5c,
+ 0x02, 0xb0, 0x01, 0xe8, 0x3a, 0xbc, 0xe8, 0x03,
+ 0x4d, 0xc7, 0x06, 0xf3, 0xb4, 0x15, 0x00, 0xb0,
+ 0x04, 0xe8, 0xf1, 0xbb, 0xb0, 0x0c, 0xe8, 0xe0,
+ 0xbb, 0xe8, 0xec, 0xe1, 0x53, 0xc6, 0x07, 0x00,
+ 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x02, 0x5e, 0x02,
+ 0xe8, 0x01, 0x4f, 0xb9, 0x2e, 0x00, 0xb0, 0x05,
+ 0xb4, 0x02, 0xe8, 0xe8, 0x4b, 0xb0, 0x02, 0xe8,
+ 0x48, 0xbc, 0xe8, 0xcf, 0x4c, 0x5b, 0xc6, 0x07,
+ 0x21, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x5d, 0x02,
+ 0xc7, 0x06, 0xf3, 0xb4, 0x17, 0x00, 0xe8, 0xe4,
+ 0x4e, 0xb0, 0x01, 0xe8, 0x2c, 0xbc, 0xe8, 0x65,
+ 0x4c, 0xc6, 0x06, 0x33, 0x33, 0x01, 0xc6, 0x06,
+ 0xdd, 0x1c, 0x02, 0xe8, 0x77, 0xb9, 0xbb, 0x02,
+ 0x20, 0xe8, 0x79, 0xb3, 0xc3, 0x80, 0x3e, 0x97,
+ 0xdb, 0x00, 0x74, 0x07, 0xbb, 0x59, 0x3d, 0xe8,
+ 0xfb, 0x41, 0xc3, 0xbe, 0xf5, 0x00, 0xbf, 0xc6,
+ 0x00, 0xc6, 0x06, 0xc3, 0x64, 0x01, 0xe8, 0xc2,
+ 0xd7, 0xe8, 0x00, 0xba, 0xbb, 0xd7, 0x21, 0xe8,
+ 0x53, 0xb3, 0xc6, 0x06, 0x97, 0xdb, 0x01, 0xb8,
+ 0x01, 0x02, 0xe8, 0x91, 0xc0, 0xb9, 0x0d, 0x00,
+ 0xb0, 0x0a, 0xb4, 0x0c, 0xe8, 0x76, 0x4b, 0xb0,
+ 0x0c, 0xe8, 0x7a, 0x4b, 0xb0, 0x0e, 0xe8, 0x7c,
+ 0x4b, 0xb0, 0x10, 0xe8, 0x7e, 0x4b, 0xb0, 0x12,
+ 0xe8, 0x80, 0x4b, 0xb0, 0x14, 0xe8, 0x82, 0x4b,
+ 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x02, 0x10, 0x02,
+ 0xb0, 0x02, 0xe8, 0xbc, 0xbb, 0xb8, 0x32, 0x00,
+ 0xe8, 0x87, 0xc0, 0xb9, 0x07, 0x00, 0xe8, 0x92,
+ 0x52, 0xc6, 0x06, 0xee, 0xdb, 0x01, 0xb9, 0x38,
+ 0x00, 0xb0, 0x03, 0xb4, 0x0a, 0xe8, 0x35, 0x4b,
+ 0xb0, 0x05, 0xe8, 0x39, 0x4b, 0xb0, 0x07, 0xe8,
+ 0x3b, 0x4b, 0xb0, 0x09, 0xe8, 0x3d, 0x4b, 0xb0,
+ 0x0b, 0xe8, 0x3f, 0x4b, 0xb0, 0x0d, 0xe8, 0x41,
+ 0x4b, 0xb0, 0x0f, 0xe8, 0x43, 0x4b, 0xb0, 0x11,
+ 0xe8, 0x45, 0x4b, 0xb9, 0x0d, 0x02, 0xe8, 0xfe,
+ 0xbb, 0xb9, 0x38, 0x00, 0xb0, 0x01, 0xb4, 0x0a,
+ 0xe8, 0x02, 0x4b, 0xb0, 0x03, 0xe8, 0x06, 0x4b,
+ 0xb0, 0x05, 0xe8, 0x08, 0x4b, 0xb0, 0x07, 0xe8,
+ 0x0a, 0x4b, 0xb0, 0x09, 0xe8, 0x0c, 0x4b, 0xb0,
+ 0x0b, 0xe8, 0x0e, 0x4b, 0xb0, 0x0d, 0xe8, 0x10,
+ 0x4b, 0xb9, 0x28, 0x00, 0xb0, 0x0f, 0xe8, 0x0f,
+ 0x4b, 0xb0, 0x12, 0xe8, 0x11, 0x4b, 0xb0, 0x16,
+ 0xe8, 0x13, 0x4b, 0xb9, 0x0e, 0x02, 0xe8, 0xc1,
+ 0xbb, 0xb9, 0x36, 0x00, 0xb0, 0x01, 0xb4, 0x0a,
+ 0xe8, 0xc2, 0x4a, 0xb9, 0x37, 0x00, 0xb0, 0x05,
+ 0xe8, 0xc3, 0x4a, 0xb9, 0x38, 0x00, 0xb0, 0x09,
+ 0xe8, 0xc2, 0x4a, 0xb0, 0x0d, 0xe8, 0xc4, 0x4a,
+ 0xb9, 0x18, 0x00, 0xb0, 0x10, 0xe8, 0xc3, 0x4a,
+ 0xb9, 0x0f, 0x02, 0xe8, 0x94, 0xbb, 0xe8, 0xcb,
+ 0xbb, 0xe8, 0xea, 0xbf, 0xbb, 0x19, 0x22, 0xe8,
+ 0x5b, 0xb2, 0xb0, 0x02, 0xbe, 0x20, 0x98, 0xe8,
+ 0x7f, 0xba, 0xc3, 0x80, 0x3e, 0xee, 0xdb, 0x01,
+ 0x75, 0x06, 0xb9, 0x06, 0x00, 0xe8, 0xcb, 0x51,
+ 0xc7, 0x06, 0xf3, 0xb4, 0x15, 0x00, 0xb8, 0x63,
+ 0x00, 0xbb, 0xb4, 0x00, 0xbf, 0x63, 0x00, 0xbe,
+ 0xba, 0x00, 0xb1, 0x0b, 0xb5, 0x03, 0xe8, 0x4a,
+ 0x4c, 0xc3, 0xbb, 0x64, 0x41, 0xe8, 0xb5, 0x40,
+ 0xc3, 0xbb, 0x64, 0x41, 0xe8, 0xae, 0x40, 0xc3,
+ 0xbb, 0xff, 0x41, 0xe8, 0xa7, 0x40, 0xc3, 0xbb,
+ 0x4e, 0x43, 0xe8, 0xa0, 0x40, 0xc3, 0xe8, 0x1d,
+ 0x45, 0xc3, 0x80, 0x3e, 0xb1, 0xdb, 0x01, 0x75,
+ 0x07, 0xbb, 0x80, 0x43, 0xe8, 0x8e, 0x40, 0xc3,
+ 0x8b, 0x36, 0xaf, 0x64, 0x8b, 0x3e, 0xb1, 0x64,
+ 0xc6, 0x06, 0xc3, 0x64, 0x04, 0xe8, 0x53, 0xd6,
+ 0xe8, 0xe2, 0xb7, 0xbb, 0xfc, 0xda, 0xe8, 0xcc,
+ 0xb1, 0xe8, 0xe1, 0xb1, 0xc3, 0xbb, 0xac, 0x43,
+ 0xe8, 0x6a, 0x40, 0xc3, 0xbb, 0xce, 0x43, 0xe8,
+ 0x63, 0x40, 0xc3, 0x80, 0x3e, 0x9a, 0xdb, 0x00,
+ 0x75, 0x0d, 0xe8, 0xc0, 0xb7, 0xbb, 0xf6, 0xda,
+ 0xe8, 0xaa, 0xb1, 0xe8, 0xbf, 0xb1, 0xc3, 0xe8,
+ 0xb3, 0xb7, 0xbb, 0x1e, 0x1e, 0xe8, 0xb5, 0xb1,
+ 0xe8, 0x3b, 0xbf, 0xe8, 0x41, 0xbb, 0xb0, 0x0c,
+ 0xe8, 0x1d, 0xc7, 0xb0, 0x0c, 0xe8, 0xc5, 0xb9,
+ 0xe8, 0xc5, 0xdf, 0xc6, 0x07, 0x00, 0xe8, 0x4b,
+ 0x4e, 0xb9, 0x05, 0x00, 0xb0, 0x06, 0xb4, 0x04,
+ 0xe8, 0xca, 0x49, 0xb9, 0x1d, 0x02, 0xe8, 0xec,
+ 0xba, 0xc3, 0xe8, 0x99, 0x44, 0xc3, 0x80, 0x3e,
+ 0xb3, 0xdb, 0x01, 0x75, 0x07, 0xbb, 0xa7, 0x44,
+ 0xe8, 0x0a, 0x40, 0xc3, 0xbb, 0x12, 0x44, 0xe8,
+ 0x18, 0x00, 0xbb, 0x4f, 0x44, 0xe8, 0x12, 0x00,
+ 0xbb, 0x6b, 0x44, 0xe8, 0x0c, 0x00, 0xbb, 0x92,
+ 0x44, 0xe8, 0xf1, 0x3f, 0xc6, 0x06, 0xb3, 0xdb,
+ 0x01, 0xc3, 0xe8, 0xe8, 0x3f, 0xb8, 0x96, 0x00,
+ 0xe8, 0xc7, 0xbe, 0xc3, 0xe8, 0x5f, 0x44, 0xc3,
+ 0xbb, 0x1e, 0x43, 0xe8, 0xd7, 0x3f, 0xc3, 0xe8,
+ 0x33, 0x00, 0xc3, 0x80, 0x3e, 0xa4, 0xdb, 0x01,
+ 0x74, 0x04, 0xe8, 0x28, 0x00, 0xc3, 0xe8, 0xc6,
+ 0xba, 0xe8, 0x54, 0xdf, 0xc6, 0x07, 0x00, 0xe8,
+ 0xda, 0x4d, 0xb9, 0x38, 0x00, 0xb0, 0x0a, 0xb4,
+ 0x02, 0xe8, 0x59, 0x49, 0xb9, 0x57, 0x02, 0xe8,
+ 0x7b, 0xba, 0xb0, 0x25, 0xe8, 0x89, 0xc6, 0xb0,
+ 0x02, 0xe8, 0x31, 0xb9, 0xc3, 0x80, 0x3e, 0xae,
+ 0xdb, 0x01, 0x75, 0x0a, 0xe8, 0x1a, 0x00, 0xbb,
+ 0xdd, 0x2f, 0xe8, 0x00, 0xb1, 0xc3, 0xbb, 0x41,
+ 0x2e, 0xe8, 0xf9, 0xb0, 0xe8, 0x0a, 0x00, 0xe8,
+ 0x83, 0xbe, 0xbb, 0x6d, 0x2e, 0xe8, 0xed, 0xb0,
+ 0xc3, 0xa0, 0xab, 0x64, 0x8a, 0x26, 0xaa, 0x64,
+ 0x50, 0xc6, 0x06, 0xab, 0x64, 0x02, 0xc6, 0x06,
+ 0xaa, 0x64, 0x02, 0xe8, 0xd1, 0xaa, 0xe8, 0x9d,
+ 0xaa, 0xb8, 0x03, 0x00, 0xe8, 0x4e, 0x43, 0x8b,
+ 0x77, 0x0d, 0x8b, 0x7f, 0x0f, 0x8a, 0x47, 0x11,
+ 0xa2, 0xc3, 0x64, 0xe8, 0x25, 0xd5, 0xe8, 0x22,
+ 0x00, 0xbe, 0x30, 0x00, 0xbf, 0xbe, 0x00, 0xc6,
+ 0x06, 0xc3, 0x64, 0x03, 0xe8, 0x14, 0xd5, 0x58,
+ 0xa2, 0xab, 0x64, 0x88, 0x26, 0xaa, 0x64, 0xe8,
+ 0x9d, 0xaa, 0xe8, 0x69, 0xaa, 0xc6, 0x06, 0xae,
+ 0xdb, 0x01, 0xc3, 0xb9, 0x34, 0x00, 0xb0, 0x0a,
+ 0xb4, 0x0b, 0xe8, 0xc8, 0x48, 0xb0, 0x0e, 0xe8,
+ 0xcc, 0x48, 0xb0, 0x12, 0xe8, 0xce, 0x48, 0xb0,
+ 0x15, 0xe8, 0xd0, 0x48, 0xb0, 0x19, 0xe8, 0xd2,
+ 0x48, 0xb0, 0x1c, 0xe8, 0xd4, 0x48, 0xb0, 0x20,
+ 0xe8, 0xd6, 0x48, 0xb9, 0x58, 0x02, 0xe8, 0x96,
+ 0xb9, 0xe8, 0x37, 0x4a, 0xc7, 0x06, 0xf3, 0xb4,
+ 0x15, 0x00, 0xb8, 0x29, 0x01, 0xbb, 0xb2, 0x00,
+ 0xbf, 0x29, 0x01, 0xbe, 0xb5, 0x00, 0xb1, 0x0b,
+ 0xb5, 0x03, 0xe8, 0x6e, 0x4a, 0xc3, 0x80, 0x3e,
+ 0xa4, 0xdb, 0x01, 0x75, 0x07, 0xbb, 0x01, 0x38,
+ 0xe8, 0xd2, 0x3e, 0xc3, 0xb9, 0x47, 0x00, 0xb0,
+ 0x06, 0xb4, 0x0c, 0xe8, 0x6f, 0x48, 0xb9, 0x56,
+ 0x02, 0xe8, 0x5b, 0xb9, 0xe8, 0x76, 0x4c, 0x80,
+ 0x3e, 0xad, 0x64, 0x01, 0x75, 0x0e, 0x8b, 0x16,
+ 0xb3, 0x32, 0xbe, 0x00, 0xfa, 0xb0, 0x40, 0xe8,
+ 0x78, 0x45, 0xeb, 0x0c, 0x8b, 0x16, 0xb3, 0x32,
+ 0xbe, 0x00, 0xfa, 0xb0, 0x40, 0xe8, 0x6a, 0x45,
+ 0xe8, 0x71, 0xb9, 0xe8, 0x2a, 0xde, 0xc6, 0x47,
+ 0x02, 0x00, 0xe8, 0xaf, 0x4c, 0xbb, 0x47, 0x33,
+ 0xc7, 0x07, 0x94, 0x02, 0xb0, 0x01, 0xe8, 0x4f,
+ 0xb8, 0xe8, 0x18, 0x49, 0xb0, 0x01, 0xe8, 0x0c,
+ 0xb8, 0xb0, 0x01, 0xb4, 0x00, 0xe8, 0x99, 0xcc,
+ 0xe8, 0xad, 0xcc, 0xc6, 0x06, 0xa4, 0xdb, 0x01,
+ 0xc3, 0x80, 0x3e, 0xa4, 0xdb, 0x01, 0x74, 0x04,
+ 0xe8, 0x0b, 0x00, 0xc3, 0xbb, 0x1e, 0xdb, 0xe8,
+ 0xb3, 0xaf, 0xe8, 0xc8, 0xaf, 0xc3, 0xbb, 0x1d,
+ 0x46, 0xe8, 0x51, 0x3e, 0xc3, 0x80, 0x3e, 0xa4,
+ 0xdb, 0x01, 0x74, 0x04, 0xe8, 0xef, 0xff, 0xc3,
+ 0xbb, 0x0e, 0x45, 0xe8, 0x3f, 0x3e, 0xc3, 0x80,
+ 0x3e, 0xa4, 0xdb, 0x01, 0x74, 0x04, 0xe8, 0xdd,
+ 0xff, 0xc3, 0xbb, 0xd6, 0x44, 0xe8, 0x2d, 0x3e,
+ 0xc3, 0x80, 0x3e, 0xa4, 0xdb, 0x01, 0x74, 0x04,
+ 0xe8, 0xcb, 0xff, 0xc3, 0xa0, 0xb4, 0xdb, 0x0a,
+ 0xc0, 0x74, 0x20, 0x3c, 0x01, 0x74, 0x07, 0xbb,
+ 0x03, 0x46, 0xe8, 0x10, 0x3e, 0xc3, 0xbb, 0xb8,
+ 0x45, 0xe8, 0x09, 0x3e, 0xe8, 0x06, 0xbd, 0xbb,
+ 0xda, 0x45, 0xe8, 0x00, 0x3e, 0xc6, 0x06, 0xb4,
+ 0xdb, 0x02, 0xc3, 0xbb, 0x32, 0x45, 0xe8, 0xf4,
+ 0x3d, 0x8b, 0x36, 0xaf, 0x64, 0x8b, 0x3e, 0xb1,
+ 0x64, 0x83, 0xee, 0x1e, 0xc6, 0x06, 0xc3, 0x64,
+ 0x01, 0xe8, 0xb7, 0xd3, 0xbb, 0x55, 0x45, 0xe8,
+ 0xdb, 0x3d, 0xbb, 0x68, 0x45, 0xe8, 0x28, 0x00,
+ 0xbb, 0x7b, 0x45, 0xe8, 0x22, 0x00, 0xbb, 0x8e,
+ 0x45, 0xe8, 0x1c, 0x00, 0x8b, 0x36, 0xaf, 0x64,
+ 0x8b, 0x3e, 0xb1, 0x64, 0xc6, 0x06, 0xc3, 0x64,
+ 0x03, 0xe8, 0x8f, 0xd3, 0xbb, 0x9f, 0x45, 0xe8,
+ 0xb3, 0x3d, 0xc6, 0x06, 0xb4, 0xdb, 0x01, 0xc3,
+ 0x53, 0x8b, 0x36, 0xaf, 0x64, 0x8b, 0x3e, 0xb1,
+ 0x64, 0x83, 0xc6, 0x14, 0xc6, 0x06, 0xc3, 0x64,
+ 0x01, 0xe8, 0x6f, 0xd3, 0x5b, 0xe8, 0x95, 0x3d,
+ 0xc3, 0x80, 0x3e, 0xa4, 0xdb, 0x01, 0x74, 0x04,
+ 0xe8, 0x33, 0xff, 0xc3, 0xe8, 0x69, 0x3d, 0xc3,
+ 0xe8, 0x84, 0xb8, 0xb9, 0x1a, 0x00, 0xb0, 0x06,
+ 0xb4, 0x09, 0xe8, 0x20, 0x47, 0xb0, 0x0a, 0xe8,
+ 0x24, 0x47, 0xb9, 0x18, 0x00, 0xb0, 0x0d, 0xe8,
+ 0x23, 0x47, 0xb9, 0x2e, 0x00, 0xb0, 0x25, 0xe8,
+ 0x22, 0x47, 0xe8, 0xf3, 0xdc, 0xc6, 0x07, 0x00,
+ 0x53, 0xe8, 0x34, 0x4b, 0xc6, 0x06, 0x35, 0x33,
+ 0x10, 0xc6, 0x06, 0x36, 0x33, 0x18, 0xb8, 0x3c,
+ 0x46, 0xa3, 0x37, 0x33, 0xb8, 0xda, 0x78, 0xa3,
+ 0x39, 0x33, 0xc6, 0x06, 0xdc, 0x64, 0x00, 0xb9,
+ 0x52, 0x02, 0xe8, 0x52, 0xb8, 0xc6, 0x06, 0xdc,
+ 0x64, 0x01, 0x5b, 0xc6, 0x07, 0x1d, 0xe8, 0x07,
+ 0x4b, 0xb9, 0x05, 0x00, 0xb0, 0x02, 0xb4, 0x0a,
+ 0xe8, 0xca, 0x46, 0xb9, 0x53, 0x02, 0xe8, 0xec,
+ 0xb7, 0xb0, 0x01, 0xe8, 0xa7, 0xb6, 0xb0, 0x24,
+ 0xe8, 0xf5, 0xc3, 0xbb, 0x90, 0x37, 0xe8, 0x0c,
+ 0x3d, 0xc3, 0xbb, 0x5e, 0x46, 0xe8, 0x05, 0x3d,
+ 0xc3, 0x80, 0x3e, 0xac, 0xdb, 0x01, 0x74, 0x07,
+ 0xbb, 0xd2, 0x3b, 0xe8, 0xf7, 0x3c, 0xc3, 0xb9,
+ 0x08, 0x00, 0xe8, 0xe6, 0x4d, 0xc7, 0x06, 0xf3,
+ 0xb4, 0x1a, 0x00, 0xb8, 0x3f, 0x01, 0xbb, 0xa9,
+ 0x00, 0xbf, 0x14, 0x01, 0xbe, 0xa9, 0x00, 0xb1,
+ 0x01, 0xb5, 0x04, 0xe8, 0x65, 0x48, 0xc3, 0xc7,
+ 0x06, 0xf3, 0xb4, 0x15, 0x00, 0xb8, 0xce, 0x00,
+ 0xbb, 0xc7, 0x00, 0xbf, 0xc4, 0x00, 0xbe, 0xc2,
+ 0x00, 0xb1, 0x13, 0xb5, 0x01, 0xe8, 0x4b, 0x48,
+ 0xc3, 0xbb, 0xf7, 0x46, 0xe8, 0xb6, 0x3c, 0xc3,
+ 0xbb, 0x3d, 0x47, 0xe8, 0xaf, 0x3c, 0xc3, 0xbb,
+ 0x3d, 0x47, 0xe8, 0xa8, 0x3c, 0xc3, 0xbb, 0x7b,
+ 0x47, 0xe8, 0xa1, 0x3c, 0xc3, 0xbb, 0x98, 0x47,
+ 0xe8, 0x9a, 0x3c, 0xc3, 0xb9, 0x06, 0x00, 0xe8,
+ 0x89, 0x4d, 0xc7, 0x06, 0xf3, 0xb4, 0x19, 0x00,
+ 0xb8, 0x97, 0x00, 0xbb, 0x9c, 0x00, 0xbf, 0xea,
+ 0x00, 0xbe, 0x98, 0x00, 0xb1, 0x01, 0xb5, 0x02,
+ 0xe8, 0x08, 0x48, 0xc3, 0xbb, 0x75, 0x33, 0xe8,
+ 0xe3, 0xad, 0xc3, 0xbb, 0xbf, 0x47, 0xe8, 0x6c,
+ 0x3c, 0xc3, 0xb9, 0x05, 0x00, 0xb0, 0x0a, 0xb4,
+ 0x0c, 0xe8, 0x09, 0x46, 0xe8, 0x60, 0xb7, 0xe8,
+ 0xee, 0xdb, 0xc6, 0x07, 0x00, 0xe8, 0x74, 0x4a,
+ 0xb9, 0x80, 0x02, 0xe8, 0x11, 0xb7, 0xb0, 0x32,
+ 0xe8, 0x2d, 0xc3, 0xb0, 0x06, 0xe8, 0xd5, 0xb5,
+ 0xc3, 0x80, 0x3e, 0x93, 0xdb, 0x01, 0x75, 0x07,
+ 0xbb, 0x08, 0x3e, 0xe8, 0x37, 0x3c, 0xc3, 0xc6,
+ 0x06, 0x93, 0xdb, 0x01, 0xbb, 0xc6, 0x3d, 0xe8,
+ 0x2b, 0x3c, 0xb9, 0x1e, 0x00, 0xb0, 0x1a, 0xb4,
+ 0x0a, 0xe8, 0xc9, 0x45, 0xb9, 0x1d, 0x00, 0xb0,
+ 0x31, 0xb4, 0x0f, 0xe8, 0xc8, 0x45, 0xe8, 0x16,
+ 0xb7, 0xb4, 0x01, 0xb0, 0x57, 0xe8, 0x9f, 0xba,
+ 0xbb, 0x47, 0x33, 0xc7, 0x07, 0xf5, 0x01, 0xb9,
+ 0xf4, 0x01, 0xe8, 0x9d, 0xb6, 0xe8, 0x90, 0xdb,
+ 0xb0, 0x01, 0x88, 0x07, 0xe8, 0xc2, 0x4a, 0xb0,
+ 0x0e, 0xe8, 0x75, 0xb5, 0xe8, 0xc5, 0xb6, 0xbb,
+ 0xf4, 0x3d, 0xe8, 0xe8, 0x3b, 0xc3, 0xbb, 0xc1,
+ 0x32, 0xe8, 0x51, 0xad, 0xc3, 0xe8, 0xf6, 0xff,
+ 0xc3, 0xbb, 0x5e, 0x32, 0xe8, 0x46, 0xad, 0xc3,
+ 0x80, 0x3e, 0x96, 0xdb, 0x01, 0x74, 0x07, 0xbb,
+ 0xb2, 0x3e, 0xe8, 0xc8, 0x3b, 0xc3, 0xb9, 0x38,
+ 0x00, 0xb0, 0x07, 0xb4, 0x09, 0xe8, 0x65, 0x45,
+ 0xb9, 0x05, 0x00, 0xb0, 0x0f, 0xe8, 0x66, 0x45,
+ 0xb9, 0x65, 0x02, 0xe8, 0x49, 0xb6, 0xe8, 0x3f,
+ 0xdb, 0xc6, 0x47, 0x03, 0x24, 0xe8, 0x80, 0x49,
+ 0xe8, 0x79, 0xb6, 0xb0, 0x27, 0xe8, 0x80, 0xc2,
+ 0xb0, 0x05, 0xe8, 0x28, 0xb5, 0xbb, 0x7c, 0x38,
+ 0xe8, 0x92, 0x3b, 0xc3, 0x80, 0x3e, 0x96, 0xdb,
+ 0x01, 0x74, 0x07, 0xbb, 0xb2, 0x3e, 0xe8, 0x84,
+ 0x3b, 0xc3, 0xe8, 0x82, 0xb6, 0x83, 0x06, 0xaf,
+ 0x64, 0x04, 0xe8, 0x0b, 0xdb, 0xc6, 0x47, 0x02,
+ 0x23, 0xe8, 0x90, 0x49, 0xb9, 0x3f, 0x00, 0xb0,
+ 0x08, 0xb4, 0x09, 0xe8, 0x0f, 0x45, 0xb9, 0x18,
+ 0x00, 0xb0, 0x0a, 0xe8, 0x10, 0x45, 0xb9, 0x64,
+ 0x02, 0xe8, 0x1b, 0xb6, 0xb0, 0x28, 0xe8, 0x37,
+ 0xc2, 0xb0, 0x06, 0xe8, 0xdf, 0xb4, 0xc3, 0x80,
+ 0x3e, 0x96, 0xdb, 0x01, 0x74, 0x07, 0xbb, 0xe7,
+ 0x47, 0xe8, 0x41, 0x3b, 0xc3, 0xe8, 0xbe, 0x3f,
+ 0xc3, 0xe8, 0x3b, 0xb6, 0xe8, 0xc9, 0xda, 0xc6,
+ 0x47, 0x04, 0x00, 0xe8, 0x4e, 0x49, 0xb9, 0x05,
+ 0x00, 0xb0, 0x0b, 0xb4, 0x05, 0xe8, 0xcd, 0x44,
+ 0xb9, 0x71, 0x02, 0xe8, 0xef, 0xb5, 0xb0, 0x2c,
+ 0xe8, 0xfd, 0xc1, 0xb0, 0x08, 0xe8, 0xa5, 0xb4,
+ 0xc3, 0xc7, 0x06, 0xf3, 0xb4, 0x14, 0x00, 0xb8,
+ 0x05, 0x00, 0xbb, 0x83, 0x00, 0xbf, 0x0e, 0x00,
+ 0xbe, 0xb9, 0x00, 0xb1, 0x0b, 0xb5, 0x03, 0xe8,
+ 0x89, 0x46, 0xc3, 0x80, 0x3e, 0x9d, 0xdb, 0x01,
+ 0x75, 0x07, 0xbb, 0x6a, 0x35, 0xe8, 0xed, 0x3a,
+ 0xc3, 0xc6, 0x06, 0x9d, 0xdb, 0x01, 0xb0, 0x11,
+ 0xe8, 0xc5, 0xc1, 0xb9, 0x31, 0x00, 0xb0, 0x03,
+ 0xb4, 0x05, 0xe8, 0x80, 0x44, 0xb9, 0x05, 0x00,
+ 0xb0, 0x1a, 0xe8, 0x81, 0x44, 0xb9, 0x24, 0x02,
+ 0xe8, 0x93, 0xb5, 0xbb, 0xb2, 0x35, 0xe8, 0xc4,
+ 0x3a, 0xc3, 0xe8, 0xc2, 0xb5, 0xb9, 0x12, 0x00,
+ 0xb0, 0x0a, 0xb4, 0x05, 0xe8, 0x5e, 0x44, 0xe8,
+ 0x46, 0xda, 0xc6, 0x47, 0x01, 0x00, 0xe8, 0xcb,
+ 0x48, 0xb9, 0x29, 0x02, 0xe8, 0x76, 0xb5, 0xb0,
+ 0x15, 0xe8, 0x84, 0xc1, 0xb0, 0x0b, 0xe8, 0x2c,
+ 0xb4, 0xe8, 0x92, 0xb9, 0xbb, 0x05, 0x36, 0xe8,
+ 0x93, 0x3a, 0xc3, 0x80, 0x3e, 0xa9, 0xdb, 0x01,
+ 0x74, 0x07, 0xbb, 0x08, 0x48, 0xe8, 0x85, 0x3a,
+ 0xc3, 0xb9, 0x7b, 0x02, 0xe8, 0x28, 0xb5, 0xe8,
+ 0x0e, 0xda, 0xc6, 0x47, 0x05, 0x00, 0xe8, 0x4f,
+ 0x48, 0xb9, 0x3f, 0x00, 0xb0, 0x0b, 0xb4, 0x06,
+ 0xe8, 0x12, 0x44, 0xb9, 0x0f, 0x00, 0xb0, 0x14,
+ 0xe8, 0x13, 0x44, 0xb9, 0x20, 0x00, 0xb0, 0x1f,
+ 0xb4, 0x09, 0xe8, 0x10, 0x44, 0xb9, 0x7c, 0x02,
+ 0xe8, 0xff, 0xb4, 0xff, 0x0e, 0xaf, 0x64, 0xc7,
+ 0x06, 0xb1, 0x64, 0x8b, 0x00, 0xc6, 0x06, 0xcc,
+ 0x64, 0x01, 0xc6, 0x06, 0xdc, 0x64, 0x00, 0xe8,
+ 0x12, 0xb5, 0xb0, 0x30, 0xe8, 0x19, 0xc1, 0xb0,
+ 0x2f, 0xe8, 0x14, 0xc1, 0xbb, 0x83, 0x3b, 0xe8,
+ 0x2b, 0x3a, 0xc6, 0x06, 0xa9, 0xdb, 0x02, 0xc6,
+ 0x06, 0xa8, 0xdb, 0x00, 0xc3, 0xbb, 0x28, 0x48,
+ 0xe8, 0x1a, 0x3a, 0xc3, 0xe8, 0x18, 0xb5, 0xe8,
+ 0xa6, 0xd9, 0xc6, 0x07, 0x00, 0xe8, 0x2c, 0x48,
+ 0xb9, 0x05, 0x00, 0xb0, 0x09, 0xb4, 0x0b, 0xe8,
+ 0xab, 0x43, 0xb9, 0xff, 0x01, 0xe8, 0xbf, 0xb4,
+ 0xb0, 0x01, 0xe8, 0xdb, 0xc0, 0xb0, 0x0e, 0xe8,
+ 0x83, 0xb3, 0xc3, 0xbb, 0x28, 0x48, 0xe8, 0xec,
+ 0x39, 0xc3, 0xbb, 0x60, 0x48, 0xe8, 0xe5, 0x39,
+ 0xc3, 0xbb, 0x3f, 0x5b, 0xe8, 0xde, 0x39, 0xc3,
+ 0xe8, 0x5b, 0x3e, 0xc3, 0xb9, 0x46, 0x00, 0xb0,
+ 0x04, 0xb4, 0x0c, 0xe8, 0x77, 0x43, 0xb9, 0xcc,
+ 0x03, 0xe8, 0x63, 0xb4, 0xe8, 0x04, 0x45, 0xc7,
+ 0x06, 0xf3, 0xb4, 0x1d, 0x00, 0xb8, 0xa0, 0x00,
+ 0xbb, 0xc7, 0x00, 0xbf, 0xa0, 0x00, 0xbe, 0xbc,
+ 0x00, 0xb1, 0x13, 0xb5, 0x01, 0xe8, 0x3b, 0x45,
+ 0xc3, 0xbb, 0x7e, 0x4a, 0xe8, 0xa6, 0x39, 0xb0,
+ 0x04, 0xe8, 0x31, 0xb3, 0xc3, 0xb9, 0x59, 0x00,
+ 0xb0, 0x05, 0xb4, 0x0b, 0xe8, 0x3e, 0x43, 0xb9,
+ 0xc9, 0x03, 0xe8, 0x3a, 0xb4, 0xe8, 0xcb, 0x44,
+ 0xc7, 0x06, 0xf3, 0xb4, 0x21, 0x00, 0xb8, 0x3f,
+ 0x01, 0xbb, 0xb5, 0x00, 0xbf, 0x2d, 0x01, 0xbe,
+ 0xb5, 0x00, 0xb1, 0x01, 0xb5, 0x04, 0xe8, 0x02,
+ 0x45, 0xc3, 0xb9, 0x58, 0x00, 0xb0, 0x04, 0xb4,
+ 0x02, 0xe8, 0x11, 0x43, 0xb9, 0xca, 0x03, 0xe8,
+ 0xfd, 0xb3, 0xe8, 0x9e, 0x44, 0xc7, 0x06, 0xf3,
+ 0xb4, 0x23, 0x00, 0xb8, 0xa0, 0x00, 0xbb, 0xc7,
+ 0x00, 0xbf, 0xa0, 0x00, 0xbe, 0xbb, 0x00, 0xb1,
+ 0x13, 0xb5, 0x01, 0xe8, 0xd5, 0x44, 0xc3, 0xbb,
+ 0x51, 0x5b, 0xe8, 0x40, 0x39, 0xc3, 0xbb, 0x0f,
+ 0x57, 0xe8, 0x39, 0x39, 0xc3, 0xbb, 0x46, 0x67,
+ 0xe8, 0xb7, 0xd8, 0x83, 0xc3, 0x03, 0xff, 0x37,
+ 0x53, 0xc7, 0x07, 0x3f, 0x01, 0xbe, 0x99, 0x00,
+ 0xbf, 0xa3, 0x00, 0xc6, 0x06, 0xc3, 0x64, 0x04,
+ 0xe8, 0xf0, 0xce, 0xb9, 0xcd, 0x03, 0xe8, 0xbe,
+ 0xb3, 0xe8, 0x4f, 0x44, 0x5b, 0x8f, 0x07, 0x80,
+ 0x3e, 0xc1, 0xdb, 0x00, 0x75, 0x0a, 0xb8, 0x06,
+ 0x00, 0xe8, 0x0f, 0x4a, 0x40, 0xa2, 0xc1, 0xdb,
+ 0xc7, 0x06, 0xf3, 0xb4, 0x1e, 0x00, 0xb8, 0x12,
+ 0x00, 0xbb, 0x9f, 0x00, 0xbf, 0x31, 0x00, 0xbe,
+ 0xb4, 0x00, 0xb1, 0x01, 0xb5, 0x02, 0xe8, 0x72,
+ 0x44, 0xc3, 0xc7, 0x06, 0xf3, 0xb4, 0x1f, 0x00,
+ 0xb8, 0x00, 0x00, 0xbb, 0xbc, 0x00, 0xbf, 0x28,
+ 0x00, 0xbe, 0xbc, 0x00, 0xb1, 0x01, 0xb5, 0x02,
+ 0xe8, 0x58, 0x44, 0xc3, 0xc7, 0x06, 0xf3, 0xb4,
+ 0x1c, 0x00, 0xb8, 0xd0, 0x00, 0xbb, 0x99, 0x00,
+ 0xbf, 0xaa, 0x00, 0xbe, 0x99, 0x00, 0xb1, 0x01,
+ 0xb5, 0x04, 0xe8, 0x3e, 0x44, 0xc3, 0xc7, 0x06,
+ 0xaf, 0x64, 0x95, 0x00, 0xc7, 0x06, 0xb1, 0x64,
+ 0xa3, 0x00, 0xc6, 0x06, 0xcc, 0x64, 0x01, 0xc6,
+ 0x06, 0xdc, 0x64, 0x00, 0xc6, 0x06, 0xcb, 0x64,
+ 0x00, 0xe8, 0xb5, 0xd6, 0xc7, 0x06, 0xf3, 0xb4,
+ 0x1d, 0x00, 0xc6, 0x06, 0xdc, 0x1c, 0x01, 0xe8,
+ 0x55, 0x44, 0xbb, 0x46, 0x67, 0xe8, 0x02, 0xd8,
+ 0x83, 0xc3, 0x03, 0xff, 0x37, 0x53, 0xc7, 0x07,
+ 0x3f, 0x01, 0xb9, 0xce, 0x03, 0xc6, 0x06, 0xdc,
+ 0x1c, 0x01, 0xe8, 0x23, 0xb3, 0xbe, 0xa0, 0x00,
+ 0xbf, 0xbc, 0x00, 0xe8, 0x35, 0xce, 0x5b, 0x8f,
+ 0x07, 0xc3, 0xe8, 0xd9, 0x3c, 0xc3, 0xbb, 0xab,
+ 0x5b, 0xe8, 0x51, 0x38, 0xc3, 0xe8, 0x41, 0x00,
+ 0xb9, 0x20, 0x00, 0xb0, 0x0c, 0xb4, 0x09, 0xe8,
+ 0xeb, 0x41, 0xb9, 0xb6, 0x02, 0xe8, 0xf8, 0xb2,
+ 0xb9, 0x0f, 0x00, 0xb0, 0x08, 0xb4, 0x09, 0xe8,
+ 0xdb, 0x41, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0xb5,
+ 0x02, 0xb0, 0x01, 0xe8, 0x3b, 0xb2, 0xe8, 0xb7,
+ 0xd7, 0xc6, 0x47, 0x06, 0x00, 0xe8, 0x3c, 0x46,
+ 0xbb, 0xc7, 0x4c, 0xe8, 0x17, 0x38, 0xb0, 0x36,
+ 0xe8, 0xf5, 0xbe, 0xb0, 0x04, 0xe8, 0x9d, 0xb1,
+ 0xc3, 0xbe, 0xd3, 0x00, 0xbf, 0x97, 0x00, 0x81,
+ 0x3e, 0xaf, 0x64, 0xd0, 0x00, 0x75, 0x1a, 0x81,
+ 0x3e, 0xb1, 0x64, 0x97, 0x00, 0x75, 0x12, 0xc6,
+ 0x06, 0xc3, 0x64, 0x02, 0x57, 0x56, 0xe8, 0xc2,
+ 0xcd, 0xb8, 0x09, 0x00, 0xe8, 0xcb, 0xb6, 0x5e,
+ 0x5f, 0xc6, 0x06, 0xc3, 0x64, 0x01, 0xe8, 0xb2,
+ 0xcd, 0xc3, 0x80, 0x3e, 0xc2, 0xdb, 0x01, 0x75,
+ 0x07, 0xbb, 0xa0, 0x4c, 0xe8, 0xce, 0x37, 0xc3,
+ 0xb9, 0x31, 0x00, 0xb0, 0x05, 0xb4, 0x09, 0xe8,
+ 0x6b, 0x41, 0xb0, 0x11, 0xe8, 0x6f, 0x41, 0xb9,
+ 0xb3, 0x02, 0xe8, 0x73, 0xb2, 0xe8, 0x46, 0x00,
+ 0x73, 0x31, 0xb9, 0x0f, 0x00, 0xb0, 0x08, 0xb4,
+ 0x09, 0xe8, 0x51, 0x41, 0xbb, 0x47, 0x33, 0xc7,
+ 0x07, 0xb4, 0x02, 0xb0, 0x01, 0xe8, 0xb1, 0xb1,
+ 0xe8, 0x2d, 0xd7, 0xc6, 0x47, 0x06, 0x3b, 0xe8,
+ 0xb2, 0x45, 0xb0, 0x04, 0xe8, 0x12, 0xb1, 0xbb,
+ 0x84, 0x4c, 0xe8, 0x88, 0x37, 0xc6, 0x06, 0xc2,
+ 0xdb, 0x01, 0xc3, 0x80, 0x3e, 0xc0, 0xdb, 0x01,
+ 0x74, 0x0b, 0xc6, 0x06, 0xc0, 0xdb, 0x01, 0xbb,
+ 0x61, 0x4c, 0xe8, 0x70, 0x37, 0xc3, 0xa0, 0xc1,
+ 0xdb, 0x98, 0x48, 0xbb, 0xb7, 0xdb, 0x53, 0x03,
+ 0xd8, 0x80, 0x3f, 0x01, 0x5b, 0x75, 0x18, 0x8b,
+ 0x07, 0x8b, 0x4f, 0x02, 0x8b, 0x57, 0x04, 0x02,
+ 0xc4, 0x02, 0xc1, 0x02, 0xc5, 0x02, 0xc2, 0x02,
+ 0xc6, 0x3c, 0x01, 0x75, 0x02, 0xf9, 0xc3, 0xf8,
+ 0xc3, 0xbb, 0xe7, 0x5b, 0xe8, 0x3e, 0x37, 0xc3,
+ 0xb0, 0x37, 0xe8, 0x4f, 0xbe, 0x73, 0x07, 0xbb,
+ 0xd9, 0x4c, 0xe8, 0x30, 0x37, 0xc3, 0x80, 0x3e,
+ 0xc3, 0xdb, 0x01, 0x74, 0x11, 0xc6, 0x06, 0xc3,
+ 0xdb, 0x01, 0xb9, 0xb7, 0x02, 0xe8, 0xe6, 0xb1,
+ 0xbb, 0x6a, 0x38, 0xe8, 0x87, 0xa8, 0xb9, 0x05,
+ 0x00, 0xb0, 0x0b, 0xb4, 0x0a, 0xe8, 0xb5, 0x40,
+ 0xb9, 0xb8, 0x02, 0xe8, 0xd0, 0xb1, 0xb0, 0x37,
+ 0xe8, 0xe5, 0xbd, 0xc3, 0xbb, 0x0b, 0x5c, 0xe8,
+ 0xfb, 0x36, 0xc3, 0xbb, 0x26, 0x5c, 0xe8, 0xf4,
+ 0x36, 0xc3, 0x80, 0x3e, 0xb7, 0xdb, 0x01, 0x74,
+ 0x2d, 0x80, 0x3e, 0xb8, 0xdb, 0x01, 0x75, 0x04,
+ 0xe8, 0x13, 0x02, 0xc3, 0xb9, 0x42, 0x00, 0xb0,
+ 0x04, 0xb4, 0x07, 0xe8, 0x7f, 0x40, 0xb9, 0xa5,
+ 0x02, 0xe8, 0x6b, 0xb1, 0xe8, 0x61, 0xd6, 0xc6,
+ 0x07, 0x35, 0xe8, 0xa3, 0x44, 0xe8, 0x9c, 0xb1,
+ 0xc6, 0x06, 0xb7, 0xdb, 0x01, 0xc3, 0xe8, 0xbe,
+ 0xb1, 0xe8, 0x4c, 0xd6, 0xc6, 0x07, 0x00, 0xe8,
+ 0xd2, 0x44, 0xb9, 0x43, 0x00, 0xb0, 0x04, 0xb4,
+ 0x07, 0xe8, 0x51, 0x40, 0xb9, 0xa6, 0x02, 0xe8,
+ 0x65, 0xb1, 0xc6, 0x06, 0xb7, 0xdb, 0x00, 0xc3,
+ 0x80, 0x3e, 0xb8, 0xdb, 0x01, 0x74, 0x39, 0x80,
+ 0x3e, 0xb7, 0xdb, 0x01, 0x75, 0x04, 0xe8, 0xbd,
+ 0x01, 0xc3, 0x80, 0x3e, 0xb9, 0xdb, 0x01, 0x75,
+ 0x04, 0xe8, 0xb2, 0x01, 0xc3, 0xb9, 0x42, 0x00,
+ 0xb0, 0x05, 0xb4, 0x07, 0xe8, 0x1e, 0x40, 0xb9,
+ 0xa7, 0x02, 0xe8, 0x0a, 0xb1, 0xe8, 0x00, 0xd6,
+ 0xc6, 0x47, 0x01, 0x36, 0xe8, 0x41, 0x44, 0xe8,
+ 0x3a, 0xb1, 0xc6, 0x06, 0xb8, 0xdb, 0x01, 0xc3,
+ 0xe8, 0x5c, 0xb1, 0xe8, 0xea, 0xd5, 0xc6, 0x47,
+ 0x01, 0x00, 0xe8, 0x6f, 0x44, 0xb9, 0x43, 0x00,
+ 0xb0, 0x04, 0xb4, 0x07, 0xe8, 0xee, 0x3f, 0xb9,
+ 0xa8, 0x02, 0xe8, 0x02, 0xb1, 0xc6, 0x06, 0xb8,
+ 0xdb, 0x00, 0xc3, 0x80, 0x3e, 0xb9, 0xdb, 0x01,
+ 0x74, 0x2e, 0x80, 0x3e, 0xb8, 0xdb, 0x01, 0x75,
+ 0x04, 0xe8, 0x5a, 0x01, 0xc3, 0xb9, 0x43, 0x00,
+ 0xb0, 0x05, 0xb4, 0x07, 0xe8, 0xc6, 0x3f, 0xb9,
+ 0xa9, 0x02, 0xe8, 0xb2, 0xb0, 0xe8, 0xa8, 0xd5,
+ 0xc6, 0x47, 0x02, 0x37, 0xe8, 0xe9, 0x43, 0xe8,
+ 0xe2, 0xb0, 0xc6, 0x06, 0xb9, 0xdb, 0x01, 0xc3,
+ 0xe8, 0x04, 0xb1, 0xe8, 0x92, 0xd5, 0xc6, 0x47,
+ 0x02, 0x00, 0xe8, 0x17, 0x44, 0xb9, 0x43, 0x00,
+ 0xb0, 0x05, 0xb4, 0x07, 0xe8, 0x96, 0x3f, 0xb9,
+ 0xaa, 0x02, 0xe8, 0xaa, 0xb0, 0xc6, 0x06, 0xb9,
+ 0xdb, 0x00, 0xc3, 0x80, 0x3e, 0xba, 0xdb, 0x01,
+ 0x74, 0x2e, 0x80, 0x3e, 0xbb, 0xdb, 0x01, 0x75,
+ 0x04, 0xe8, 0x02, 0x01, 0xc3, 0xb9, 0x42, 0x00,
+ 0xb0, 0x04, 0xb4, 0x07, 0xe8, 0x6e, 0x3f, 0xb9,
+ 0xab, 0x02, 0xe8, 0x5a, 0xb0, 0xe8, 0x50, 0xd5,
+ 0xc6, 0x47, 0x03, 0x38, 0xe8, 0x91, 0x43, 0xe8,
+ 0x8a, 0xb0, 0xc6, 0x06, 0xba, 0xdb, 0x01, 0xc3,
+ 0xe8, 0xac, 0xb0, 0xe8, 0x3a, 0xd5, 0xc6, 0x47,
+ 0x03, 0x00, 0xe8, 0xbf, 0x43, 0xb9, 0x43, 0x00,
+ 0xb0, 0x04, 0xb4, 0x07, 0xe8, 0x3e, 0x3f, 0xb9,
+ 0xac, 0x02, 0xe8, 0x52, 0xb0, 0xc6, 0x06, 0xba,
+ 0xdb, 0x00, 0xc3, 0x80, 0x3e, 0xbb, 0xdb, 0x01,
+ 0x74, 0x39, 0x80, 0x3e, 0xba, 0xdb, 0x01, 0x75,
+ 0x04, 0xe8, 0xaa, 0x00, 0xc3, 0x80, 0x3e, 0xbc,
+ 0xdb, 0x01, 0x75, 0x04, 0xe8, 0x9f, 0x00, 0xc3,
+ 0xb9, 0x42, 0x00, 0xb0, 0x05, 0xb4, 0x07, 0xe8,
+ 0x0b, 0x3f, 0xb9, 0xad, 0x02, 0xe8, 0xf7, 0xaf,
+ 0xe8, 0xed, 0xd4, 0xc6, 0x47, 0x04, 0x39, 0xe8,
+ 0x2e, 0x43, 0xe8, 0x27, 0xb0, 0xc6, 0x06, 0xbb,
+ 0xdb, 0x01, 0xc3, 0xe8, 0x49, 0xb0, 0xe8, 0xd7,
+ 0xd4, 0xc6, 0x47, 0x04, 0x00, 0xe8, 0x5c, 0x43,
+ 0xb9, 0x43, 0x00, 0xb0, 0x04, 0xb4, 0x07, 0xe8,
+ 0xdb, 0x3e, 0xb9, 0xae, 0x02, 0xe8, 0xef, 0xaf,
+ 0xc6, 0x06, 0xbb, 0xdb, 0x00, 0xc3, 0x80, 0x3e,
+ 0xbc, 0xdb, 0x01, 0x74, 0x2e, 0x80, 0x3e, 0xbb,
+ 0xdb, 0x01, 0x75, 0x04, 0xe8, 0x47, 0x00, 0xc3,
+ 0xb9, 0x42, 0x00, 0xb0, 0x06, 0xb4, 0x07, 0xe8,
+ 0xb3, 0x3e, 0xb9, 0xaf, 0x02, 0xe8, 0x9f, 0xaf,
+ 0xe8, 0x95, 0xd4, 0xc6, 0x47, 0x05, 0x3a, 0xe8,
+ 0xd6, 0x42, 0xe8, 0xcf, 0xaf, 0xc6, 0x06, 0xbc,
+ 0xdb, 0x01, 0xc3, 0xe8, 0xf1, 0xaf, 0xe8, 0x7f,
+ 0xd4, 0xc6, 0x47, 0x05, 0x00, 0xe8, 0x04, 0x43,
+ 0xb9, 0x43, 0x00, 0xb0, 0x05, 0xb4, 0x07, 0xe8,
+ 0x83, 0x3e, 0xb9, 0xb0, 0x02, 0xe8, 0x97, 0xaf,
+ 0xc6, 0x06, 0xbc, 0xdb, 0x00, 0xc3, 0x80, 0x3e,
+ 0xbd, 0xdb, 0x01, 0x74, 0x12, 0xbb, 0xcd, 0x4a,
+ 0xe8, 0xc2, 0x34, 0xbb, 0x0d, 0x4b, 0xe8, 0xbc,
+ 0x34, 0xc6, 0x06, 0xbd, 0xdb, 0x01, 0xc3, 0xbb,
+ 0x39, 0x4b, 0xe8, 0xb0, 0x34, 0xc3, 0xbb, 0x46,
+ 0x5c, 0xe8, 0xa9, 0x34, 0xc3, 0xb9, 0x50, 0x00,
+ 0xb0, 0x04, 0xb4, 0x0a, 0xe8, 0x46, 0x3e, 0xb9,
+ 0xcb, 0x03, 0xe8, 0x32, 0xaf, 0xe8, 0xd3, 0x3f,
+ 0xc7, 0x06, 0xf3, 0xb4, 0x20, 0x00, 0xb8, 0x8b,
+ 0x00, 0xbb, 0xc7, 0x00, 0xbf, 0x8b, 0x00, 0xbe,
+ 0xbc, 0x00, 0xb1, 0x13, 0xb5, 0x01, 0xe8, 0x0a,
+ 0x40, 0xc3, 0xbb, 0x65, 0x5b, 0xe8, 0x75, 0x34,
+ 0xc3, 0x80, 0x3e, 0xd9, 0xdb, 0x01, 0x75, 0x07,
+ 0xbb, 0x26, 0x53, 0xe8, 0x67, 0x34, 0xc3, 0xb9,
+ 0x58, 0x00, 0xb0, 0x04, 0xb4, 0x0e, 0xe8, 0x04,
+ 0x3e, 0xb9, 0x28, 0x03, 0xe8, 0xf0, 0xae, 0xe8,
+ 0x91, 0x3f, 0xc7, 0x06, 0xf3, 0xb4, 0x24, 0x00,
+ 0xb8, 0x29, 0x00, 0xbb, 0xc3, 0x00, 0xbf, 0x32,
+ 0x00, 0xbe, 0xc3, 0x00, 0xb1, 0x01, 0xb5, 0x02,
+ 0xe8, 0xc8, 0x3f, 0xc3, 0xe8, 0xb7, 0x38, 0xc3,
+ 0xe8, 0xb3, 0x38, 0xc3, 0xbb, 0x51, 0x5b, 0xe8,
+ 0x2b, 0x34, 0xc3, 0xc7, 0x06, 0xf3, 0xb4, 0x1d,
+ 0x00, 0xb8, 0x3f, 0x01, 0xbb, 0xbc, 0x00, 0xbf,
+ 0x18, 0x01, 0xbe, 0xbc, 0x00, 0xb1, 0x01, 0xb5,
+ 0x04, 0xe8, 0x9f, 0x3f, 0xc3, 0xb9, 0x59, 0x00,
+ 0xb0, 0x06, 0xb4, 0x0c, 0xe8, 0xae, 0x3d, 0xb9,
+ 0x26, 0x03, 0x80, 0x3e, 0xef, 0xdb, 0x01, 0x75,
+ 0x03, 0xb9, 0xd9, 0x03, 0xe8, 0x90, 0xae, 0xe8,
+ 0x31, 0x3f, 0xc7, 0x06, 0xf3, 0xb4, 0x22, 0x00,
+ 0xb8, 0x28, 0x00, 0xbb, 0x85, 0x00, 0xbf, 0x34,
+ 0x00, 0xbe, 0x85, 0x00, 0xb1, 0x01, 0xb5, 0x02,
+ 0xe8, 0x68, 0x3f, 0xc3, 0xbb, 0x80, 0x5b, 0xe8,
+ 0xd3, 0x33, 0xc3, 0xe8, 0xbb, 0xac, 0xbb, 0x2e,
+ 0xdb, 0xe8, 0x21, 0xa5, 0xe8, 0x36, 0xa5, 0xb0,
+ 0x01, 0xbe, 0x94, 0xaa, 0xe8, 0x5a, 0xad, 0xc6,
+ 0x06, 0xd1, 0xdb, 0x01, 0xc3, 0xe8, 0xb7, 0xae,
+ 0xe8, 0x45, 0xd3, 0xc6, 0x07, 0x47, 0xe8, 0xcb,
+ 0x41, 0xb9, 0x20, 0x00, 0xb0, 0x05, 0xb4, 0x04,
+ 0xe8, 0x4a, 0x3d, 0xb9, 0xdc, 0x02, 0xe8, 0x5e,
+ 0xae, 0xb0, 0x02, 0xe8, 0x27, 0xad, 0xb0, 0x48,
+ 0xe8, 0x75, 0xba, 0xc3, 0xb9, 0xf2, 0x02, 0xe8,
+ 0x25, 0xae, 0xe8, 0xc6, 0x3e, 0xbe, 0xde, 0x76,
+ 0xbb, 0x7b, 0x51, 0x06, 0x53, 0x56, 0xb8, 0x00,
+ 0xa0, 0x8e, 0xc0, 0xe8, 0x67, 0x2f, 0xb8, 0x00,
+ 0xa0, 0xb9, 0x00, 0x7d, 0xe8, 0x19, 0x40, 0x5e,
+ 0x5b, 0xe8, 0x69, 0x37, 0xe8, 0x65, 0x2f, 0xb8,
+ 0x0e, 0x01, 0xe8, 0x67, 0xb2, 0xe8, 0x4d, 0x2f,
+ 0xa1, 0xb3, 0x32, 0x8e, 0xc0, 0xbf, 0x00, 0xfa,
+ 0xb9, 0x80, 0x01, 0x33, 0xc0, 0xfc, 0xf3, 0xab,
+ 0x07, 0xb9, 0x03, 0x00, 0xe8, 0x3c, 0x44, 0xc7,
+ 0x06, 0xf3, 0xb4, 0x0b, 0x00, 0xe8, 0xf4, 0x3f,
+ 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x02, 0xee, 0x02,
+ 0xb0, 0x02, 0xe8, 0x3d, 0xad, 0xc6, 0x06, 0x45,
+ 0x33, 0xe5, 0xc6, 0x06, 0x46, 0x33, 0xd9, 0xb0,
+ 0x02, 0xb4, 0x01, 0xbe, 0xef, 0x02, 0xbf, 0x11,
+ 0x02, 0xbb, 0x50, 0x4f, 0xe8, 0x2f, 0xa7, 0xbb,
+ 0x47, 0x33, 0xc7, 0x07, 0xf0, 0x02, 0xc7, 0x47,
+ 0x02, 0xf1, 0x02, 0xb0, 0x01, 0xe8, 0x12, 0xad,
+ 0xc6, 0x06, 0x45, 0x33, 0xd9, 0xc6, 0x06, 0x46,
+ 0x33, 0xe5, 0xb0, 0x01, 0xb4, 0x02, 0xbe, 0x11,
+ 0x02, 0xbf, 0xef, 0x02, 0xbb, 0x68, 0x51, 0xe8,
+ 0x04, 0xa7, 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x02,
+ 0xdd, 0x02, 0xc7, 0x47, 0x04, 0xde, 0x02, 0xc7,
+ 0x06, 0xf3, 0xb4, 0x1e, 0x00, 0xe8, 0x8c, 0x3f,
+ 0xc6, 0x06, 0x45, 0x33, 0xe5, 0xc6, 0x06, 0x46,
+ 0x33, 0xd0, 0xb0, 0x02, 0xb4, 0x03, 0xbe, 0xdd,
+ 0x02, 0xbf, 0xde, 0x02, 0xbb, 0x9e, 0x44, 0xe8,
+ 0xd4, 0xa6, 0xb9, 0x4b, 0x00, 0xb0, 0x0d, 0xb4,
+ 0x04, 0xe8, 0x59, 0x3c, 0xb9, 0x20, 0x00, 0xb0,
+ 0x16, 0xe8, 0x5a, 0x3c, 0xbb, 0x47, 0x33, 0xc7,
+ 0x47, 0x02, 0xdf, 0x02, 0xc7, 0x47, 0x04, 0xe0,
+ 0x02, 0xb0, 0x02, 0xe8, 0xa4, 0xac, 0xc6, 0x06,
+ 0x46, 0x33, 0xe5, 0xc6, 0x06, 0x45, 0x33, 0xd0,
+ 0xb0, 0x03, 0xb4, 0x02, 0xbe, 0xe1, 0x02, 0xbf,
+ 0xe2, 0x02, 0xbb, 0xcf, 0x46, 0xe8, 0x96, 0xa6,
+ 0xb9, 0x20, 0x00, 0xb0, 0x01, 0xb4, 0x04, 0xe8,
+ 0x1b, 0x3c, 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x02,
+ 0xe3, 0x02, 0xc7, 0x47, 0x04, 0xe4, 0x02, 0xb0,
+ 0x02, 0xe8, 0x6e, 0xac, 0xc6, 0x06, 0x45, 0x33,
+ 0xe5, 0xc6, 0x06, 0x46, 0x33, 0xd0, 0xb0, 0x02,
+ 0xb4, 0x03, 0xbe, 0xdd, 0x02, 0xbf, 0xde, 0x02,
+ 0xbb, 0x72, 0x47, 0xe8, 0x60, 0xa6, 0xbb, 0x47,
+ 0x33, 0xc7, 0x47, 0x02, 0xe6, 0x02, 0xc7, 0x47,
+ 0x04, 0xe5, 0x02, 0xb0, 0x02, 0xe8, 0x42, 0xac,
+ 0xc6, 0x06, 0x46, 0x33, 0xe5, 0xc6, 0x06, 0x45,
+ 0x33, 0xd0, 0xb0, 0x03, 0xb4, 0x02, 0xbe, 0xe7,
+ 0x02, 0xbf, 0xdd, 0x02, 0xbb, 0x1c, 0x48, 0xe8,
+ 0x34, 0xa6, 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x02,
+ 0xe8, 0x02, 0xc7, 0x47, 0x04, 0xe9, 0x02, 0xb0,
+ 0x02, 0xe8, 0x16, 0xac, 0xb0, 0x03, 0xb4, 0x02,
+ 0xbe, 0xde, 0x02, 0xbf, 0xdd, 0x02, 0xbb, 0x73,
+ 0x48, 0xe8, 0x12, 0xa6, 0xbb, 0x47, 0x33, 0xc7,
+ 0x47, 0x02, 0xea, 0x02, 0xc7, 0x47, 0x04, 0xeb,
+ 0x02, 0xb0, 0x02, 0xe8, 0xf4, 0xab, 0xe8, 0x2d,
+ 0x3c, 0xb0, 0x03, 0xbe, 0xde, 0x02, 0xbb, 0xa5,
+ 0x4d, 0xe8, 0x7b, 0xa7, 0xb0, 0x03, 0xbe, 0xec,
+ 0x02, 0xbb, 0xb9, 0x4e, 0xe8, 0x70, 0xa7, 0xb0,
+ 0x03, 0xbe, 0xed, 0x02, 0xbb, 0x15, 0x4f, 0xe8,
+ 0x65, 0xa7, 0xb0, 0x03, 0xbe, 0xec, 0x02, 0xbb,
+ 0x2f, 0x4f, 0xe8, 0x5a, 0xa7, 0xb9, 0x0a, 0x00,
+ 0xe8, 0xa8, 0x42, 0xc7, 0x06, 0xf3, 0xb4, 0x20,
+ 0x00, 0xe8, 0x60, 0x3e, 0xb9, 0x1a, 0x00, 0xb0,
+ 0x0a, 0xb4, 0x04, 0xe8, 0x47, 0x3b, 0xb9, 0xf3,
+ 0x02, 0xe8, 0x5b, 0xac, 0x8b, 0x36, 0xaf, 0x64,
+ 0x8b, 0x3e, 0xb1, 0x64, 0xc6, 0x06, 0xc3, 0x64,
+ 0x03, 0xe8, 0x5f, 0xc7, 0xbb, 0xbf, 0x51, 0xe8,
+ 0xf3, 0xa2, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0xfb,
+ 0x02, 0xc7, 0x47, 0x02, 0xfc, 0x02, 0xc7, 0x06,
+ 0xf3, 0xb4, 0x1f, 0x00, 0xe8, 0x25, 0x3e, 0xc6,
+ 0x06, 0x45, 0x33, 0xd9, 0xc6, 0x06, 0x46, 0x33,
+ 0xd0, 0xb0, 0x01, 0xb4, 0x02, 0xbe, 0xfb, 0x02,
+ 0xbf, 0xfc, 0x02, 0xbb, 0x9f, 0x53, 0xe8, 0x6d,
+ 0xa5, 0xc7, 0x06, 0xf3, 0xb4, 0x20, 0x00, 0xe8,
+ 0x1d, 0x3d, 0xbb, 0xc3, 0x52, 0xe8, 0xb5, 0xa2,
+ 0xb0, 0x03, 0xe8, 0xd0, 0xaa, 0xb0, 0x07, 0xe8,
+ 0xbf, 0xaa, 0xc6, 0x06, 0xd5, 0xdb, 0x01, 0xc3,
+ 0x80, 0x3e, 0xd5, 0xdb, 0x01, 0x75, 0x07, 0xbb,
+ 0xa7, 0x51, 0xe8, 0x28, 0x31, 0xc3, 0xe8, 0xa5,
+ 0x35, 0xc3, 0x80, 0x3e, 0xd5, 0xdb, 0x01, 0x75,
+ 0x07, 0xbb, 0xa7, 0x51, 0xe8, 0x16, 0x31, 0xc3,
+ 0xb9, 0xd1, 0x03, 0xe8, 0xca, 0xab, 0xbb, 0x11,
+ 0x55, 0xe8, 0x09, 0x31, 0xc3, 0x80, 0x3e, 0xd5,
+ 0xdb, 0x01, 0x75, 0x07, 0xbb, 0xbb, 0x51, 0xe8,
+ 0xfb, 0x30, 0xc3, 0xc7, 0x06, 0xf3, 0xb4, 0x1f,
+ 0x00, 0xb8, 0x8b, 0x00, 0xbb, 0xac, 0x00, 0xbf,
+ 0x8b, 0x00, 0xbe, 0xb5, 0x00, 0xb1, 0x0b, 0xb5,
+ 0x03, 0xe8, 0x6f, 0x3c, 0xc3, 0xe8, 0xdf, 0xab,
+ 0x8b, 0x36, 0xaf, 0x64, 0x8b, 0x3e, 0xb1, 0x64,
+ 0xc6, 0x06, 0xc3, 0x64, 0x03, 0xe8, 0xa3, 0xc6,
+ 0xb9, 0xf4, 0x02, 0xe8, 0x64, 0xab, 0xe8, 0x02,
+ 0x3c, 0xc6, 0x06, 0xdc, 0x1c, 0x01, 0xbb, 0x47,
+ 0x33, 0xc7, 0x47, 0x02, 0xf6, 0x02, 0xb0, 0x02,
+ 0xe8, 0xbf, 0xaa, 0xc6, 0x06, 0x45, 0x33, 0xd0,
+ 0xb0, 0x02, 0xbe, 0xf7, 0x02, 0xbb, 0xe6, 0x52,
+ 0xe8, 0x44, 0xa6, 0xb9, 0x28, 0x00, 0xb0, 0x05,
+ 0xb4, 0x04, 0xe8, 0x40, 0x3a, 0xb9, 0x34, 0x00,
+ 0xb0, 0x0d, 0xe8, 0x41, 0x3a, 0xb0, 0x11, 0xe8,
+ 0x43, 0x3a, 0xb0, 0x15, 0xe8, 0x45, 0x3a, 0xbb,
+ 0x47, 0x33, 0xc7, 0x47, 0x02, 0xf8, 0x02, 0xb0,
+ 0x02, 0xe8, 0x86, 0xaa, 0xe8, 0x0d, 0x3b, 0xe8,
+ 0x06, 0xd0, 0xc6, 0x47, 0x01, 0x48, 0xc6, 0x47,
+ 0x02, 0x49, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0xfd,
+ 0x02, 0xc7, 0x06, 0xf3, 0xb4, 0x1f, 0x00, 0xe8,
+ 0x12, 0x3d, 0xb9, 0x3a, 0x00, 0xb0, 0x05, 0xb4,
+ 0x07, 0xe8, 0xf9, 0x39, 0xb0, 0x08, 0xe8, 0xfd,
+ 0x39, 0xb0, 0x0a, 0xe8, 0xff, 0x39, 0xb0, 0x0c,
+ 0xe8, 0x01, 0x3a, 0xb0, 0x0e, 0xe8, 0x03, 0x3a,
+ 0xb0, 0x01, 0xe8, 0x45, 0xaa, 0xc6, 0x06, 0x45,
+ 0x33, 0xd9, 0xb0, 0x01, 0xbe, 0xfe, 0x02, 0xbb,
+ 0x43, 0x54, 0xe8, 0xca, 0xa5, 0xbb, 0x47, 0x33,
+ 0xc7, 0x47, 0x02, 0xf9, 0x02, 0xc7, 0x06, 0xf3,
+ 0xb4, 0x20, 0x00, 0xe8, 0xce, 0x3c, 0xc6, 0x06,
+ 0x45, 0x33, 0xd0, 0xb0, 0x02, 0xbe, 0xf9, 0x02,
+ 0xbb, 0x58, 0x53, 0xe8, 0xa9, 0xa5, 0xbb, 0x47,
+ 0x33, 0xc7, 0x47, 0x02, 0xfa, 0x02, 0xb0, 0x02,
+ 0xe8, 0x07, 0xaa, 0xe8, 0x40, 0x3a, 0xe8, 0x87,
+ 0xcf, 0xc6, 0x47, 0x02, 0x00, 0xe8, 0xa5, 0x3d,
+ 0xb9, 0xf5, 0x02, 0xe8, 0x84, 0xaa, 0xc6, 0x06,
+ 0xcd, 0x64, 0x01, 0xc6, 0x06, 0xcc, 0x64, 0x01,
+ 0xc6, 0x06, 0xcb, 0x64, 0x01, 0xe8, 0xac, 0xaa,
+ 0xbb, 0xe7, 0x51, 0xe8, 0xcf, 0x2f, 0xb0, 0x08,
+ 0xe8, 0x4e, 0xa9, 0xb0, 0x07, 0xe8, 0x55, 0xa9,
+ 0xc6, 0x06, 0xd5, 0xdb, 0x00, 0xc3, 0xb9, 0x20,
+ 0x00, 0xb0, 0x05, 0xb4, 0x08, 0xe8, 0x5d, 0x39,
+ 0xb9, 0xff, 0x02, 0xe8, 0x6a, 0xaa, 0xe8, 0x3f,
+ 0xcf, 0xc6, 0x47, 0x01, 0x00, 0xe8, 0xc4, 0x3d,
+ 0xb0, 0x49, 0xe8, 0x83, 0xb6, 0xb0, 0x08, 0xe8,
+ 0x2b, 0xa9, 0xc3, 0xe8, 0x60, 0xa8, 0xbb, 0x24,
+ 0xdb, 0xe8, 0xe9, 0xa0, 0xe8, 0xfe, 0xa0, 0xc3,
+ 0xe8, 0x15, 0x00, 0xbe, 0x51, 0x00, 0xbf, 0xa0,
+ 0x00, 0xc6, 0x06, 0xc3, 0x64, 0x04, 0xe8, 0x52,
+ 0xc5, 0xbb, 0xac, 0x5c, 0xe8, 0x76, 0x2f, 0xc3,
+ 0x80, 0x3e, 0xcc, 0xdb, 0x01, 0x74, 0x07, 0xbb,
+ 0xce, 0x4e, 0xe8, 0x68, 0x2f, 0x58, 0xc3, 0xe8,
+ 0xee, 0xff, 0xbb, 0x46, 0x50, 0xe8, 0x5d, 0x2f,
+ 0xc3, 0xb0, 0x44, 0xe8, 0x6e, 0xb6, 0x73, 0x12,
+ 0xb0, 0x44, 0xe8, 0x43, 0xb6, 0xe8, 0x0a, 0x00,
+ 0xe8, 0x23, 0xc5, 0xbb, 0x0a, 0x50, 0xe8, 0x44,
+ 0x2f, 0xc3, 0xc7, 0x06, 0xf3, 0xb4, 0x1d, 0x00,
+ 0xb8, 0x28, 0x00, 0xbb, 0xb0, 0x00, 0xbf, 0x3e,
+ 0x00, 0xbe, 0xb7, 0x00, 0xb1, 0x01, 0xb5, 0x02,
+ 0xe8, 0xb8, 0x3a, 0xc3, 0xe8, 0xb1, 0xff, 0x80,
+ 0x3e, 0xcf, 0xdb, 0x01, 0x74, 0x48, 0xe8, 0x1e,
+ 0xaa, 0xc6, 0x06, 0xe6, 0x1c, 0xe5, 0xc6, 0x06,
+ 0x35, 0x33, 0x0b, 0xc6, 0x06, 0x36, 0x33, 0x23,
+ 0xb8, 0xcb, 0x4f, 0xa3, 0x37, 0x33, 0xb8, 0x70,
+ 0x87, 0xa3, 0x39, 0x33, 0xb9, 0x59, 0x00, 0xb0,
+ 0x04, 0xb4, 0x09, 0xe8, 0x9f, 0x38, 0xb9, 0x57,
+ 0x00, 0xb0, 0x2d, 0xe8, 0xa0, 0x38, 0xb9, 0xce,
+ 0x02, 0xe8, 0x03, 0xaa, 0xe8, 0xbd, 0xa9, 0xe8,
+ 0xe3, 0xad, 0xbb, 0xe2, 0x4f, 0xe8, 0xdd, 0x2e,
+ 0xc6, 0x06, 0xcf, 0xdb, 0x01, 0xc3, 0xb9, 0x59,
+ 0x00, 0xb0, 0x04, 0xb4, 0x09, 0xe8, 0x75, 0x38,
+ 0xb9, 0xcf, 0x02, 0xe8, 0x61, 0xa9, 0xe8, 0x57,
+ 0xce, 0xc6, 0x47, 0x04, 0x43, 0xe8, 0x98, 0x3c,
+ 0xe8, 0x91, 0xa9, 0xbb, 0x46, 0x67, 0xe8, 0x39,
+ 0xce, 0xfe, 0x07, 0xb0, 0x05, 0xe8, 0x3d, 0xa8,
+ 0xb0, 0x0c, 0xe8, 0x2c, 0xa8, 0xc3, 0x80, 0x3e,
+ 0xcd, 0xdb, 0x01, 0x74, 0x07, 0xbb, 0x9d, 0x3c,
+ 0xe8, 0x0a, 0xa0, 0xc3, 0x80, 0x3e, 0xce, 0xdb,
+ 0x01, 0x75, 0x07, 0xbb, 0x9b, 0x4f, 0xe8, 0x8c,
+ 0x2e, 0xc3, 0xbb, 0xb1, 0x4f, 0xe8, 0x85, 0x2e,
+ 0xb9, 0x20, 0x00, 0xb0, 0x06, 0xb4, 0x07, 0xe8,
+ 0x23, 0x38, 0xb9, 0xcd, 0x02, 0xe8, 0x30, 0xa9,
+ 0xb0, 0x42, 0xe8, 0x53, 0xb5, 0xc6, 0x06, 0xce,
+ 0xdb, 0x01, 0xc3, 0xe8, 0x69, 0xa9, 0xe8, 0xf7,
+ 0xcd, 0xc6, 0x47, 0x02, 0x00, 0xe8, 0x7c, 0x3c,
+ 0xb9, 0x20, 0x00, 0xb0, 0x07, 0xb4, 0x08, 0xe8,
+ 0xfb, 0x37, 0xb9, 0xc6, 0x02, 0xe8, 0x0f, 0xa9,
+ 0xb0, 0x3e, 0xe8, 0x2b, 0xb5, 0xb0, 0x07, 0xe8,
+ 0xd3, 0xa7, 0xb0, 0x08, 0xe8, 0xc2, 0xa7, 0xc3,
+ 0xe8, 0xbb, 0x32, 0xc3, 0xe8, 0x38, 0xa9, 0xe8,
+ 0xc6, 0xcd, 0xc6, 0x47, 0x03, 0x00, 0xe8, 0x4b,
+ 0x3c, 0xb9, 0x20, 0x00, 0xb0, 0x07, 0xb4, 0x0b,
+ 0xe8, 0xca, 0x37, 0xb9, 0xcb, 0x02, 0xe8, 0xde,
+ 0xa8, 0xb0, 0x3f, 0xe8, 0xfa, 0xb4, 0xb0, 0x09,
+ 0xe8, 0xa2, 0xa7, 0xc3, 0xe8, 0x99, 0xfe, 0xbb,
+ 0x60, 0x5c, 0xe8, 0x08, 0x2e, 0xc3, 0xbb, 0x82,
+ 0x5c, 0xe8, 0x01, 0x2e, 0xc3, 0x80, 0x3e, 0xd0,
+ 0xdb, 0x01, 0x74, 0x0d, 0xb9, 0xd1, 0x02, 0xe8,
+ 0xae, 0xa8, 0xbb, 0x5e, 0x50, 0xe8, 0xed, 0x2d,
+ 0xc3, 0xe8, 0xeb, 0xa8, 0xe8, 0x79, 0xcd, 0xc6,
+ 0x47, 0x04, 0x45, 0xe8, 0xfe, 0x3b, 0xb9, 0x20,
+ 0x00, 0xb0, 0x05, 0xb4, 0x08, 0xe8, 0x7d, 0x37,
+ 0xb9, 0xd5, 0x02, 0xe8, 0x91, 0xa8, 0xb0, 0x0c,
+ 0xe8, 0x5a, 0xa7, 0xb0, 0x45, 0xe8, 0xa8, 0xb4,
+ 0xc3, 0xb9, 0x59, 0x00, 0xb0, 0x03, 0xb4, 0x01,
+ 0xe8, 0x62, 0x37, 0xb9, 0xcf, 0x03, 0xe8, 0x5e,
+ 0xa8, 0xe8, 0xef, 0x38, 0xc7, 0x06, 0xf3, 0xb4,
+ 0x1f, 0x00, 0xb8, 0x2a, 0x01, 0xbb, 0xb1, 0x00,
+ 0xbf, 0x16, 0x01, 0xbe, 0xb1, 0x00, 0xb1, 0x01,
+ 0xb5, 0x04, 0xe8, 0x26, 0x39, 0xc3, 0xe8, 0x15,
+ 0x32, 0xc3, 0x80, 0x3e, 0xd6, 0xdb, 0x02, 0x75,
+ 0x07, 0xbb, 0x2c, 0x52, 0xe8, 0x86, 0x2d, 0xc3,
+ 0xb9, 0x4f, 0x00, 0xb0, 0x06, 0xb4, 0x0e, 0xe8,
+ 0x23, 0x37, 0xb9, 0x54, 0x00, 0xb0, 0x09, 0xe8,
+ 0x24, 0x37, 0xb9, 0x21, 0x03, 0xe8, 0x28, 0xa8,
+ 0xe8, 0x63, 0xac, 0x80, 0x3e, 0xd6, 0xdb, 0x01,
+ 0x74, 0x07, 0xbb, 0x72, 0x53, 0xe8, 0x5d, 0x2d,
+ 0xc3, 0xbb, 0x8d, 0x53, 0xe8, 0x56, 0x2d, 0xc6,
+ 0x06, 0xd6, 0xdb, 0x02, 0xc3, 0xe8, 0xce, 0x31,
+ 0xc3, 0xb9, 0x42, 0x00, 0xb0, 0x05, 0xb4, 0x03,
+ 0xe8, 0xea, 0x36, 0xb9, 0x43, 0x00, 0xb0, 0x0b,
+ 0xe8, 0xeb, 0x36, 0xb9, 0xd0, 0x03, 0xe8, 0xef,
+ 0xa7, 0xbb, 0x55, 0x59, 0xe8, 0x2e, 0x2d, 0xc3,
+ 0xbb, 0xdb, 0x5c, 0xe8, 0x27, 0x2d, 0xc3, 0xbb,
+ 0xfd, 0x5c, 0xe8, 0x20, 0x2d, 0xc3, 0xe8, 0x1e,
+ 0xa8, 0xe8, 0xac, 0xcc, 0xc6, 0x47, 0x01, 0x00,
+ 0xe8, 0x31, 0x3b, 0xb9, 0x05, 0x00, 0xb0, 0x2a,
+ 0xb4, 0x07, 0xe8, 0xb0, 0x36, 0xc6, 0x06, 0x35,
+ 0x33, 0x14, 0xc6, 0x06, 0x36, 0x33, 0x26, 0xb8,
+ 0x02, 0x4d, 0xa3, 0x37, 0x33, 0xb8, 0x82, 0x7f,
+ 0xa3, 0x39, 0x33, 0xc6, 0x06, 0xdc, 0x64, 0x00,
+ 0xb9, 0xb9, 0x02, 0xe8, 0x01, 0xa8, 0xc6, 0x06,
+ 0xdc, 0x64, 0x01, 0xe8, 0xb6, 0xa7, 0xb0, 0x38,
+ 0xe8, 0xbd, 0xb3, 0xb0, 0x01, 0xe8, 0x65, 0xa6,
+ 0xc3, 0xb9, 0x05, 0x00, 0xb0, 0x0c, 0xb4, 0x07,
+ 0xe8, 0x72, 0x36, 0xb9, 0xc0, 0x02, 0xe8, 0x8d,
+ 0xa7, 0xb0, 0x02, 0xe8, 0x4f, 0xa6, 0xb0, 0x3a,
+ 0xe8, 0x9d, 0xb3, 0xc3, 0xbb, 0x2c, 0x5d, 0xe8,
+ 0xb3, 0x2c, 0xc3, 0x80, 0x3e, 0xc5, 0xdb, 0x01,
+ 0x74, 0x20, 0xc6, 0x06, 0xc5, 0xdb, 0x01, 0x80,
+ 0x3e, 0xc6, 0xdb, 0x00, 0x74, 0x05, 0xb8, 0xbe,
+ 0x02, 0xeb, 0x03, 0xb8, 0xbd, 0x02, 0xe8, 0x25,
+ 0x00, 0xb0, 0x01, 0xe8, 0x61, 0xa6, 0xe8, 0x23,
+ 0x37, 0xc3, 0xc6, 0x06, 0xc5, 0xdb, 0x00, 0xb8,
+ 0xbd, 0x02, 0xe8, 0x11, 0x00, 0xe8, 0xc6, 0x36,
+ 0x80, 0x3e, 0xc6, 0xdb, 0x01, 0x75, 0x06, 0xbb,
+ 0xa6, 0x4d, 0xe8, 0x70, 0x2c, 0xc3, 0x50, 0xb9,
+ 0x47, 0x00, 0xb0, 0x03, 0xb4, 0x06, 0xe8, 0x0c,
+ 0x36, 0xb9, 0xbc, 0x02, 0xe8, 0xf8, 0xa6, 0xe8,
+ 0x99, 0x37, 0x58, 0xbb, 0x47, 0x33, 0x89, 0x07,
+ 0xc3, 0xbb, 0x41, 0x5d, 0xe8, 0x4e, 0x2c, 0xc3,
+ 0x80, 0x3e, 0xc4, 0xdb, 0x01, 0x75, 0x07, 0xbb,
+ 0x2a, 0x4d, 0xe8, 0x40, 0x2c, 0xc3, 0xe8, 0x3e,
+ 0xa7, 0xe8, 0xcc, 0xcb, 0xc6, 0x07, 0x00, 0xe8,
+ 0x52, 0x3a, 0xb9, 0x1a, 0x00, 0xb0, 0x11, 0xb4,
+ 0x0a, 0xe8, 0xd1, 0x35, 0xb0, 0x17, 0xe8, 0xd5,
+ 0x35, 0xb0, 0x1e, 0xe8, 0xd7, 0x35, 0xb0, 0x25,
+ 0xe8, 0xe0, 0x35, 0xb0, 0x2b, 0xe8, 0xe2, 0x35,
+ 0xb9, 0x34, 0x00, 0xb0, 0x22, 0xe8, 0xcc, 0x35,
+ 0xb9, 0xba, 0x02, 0xe8, 0xa4, 0xa6, 0xe8, 0x97,
+ 0xcb, 0xc6, 0x07, 0x34, 0xc6, 0x47, 0x02, 0x3d,
+ 0xe8, 0xd5, 0x39, 0xe8, 0xce, 0xa6, 0xbb, 0xb6,
+ 0x38, 0xe8, 0x61, 0x9d, 0xb0, 0x0b, 0xe8, 0x70,
+ 0xa5, 0xc6, 0x06, 0xc4, 0xdb, 0x01, 0xc3, 0xbb,
+ 0x6e, 0x5d, 0xe8, 0xe0, 0x2b, 0xc3, 0x80, 0x3e,
+ 0xc9, 0xdb, 0x01, 0x75, 0x07, 0xbb, 0xbb, 0x4d,
+ 0xe8, 0xd2, 0x2b, 0xc3, 0xc6, 0x06, 0xc9, 0xdb,
+ 0x01, 0xbb, 0xca, 0x3a, 0xe8, 0x36, 0x9d, 0xb9,
+ 0x3d, 0x00, 0xb0, 0x05, 0xb4, 0x09, 0xe8, 0x64,
+ 0x35, 0xb9, 0x05, 0x00, 0xb0, 0x0e, 0xe8, 0x65,
+ 0x35, 0xb9, 0xc1, 0x02, 0xe8, 0x69, 0xa6, 0xbb,
+ 0xd3, 0x4d, 0xe8, 0xa8, 0x2b, 0xb0, 0x3b, 0xe8,
+ 0x86, 0xb2, 0xc3, 0xc7, 0x06, 0xf3, 0xb4, 0x1d,
+ 0x00, 0xb8, 0x00, 0x01, 0xbb, 0xab, 0x00, 0xbf,
+ 0x00, 0x01, 0xbe, 0xb2, 0x00, 0xb1, 0x0b, 0xb5,
+ 0x03, 0xe8, 0x17, 0x37, 0xc3, 0xe8, 0x06, 0x30,
+ 0xc3, 0xe8, 0x83, 0xa6, 0xe8, 0x11, 0xcb, 0xc6,
+ 0x47, 0x02, 0x00, 0xe8, 0x96, 0x39, 0xb9, 0x05,
+ 0x00, 0xb0, 0x0c, 0xb4, 0x07, 0xe8, 0x15, 0x35,
+ 0xb9, 0xbb, 0x02, 0xe8, 0x29, 0xa6, 0xb0, 0x39,
+ 0xe8, 0x45, 0xb2, 0xb0, 0x0b, 0xe8, 0xed, 0xa4,
+ 0xc3, 0xc7, 0x06, 0xf3, 0xb4, 0x26, 0x00, 0xb8,
+ 0xa0, 0x00, 0xbb, 0xc7, 0x00, 0xbf, 0xa0, 0x00,
+ 0xbe, 0xbe, 0x00, 0xb1, 0x13, 0xb5, 0x01, 0xe8,
+ 0xd1, 0x36, 0xc3, 0x80, 0x3e, 0xd7, 0xdb, 0x01,
+ 0x74, 0x07, 0xbb, 0xcb, 0x52, 0xe8, 0x35, 0x2b,
+ 0xc3, 0x80, 0x3e, 0xd8, 0xdb, 0x01, 0x74, 0x07,
+ 0xbb, 0xfe, 0x52, 0xe8, 0x27, 0x2b, 0xc3, 0xb9,
+ 0x58, 0x00, 0xb0, 0x04, 0xb4, 0x0c, 0xe8, 0xc4,
+ 0x34, 0xb9, 0xd3, 0x03, 0xe8, 0xb0, 0xa5, 0xe8,
+ 0x51, 0x36, 0xc7, 0x06, 0xaf, 0x64, 0x33, 0x00,
+ 0xc7, 0x06, 0xb1, 0x64, 0xb7, 0x00, 0xbb, 0x47,
+ 0x33, 0xc7, 0x07, 0x00, 0x03, 0xc7, 0x47, 0x02,
+ 0x01, 0x03, 0xc7, 0x06, 0xf3, 0xb4, 0x25, 0x00,
+ 0xe8, 0xb2, 0x37, 0xc6, 0x06, 0x45, 0x33, 0xd9,
+ 0xc6, 0x06, 0x46, 0x33, 0xe5, 0xb0, 0x01, 0xb4,
+ 0x02, 0xbe, 0x00, 0x03, 0xbf, 0x01, 0x03, 0xbb,
+ 0xea, 0x54, 0xe8, 0xf1, 0x9e, 0xbb, 0x47, 0x33,
+ 0xc7, 0x07, 0x02, 0x03, 0xc7, 0x47, 0x02, 0x03,
+ 0x03, 0xe8, 0xd0, 0x34, 0xbb, 0x23, 0x55, 0xe8,
+ 0x33, 0x9c, 0xb9, 0x05, 0x00, 0xb0, 0x03, 0xb4,
+ 0x02, 0xe8, 0x61, 0x34, 0xb9, 0x38, 0x00, 0xb0,
+ 0x0c, 0xe8, 0x62, 0x34, 0xb9, 0x17, 0x00, 0xb0,
+ 0x14, 0xe8, 0x61, 0x34, 0xb9, 0x4b, 0x00, 0xb0,
+ 0x19, 0xe8, 0x60, 0x34, 0xb9, 0x04, 0x03, 0xe8,
+ 0x38, 0xa5, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x06,
+ 0x03, 0xb9, 0x05, 0x03, 0xe8, 0x2b, 0xa5, 0xe8,
+ 0xc9, 0x35, 0xc6, 0x06, 0xdc, 0x1c, 0x01, 0xe8,
+ 0x16, 0xca, 0xc6, 0x07, 0x4a, 0xe8, 0xeb, 0x38,
+ 0xe8, 0xcd, 0x35, 0xb0, 0x01, 0xbe, 0x07, 0x03,
+ 0xbb, 0x56, 0x55, 0xe8, 0x11, 0xa0, 0xbb, 0x47,
+ 0x33, 0xc7, 0x07, 0x08, 0x03, 0xb0, 0x01, 0xe8,
+ 0x70, 0xa4, 0xb0, 0x01, 0xb4, 0x02, 0xbe, 0x09,
+ 0x03, 0xbf, 0x0a, 0x03, 0xbb, 0xf7, 0x55, 0xe8,
+ 0x6c, 0x9e, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x0b,
+ 0x03, 0xc7, 0x47, 0x02, 0x0c, 0x03, 0xe8, 0x4b,
+ 0x34, 0xe8, 0xd8, 0x34, 0xb9, 0x3a, 0x00, 0xb0,
+ 0x01, 0xb4, 0x04, 0xe8, 0xdf, 0x33, 0xb0, 0x02,
+ 0xe8, 0xe3, 0x33, 0xb0, 0x03, 0xe8, 0xe5, 0x33,
+ 0xb0, 0x04, 0xe8, 0xe7, 0x33, 0xb0, 0x05, 0xe8,
+ 0xe9, 0x33, 0xb0, 0x06, 0xe8, 0xeb, 0x33, 0xb0,
+ 0x0a, 0xe8, 0xf4, 0x33, 0xb9, 0x02, 0x00, 0xb0,
+ 0x07, 0xe8, 0xe5, 0x33, 0xb9, 0x37, 0x00, 0xb0,
+ 0x0b, 0xe8, 0xeb, 0x33, 0xb9, 0x36, 0x00, 0xb0,
+ 0x0f, 0xb4, 0x0a, 0xe8, 0xe8, 0x33, 0xbb, 0x47,
+ 0x33, 0xc7, 0x47, 0x04, 0x0d, 0x03, 0xc7, 0x47,
+ 0x06, 0x0e, 0x03, 0xb0, 0x03, 0xe8, 0xfa, 0xa3,
+ 0xe8, 0x7d, 0xc9, 0xc6, 0x47, 0x01, 0x4b, 0xc6,
+ 0x47, 0x02, 0x4c, 0xe8, 0x4d, 0x38, 0xe8, 0x2f,
+ 0x35, 0xb9, 0x3a, 0x00, 0xb0, 0x01, 0xb4, 0x04,
+ 0xe8, 0x7a, 0x33, 0xb0, 0x02, 0xe8, 0x7e, 0x33,
+ 0xb0, 0x03, 0xe8, 0x80, 0x33, 0xb0, 0x04, 0xe8,
+ 0x82, 0x33, 0xb0, 0x05, 0xe8, 0x84, 0x33, 0xb0,
+ 0x06, 0xe8, 0x86, 0x33, 0xb0, 0x09, 0xe8, 0x8f,
+ 0x33, 0xb9, 0x02, 0x00, 0xb0, 0x07, 0xe8, 0x80,
+ 0x33, 0xb0, 0x0f, 0xb4, 0x07, 0xe8, 0x8e, 0x33,
+ 0xb9, 0x37, 0x00, 0xb0, 0x0a, 0xe8, 0x7f, 0x33,
+ 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x04, 0x0f, 0x03,
+ 0xc7, 0x47, 0x06, 0x10, 0x03, 0xb0, 0x03, 0xe8,
+ 0x98, 0xa3, 0xe8, 0x1b, 0xc9, 0xc6, 0x47, 0x01,
+ 0x4d, 0xc6, 0x47, 0x02, 0x4e, 0xe8, 0xeb, 0x37,
+ 0xe8, 0xcd, 0x34, 0xbb, 0x47, 0x33, 0xc7, 0x47,
+ 0x04, 0x11, 0x03, 0xc7, 0x47, 0x06, 0x12, 0x03,
+ 0xb0, 0x03, 0xe8, 0x75, 0xa3, 0xbb, 0x47, 0x33,
+ 0xc7, 0x07, 0xff, 0xff, 0xe8, 0xa7, 0x33, 0xc7,
+ 0x06, 0xaf, 0x64, 0x70, 0x00, 0xc6, 0x06, 0xdc,
+ 0x1c, 0x02, 0xe8, 0xe3, 0xc8, 0xc6, 0x47, 0x03,
+ 0x4f, 0xc6, 0x07, 0x00, 0xe8, 0xb4, 0x37, 0xe8,
+ 0x96, 0x34, 0xe8, 0x5f, 0x37, 0xc7, 0x06, 0x30,
+ 0x32, 0x96, 0x97, 0xc7, 0x06, 0x2e, 0x32, 0x2a,
+ 0x00, 0xc7, 0x06, 0x2c, 0x32, 0x3e, 0x00, 0xe8,
+ 0x4c, 0xb1, 0xe8, 0x93, 0x31, 0xbb, 0x47, 0x33,
+ 0xc7, 0x47, 0x04, 0x13, 0x03, 0xc7, 0x47, 0x06,
+ 0x14, 0x03, 0xb0, 0x03, 0xe8, 0x23, 0xa3, 0xbb,
+ 0x47, 0x33, 0xc7, 0x47, 0x02, 0xff, 0xff, 0xe8,
+ 0x54, 0x33, 0xb9, 0x20, 0x00, 0xb0, 0x02, 0xb4,
+ 0x0c, 0xe8, 0xa9, 0x32, 0xb9, 0x18, 0x00, 0xb0,
+ 0x07, 0xe8, 0xaa, 0x32, 0xbb, 0x47, 0x33, 0xc7,
+ 0x07, 0x15, 0x03, 0xc7, 0x47, 0x06, 0x16, 0x03,
+ 0xb0, 0x01, 0xe8, 0xf5, 0xa2, 0xbb, 0x47, 0x33,
+ 0xe8, 0x2b, 0x33, 0xe8, 0x72, 0xc8, 0xc6, 0x07,
+ 0x50, 0xe8, 0x47, 0x37, 0xe8, 0x29, 0x34, 0xe8,
+ 0xe2, 0xa1, 0xbb, 0x65, 0x56, 0xe8, 0x3d, 0x9a,
+ 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x06, 0x18, 0x03,
+ 0xe8, 0xc9, 0x32, 0xe8, 0x56, 0x33, 0xbe, 0x28,
+ 0x00, 0xbf, 0xab, 0x00, 0xc6, 0x06, 0xc3, 0x64,
+ 0x04, 0xe8, 0x87, 0xbe, 0xc7, 0x06, 0xf3, 0xb4,
+ 0x23, 0x00, 0xe8, 0x3b, 0xc8, 0xc6, 0x47, 0x03,
+ 0x51, 0xb0, 0x0c, 0xe8, 0x23, 0xa2, 0xc7, 0x06,
+ 0xf3, 0xb4, 0x1f, 0x00, 0xb8, 0x2a, 0x01, 0xbb,
+ 0xb1, 0x00, 0xbf, 0x16, 0x01, 0xbe, 0xb1, 0x00,
+ 0xb1, 0x01, 0xb5, 0x04, 0xe8, 0x14, 0x34, 0xc6,
+ 0x06, 0xd9, 0xdb, 0x01, 0xc3, 0xb9, 0x59, 0x00,
+ 0xb0, 0x06, 0xb4, 0x02, 0xe8, 0x1e, 0x32, 0xb9,
+ 0xd2, 0x03, 0xe8, 0x1a, 0xa3, 0xe8, 0xab, 0x33,
+ 0xc7, 0x06, 0xf3, 0xb4, 0x1f, 0x00, 0xb8, 0x2a,
+ 0x01, 0xbb, 0xb1, 0x00, 0xbf, 0x16, 0x01, 0xbe,
+ 0xb1, 0x00, 0xb1, 0x01, 0xb5, 0x04, 0xe8, 0xe2,
+ 0x33, 0xc3, 0x80, 0x3e, 0xd7, 0xdb, 0x01, 0x74,
+ 0x07, 0xbb, 0xcb, 0x52, 0xe8, 0x46, 0x28, 0xc3,
+ 0x80, 0x3e, 0xd8, 0xdb, 0x01, 0x75, 0x07, 0xbb,
+ 0xf6, 0x52, 0xe8, 0x38, 0x28, 0xc3, 0xb9, 0x47,
+ 0x00, 0xb0, 0x04, 0xb4, 0x0c, 0xe8, 0xd5, 0x31,
+ 0xb9, 0x1c, 0x03, 0xe8, 0xe2, 0xa2, 0xb8, 0x01,
+ 0x00, 0xe8, 0x45, 0xb6, 0xe8, 0x59, 0xb6, 0xc6,
+ 0x06, 0xd8, 0xdb, 0x01, 0xc3, 0xe8, 0x98, 0xa0,
+ 0xbb, 0x36, 0xdb, 0xe8, 0x67, 0x99, 0xe8, 0x7c,
+ 0x99, 0xc3, 0xbb, 0x87, 0x5d, 0xe8, 0x05, 0x28,
+ 0xc3, 0xbb, 0x11, 0x55, 0xe8, 0xfe, 0x27, 0xc3,
+ 0xbb, 0x11, 0x55, 0xe8, 0xf7, 0x27, 0xc3, 0xbb,
+ 0x0f, 0x57, 0xe8, 0xf0, 0x27, 0xc3, 0x80, 0x3e,
+ 0xdd, 0xdb, 0x03, 0x75, 0x07, 0xbb, 0xff, 0x55,
+ 0xe8, 0xe2, 0x27, 0xc3, 0xe8, 0xc1, 0x27, 0xc3,
+ 0xfe, 0x06, 0xdb, 0xdb, 0xa0, 0xdb, 0xdb, 0xbb,
+ 0x11, 0x54, 0x3c, 0x01, 0x74, 0x1f, 0xbb, 0x63,
+ 0x54, 0x3c, 0x02, 0x74, 0x18, 0xbb, 0x75, 0x54,
+ 0x3c, 0x03, 0x74, 0x11, 0xbb, 0x84, 0x54, 0x3c,
+ 0x04, 0x74, 0x0a, 0xbb, 0xc4, 0x54, 0x3c, 0x05,
+ 0x74, 0x03, 0xbb, 0xd5, 0x54, 0xe8, 0xad, 0x27,
+ 0xc3, 0x80, 0x3e, 0xe6, 0xdb, 0x01, 0x75, 0x07,
+ 0xbb, 0x27, 0x58, 0xe8, 0x9f, 0x27, 0xc3, 0xe8,
+ 0x7e, 0x27, 0xc3, 0x80, 0x3e, 0xe8, 0xdb, 0x01,
+ 0x74, 0x04, 0xe8, 0x73, 0x27, 0xc3, 0xbb, 0xb0,
+ 0x58, 0xe8, 0x89, 0x27, 0xc3, 0xc3, 0x80, 0x3e,
+ 0xa1, 0xdb, 0x01, 0x74, 0x07, 0xbb, 0x94, 0x36,
+ 0xe8, 0x7a, 0x27, 0xc3, 0xe8, 0x59, 0x27, 0xc3,
+ 0xe8, 0xe2, 0xd7, 0xe8, 0x52, 0x27, 0xc3, 0xe8,
+ 0x94, 0xdc, 0xe8, 0x4b, 0x27, 0xc3, 0xe8, 0x8d,
+ 0xdc, 0xe8, 0x44, 0x27, 0xc3, 0x80, 0x3e, 0x95,
+ 0xdb, 0x01, 0x75, 0x07, 0xbb, 0x75, 0x3e, 0xe8,
+ 0x53, 0x27, 0xc3, 0xe8, 0x32, 0x27, 0xc3, 0x80,
+ 0x3e, 0x94, 0xdb, 0x01, 0x75, 0x07, 0xbb, 0x4f,
+ 0x3e, 0xe8, 0x41, 0x27, 0xc3, 0xe8, 0x20, 0x27,
+ 0xc3, 0x80, 0x3e, 0xa5, 0xdb, 0x01, 0x75, 0x07,
+ 0xbb, 0x98, 0x3e, 0xe8, 0x2f, 0x27, 0xc3, 0xe8,
+ 0x0e, 0x27, 0xc3, 0xbe, 0xf5, 0x00, 0xbf, 0xc6,
+ 0x00, 0xc6, 0x06, 0xc3, 0x64, 0x01, 0xe8, 0xf2,
+ 0xbc, 0x80, 0x3e, 0xaf, 0xdb, 0x01, 0x74, 0x0c,
+ 0xbb, 0x93, 0x21, 0xe8, 0x7f, 0x98, 0xc6, 0x06,
+ 0xaf, 0xdb, 0x01, 0xc3, 0xe8, 0xe9, 0x26, 0xc3,
+ 0x80, 0x3e, 0xb1, 0xdb, 0x01, 0x75, 0x07, 0xbb,
+ 0xaf, 0x3d, 0xe8, 0xf8, 0x26, 0xc3, 0xe8, 0xd7,
+ 0x26, 0xc3, 0xe8, 0x50, 0xe7, 0xc3, 0x80, 0x3e,
+ 0xa4, 0xdb, 0x01, 0x74, 0x04, 0xe8, 0x45, 0xe7,
+ 0xc3, 0xe8, 0xc4, 0x26, 0xc3, 0x80, 0x3e, 0xa4,
+ 0xdb, 0x01, 0x74, 0x07, 0xbb, 0x32, 0x38, 0xe8,
+ 0xd3, 0x26, 0xc3, 0xe8, 0xb2, 0x26, 0xc3, 0x80,
+ 0x3e, 0xa4, 0xdb, 0x01, 0x74, 0x04, 0xe8, 0x6d,
+ 0xe8, 0xc3, 0xe8, 0xa3, 0x26, 0xc3, 0x80, 0x3e,
+ 0xa4, 0xdb, 0x01, 0x74, 0x04, 0xe8, 0x5e, 0xe8,
+ 0xc3, 0xe8, 0x94, 0x26, 0xc3, 0x80, 0x3e, 0xa4,
+ 0xdb, 0x01, 0x74, 0x04, 0xe8, 0x4f, 0xe8, 0xc3,
+ 0xe8, 0x85, 0x26, 0xc3, 0x80, 0x3e, 0xa4, 0xdb,
+ 0x01, 0x74, 0x04, 0xe8, 0x40, 0xe8, 0xc3, 0xe8,
+ 0x76, 0x26, 0xc3, 0x80, 0x3e, 0xa4, 0xdb, 0x01,
+ 0x74, 0x04, 0xe8, 0x31, 0xe8, 0xc3, 0xe8, 0x67,
+ 0x26, 0xc3, 0x80, 0x3e, 0x9d, 0xdb, 0x01, 0x75,
+ 0x07, 0xbb, 0x90, 0x35, 0xe8, 0x76, 0x26, 0xc3,
+ 0xe8, 0x55, 0x26, 0xc3, 0xe8, 0x62, 0xee, 0xe8,
+ 0x4e, 0x26, 0xc3, 0xa0, 0xc1, 0xdb, 0x98, 0x48,
+ 0xd1, 0xe0, 0xbb, 0x3c, 0x5f, 0x03, 0xd8, 0x8b,
+ 0x1f, 0xe8, 0x59, 0x26, 0xc3, 0x80, 0x3e, 0xb7,
+ 0xdb, 0x01, 0x74, 0x04, 0xe8, 0x31, 0x26, 0xc3,
+ 0xbb, 0x6c, 0x4b, 0xe8, 0x47, 0x26, 0xc3, 0x80,
+ 0x3e, 0xb8, 0xdb, 0x01, 0x74, 0x04, 0xe8, 0x1f,
+ 0x26, 0xc3, 0x80, 0x3e, 0xbf, 0xdb, 0x01, 0x74,
+ 0x21, 0xbb, 0x32, 0x4c, 0xe8, 0x2e, 0x26, 0xb9,
+ 0x05, 0x00, 0xb0, 0x0b, 0xb4, 0x07, 0xe8, 0xcc,
+ 0x2f, 0xb9, 0xb2, 0x02, 0xe8, 0xd9, 0xa0, 0xb0,
+ 0x35, 0xe8, 0xfc, 0xac, 0xc6, 0x06, 0xbf, 0xdb,
+ 0x01, 0xc3, 0xbb, 0x87, 0x4b, 0xe8, 0x0d, 0x26,
+ 0xc3, 0x80, 0x3e, 0xb9, 0xdb, 0x01, 0x74, 0x04,
+ 0xe8, 0xe5, 0x25, 0xc3, 0xbb, 0xa1, 0x4b, 0xe8,
+ 0xfb, 0x25, 0xc3, 0x80, 0x3e, 0xba, 0xdb, 0x01,
+ 0x74, 0x04, 0xe8, 0xd3, 0x25, 0xc3, 0xbb, 0xbc,
+ 0x4b, 0xe8, 0xe9, 0x25, 0xc3, 0x80, 0x3e, 0xbb,
+ 0xdb, 0x01, 0x74, 0x04, 0xe8, 0xc1, 0x25, 0xc3,
+ 0xbb, 0xd8, 0x4b, 0xe8, 0xd7, 0x25, 0xc3, 0x80,
+ 0x3e, 0xbc, 0xdb, 0x01, 0x74, 0x04, 0xe8, 0xaf,
+ 0x25, 0xc3, 0x80, 0x3e, 0xbe, 0xdb, 0x01, 0x74,
+ 0x21, 0xbb, 0x0f, 0x4c, 0xe8, 0xbe, 0x25, 0xb9,
+ 0x05, 0x00, 0xb0, 0x0c, 0xb4, 0x07, 0xe8, 0x5c,
+ 0x2f, 0xb9, 0xb1, 0x02, 0xe8, 0x69, 0xa0, 0xb0,
+ 0x34, 0xe8, 0x8c, 0xac, 0xc6, 0x06, 0xbe, 0xdb,
+ 0x01, 0xc3, 0xbb, 0xf4, 0x4b, 0xe8, 0x9d, 0x25,
+ 0xc3, 0x80, 0x3e, 0xb6, 0xdb, 0x01, 0x74, 0x0c,
+ 0xbb, 0xd0, 0x37, 0xe8, 0xff, 0x96, 0xc6, 0x06,
+ 0xb6, 0xdb, 0x01, 0xc3, 0xe8, 0x69, 0x25, 0xc3,
+ 0xe8, 0x0d, 0xf6, 0xe8, 0x62, 0x25, 0xc3, 0xe8,
+ 0x06, 0xf6, 0xe8, 0x5b, 0x25, 0xc3, 0x80, 0x3e,
+ 0xcd, 0xdb, 0x01, 0x74, 0x04, 0xe8, 0x50, 0x25,
+ 0xc3, 0xbb, 0x69, 0x4f, 0xe8, 0x66, 0x25, 0xc3,
+ 0xe8, 0xed, 0xf5, 0xe8, 0x42, 0x25, 0xc3, 0x80,
+ 0x3e, 0xd0, 0xdb, 0x01, 0x74, 0x04, 0xe8, 0x37,
+ 0x25, 0xc3, 0xbb, 0x82, 0x50, 0xe8, 0x4d, 0x25,
+ 0xc3, 0xa0, 0xd6, 0xdb, 0x3c, 0x01, 0x74, 0x08,
+ 0x3c, 0x02, 0x74, 0x0b, 0xe8, 0x21, 0x25, 0xc3,
+ 0xbb, 0xf8, 0x51, 0xe8, 0x37, 0x25, 0xc3, 0xbb,
+ 0x8d, 0x53, 0xe8, 0x30, 0x25, 0xc3, 0xe8, 0x2e,
+ 0xa0, 0xe8, 0xbc, 0xc4, 0xc6, 0x07, 0x00, 0xe8,
+ 0x42, 0x33, 0xb9, 0x05, 0x00, 0xb0, 0x02, 0xb4,
+ 0x0c, 0xe8, 0xc1, 0x2e, 0xb9, 0x33, 0x00, 0xb0,
+ 0x0b, 0xe8, 0xc2, 0x2e, 0xb0, 0x17, 0xe8, 0xc4,
+ 0x2e, 0xb9, 0x45, 0x03, 0xe8, 0xa3, 0x9f, 0xb9,
+ 0x33, 0x00, 0xb0, 0x03, 0xb4, 0x0d, 0xe8, 0xa4,
+ 0x2e, 0xb0, 0x13, 0xe8, 0xa8, 0x2e, 0xb9, 0x17,
+ 0x00, 0xb0, 0x1a, 0xe8, 0xa7, 0x2e, 0xb9, 0x46,
+ 0x03, 0xe8, 0x86, 0x9f, 0xe8, 0x79, 0xc4, 0xc6,
+ 0x07, 0x60, 0xe8, 0xbb, 0x32, 0xc7, 0x06, 0xaf,
+ 0x64, 0x19, 0x01, 0xe8, 0xae, 0x9f, 0xb0, 0x04,
+ 0xe8, 0x62, 0x9e, 0xc6, 0x06, 0xe1, 0xdb, 0x01,
+ 0xc3, 0x80, 0x3e, 0xe1, 0xdb, 0x01, 0x74, 0x07,
+ 0xbb, 0xda, 0x56, 0xe8, 0xbf, 0x24, 0xc3, 0xb9,
+ 0x4c, 0x03, 0xe8, 0x52, 0x9f, 0xe8, 0x48, 0xc4,
+ 0xc6, 0x47, 0x01, 0x00, 0x53, 0xe8, 0x88, 0x32,
+ 0xb9, 0x05, 0x00, 0xb0, 0x05, 0xb4, 0x0a, 0xe8,
+ 0x4b, 0x2e, 0xb9, 0x1a, 0x00, 0xb0, 0x13, 0xe8,
+ 0x4c, 0x2e, 0xb9, 0x18, 0x00, 0xb0, 0x19, 0xe8,
+ 0x4b, 0x2e, 0xb9, 0x4f, 0x03, 0xe8, 0x2a, 0x9f,
+ 0xb9, 0x05, 0x00, 0xb0, 0x0b, 0xb4, 0x09, 0xe8,
+ 0x2b, 0x2e, 0xb9, 0x50, 0x03, 0xe8, 0x1a, 0x9f,
+ 0x5b, 0xc6, 0x47, 0x01, 0x64, 0xe8, 0x50, 0x32,
+ 0xb9, 0x4d, 0x03, 0xe8, 0x31, 0x9f, 0xb0, 0x03,
+ 0xe8, 0xfa, 0x9d, 0xb0, 0x52, 0xe8, 0x48, 0xab,
+ 0xb0, 0x51, 0xe8, 0x53, 0xab, 0xc3, 0xbb, 0x54,
+ 0x5e, 0xe8, 0x59, 0x24, 0xc3, 0xb9, 0x4c, 0x00,
+ 0xb0, 0x12, 0xb4, 0x08, 0xe8, 0xf6, 0x2d, 0xb0,
+ 0x16, 0xe8, 0xfa, 0x2d, 0xb0, 0x1a, 0xe8, 0xfc,
+ 0x2d, 0xb0, 0x1e, 0xe8, 0xfe, 0x2d, 0xb0, 0x22,
+ 0xe8, 0x00, 0x2e, 0xb0, 0x2f, 0xe8, 0x02, 0x2e,
+ 0xb0, 0x33, 0xe8, 0x04, 0x2e, 0xb0, 0x37, 0xe8,
+ 0x06, 0x2e, 0xb0, 0x3b, 0xe8, 0x08, 0x2e, 0xb0,
+ 0x3f, 0xe8, 0x0a, 0x2e, 0xb9, 0x69, 0x03, 0xe8,
+ 0xd6, 0x9e, 0xbe, 0xf0, 0x00, 0xbf, 0xa3, 0x00,
+ 0xc6, 0x06, 0xc3, 0x64, 0x04, 0xe8, 0xe3, 0xb9,
+ 0xbb, 0x37, 0x58, 0xe8, 0x07, 0x24, 0xb4, 0x01,
+ 0xb0, 0x22, 0xe8, 0xb9, 0xa2, 0xb9, 0x4d, 0x00,
+ 0xb0, 0x02, 0xb4, 0x08, 0xe8, 0x9e, 0x2d, 0xb0,
+ 0x0c, 0xe8, 0xa2, 0x2d, 0xb0, 0x10, 0xe8, 0xa4,
+ 0x2d, 0xb0, 0x14, 0xe8, 0xa6, 0x2d, 0xb0, 0x22,
+ 0xe8, 0xa8, 0x2d, 0xb9, 0x4e, 0x00, 0xb0, 0x29,
+ 0xe8, 0xa7, 0x2d, 0xb0, 0x33, 0xe8, 0xa9, 0x2d,
+ 0xb9, 0x38, 0x00, 0xb0, 0x3f, 0xe8, 0xa8, 0x2d,
+ 0xb9, 0x18, 0x00, 0xb0, 0x43, 0xe8, 0xa7, 0x2d,
+ 0xb9, 0x17, 0x00, 0xb0, 0x4c, 0xe8, 0xa6, 0x2d,
+ 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x6a, 0x03, 0xb0,
+ 0x01, 0xe8, 0x7c, 0x9d, 0xe8, 0x45, 0x2e, 0xe8,
+ 0x3e, 0xc3, 0xc6, 0x07, 0x68, 0xe8, 0xc4, 0x31,
+ 0xb8, 0x01, 0x00, 0xe8, 0xc3, 0xb1, 0xe8, 0xd7,
+ 0xb1, 0xb0, 0x5b, 0xe8, 0x8a, 0xaa, 0xb0, 0x06,
+ 0xe8, 0x16, 0x9d, 0xb0, 0x01, 0xe8, 0x1d, 0x9d,
+ 0xc3, 0xbb, 0xbe, 0x5e, 0xe8, 0x86, 0x23, 0xc3,
+ 0xbb, 0xbe, 0x5e, 0xe8, 0x7f, 0x23, 0xc3, 0xbb,
+ 0xe6, 0x5e, 0xe8, 0x78, 0x23, 0xc3, 0xbb, 0x11,
+ 0x5f, 0xe8, 0x71, 0x23, 0xc3, 0xb9, 0x05, 0x00,
+ 0xb0, 0x02, 0xb4, 0x07, 0xe8, 0x0e, 0x2d, 0xb9,
+ 0x13, 0x00, 0xb0, 0x0b, 0xe8, 0x0f, 0x2d, 0xb9,
+ 0x48, 0x03, 0xe8, 0x02, 0x9e, 0xe8, 0xe8, 0xc2,
+ 0xc6, 0x47, 0x01, 0x61, 0xe8, 0x29, 0x31, 0xe8,
+ 0x22, 0x9e, 0xb0, 0x50, 0xe8, 0x39, 0xaa, 0xb0,
+ 0x02, 0xe8, 0xd1, 0x9c, 0xb0, 0x07, 0xe8, 0xc0,
+ 0x9c, 0xc3, 0x80, 0x3e, 0xdf, 0xdb, 0x01, 0x76,
+ 0x07, 0xbb, 0xf6, 0x52, 0xe8, 0x2e, 0x23, 0xc3,
+ 0xb9, 0x05, 0x00, 0xb0, 0x02, 0xb4, 0x0c, 0xe8,
+ 0xcb, 0x2c, 0xb9, 0x39, 0x00, 0xb0, 0x0c, 0xe8,
+ 0xcc, 0x2c, 0xb9, 0x46, 0x00, 0xb0, 0x13, 0xe8,
+ 0xcb, 0x2c, 0xb9, 0x3c, 0x03, 0xe8, 0xa7, 0x9d,
+ 0xe8, 0x48, 0x2e, 0xc7, 0x06, 0xaf, 0x64, 0x06,
+ 0x01, 0xc7, 0x06, 0xb1, 0x64, 0xa0, 0x00, 0xc6,
+ 0x06, 0xcc, 0x64, 0x01, 0xc6, 0x06, 0xcd, 0x64,
+ 0x00, 0xc6, 0x06, 0xcb, 0x64, 0x01, 0xe8, 0x10,
+ 0xc1, 0xb0, 0x04, 0xe8, 0x77, 0x9c, 0xb0, 0x03,
+ 0xe8, 0x72, 0x9c, 0xe8, 0x72, 0xc2, 0xc6, 0x07,
+ 0x00, 0xc6, 0x47, 0x02, 0x00, 0xc6, 0x47, 0x03,
+ 0x00, 0xc6, 0x47, 0x01, 0x55, 0xbb, 0x47, 0x33,
+ 0xc7, 0x07, 0x3d, 0x03, 0xc7, 0x06, 0xf3, 0xb4,
+ 0x05, 0x00, 0xe8, 0x53, 0xc2, 0xc6, 0x07, 0x5c,
+ 0xe8, 0x7a, 0x2f, 0xe8, 0x4a, 0xc2, 0xc6, 0x07,
+ 0x00, 0xb8, 0xc8, 0x00, 0xe8, 0x93, 0xa1, 0xc6,
+ 0x06, 0x45, 0x33, 0xd0, 0xb0, 0x01, 0xbe, 0x3e,
+ 0x03, 0xbb, 0xa5, 0x63, 0xe8, 0x40, 0x98, 0xb9,
+ 0x04, 0x00, 0xe8, 0x8e, 0x33, 0xbb, 0x47, 0x33,
+ 0xc7, 0x07, 0x3f, 0x03, 0xc7, 0x06, 0xf3, 0xb4,
+ 0x07, 0x00, 0xe8, 0x3f, 0x2f, 0xc7, 0x06, 0xaf,
+ 0x64, 0x82, 0x00, 0xc7, 0x06, 0xb1, 0x64, 0xc3,
+ 0x00, 0xc6, 0x06, 0xdc, 0x1c, 0x02, 0xe8, 0x95,
+ 0xaa, 0xe8, 0x71, 0xa1, 0xe8, 0x92, 0x99, 0xbb,
+ 0x06, 0x64, 0xe8, 0xd8, 0x93, 0xbb, 0x47, 0x33,
+ 0xc7, 0x07, 0x3f, 0x03, 0xb0, 0x01, 0xe8, 0x2e,
+ 0x9c, 0xe8, 0xf0, 0x2c, 0xc6, 0x06, 0xdf, 0xdb,
+ 0x02, 0xc3, 0x80, 0x3e, 0xe0, 0xdb, 0x01, 0x75,
+ 0x07, 0xbb, 0x32, 0x56, 0xe8, 0x46, 0x22, 0xc3,
+ 0xb9, 0x05, 0x00, 0xb0, 0x06, 0xb4, 0x05, 0xe8,
+ 0xe3, 0x2b, 0xb9, 0x1b, 0x00, 0xb0, 0x31, 0xe8,
+ 0xe4, 0x2b, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x43,
+ 0x03, 0xb9, 0x42, 0x03, 0xe8, 0xc0, 0x9c, 0xe8,
+ 0xb6, 0xc1, 0xc6, 0x07, 0x5e, 0xe8, 0xf8, 0x2f,
+ 0xe8, 0xf1, 0x9c, 0xe8, 0x3b, 0x99, 0xbb, 0xe9,
+ 0x65, 0xe8, 0x81, 0x93, 0xb0, 0x0c, 0xe8, 0x90,
+ 0x9b, 0xc6, 0x06, 0xe0, 0xdb, 0x01, 0xc3, 0xe8,
+ 0x32, 0x99, 0xbb, 0xc0, 0x66, 0xe8, 0x6d, 0x93,
+ 0xb9, 0x05, 0x00, 0xb0, 0x03, 0xb4, 0x03, 0xe8,
+ 0x9b, 0x2b, 0xb9, 0x54, 0x03, 0xe8, 0x8a, 0x9c,
+ 0xe8, 0x28, 0x2d, 0xc6, 0x06, 0xdc, 0x1c, 0x01,
+ 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x55, 0x03, 0xb0,
+ 0x01, 0xe8, 0xab, 0x9b, 0xe8, 0x6d, 0x2c, 0xa0,
+ 0xac, 0x64, 0x50, 0xc6, 0x06, 0xac, 0x64, 0x04,
+ 0xe8, 0x10, 0x8d, 0xbb, 0x42, 0x57, 0xbe, 0x13,
+ 0x8c, 0xe8, 0x6a, 0x24, 0xbb, 0x57, 0x57, 0xbe,
+ 0x12, 0x8c, 0xe8, 0x61, 0x24, 0xbb, 0x70, 0x57,
+ 0xbe, 0x1d, 0x8c, 0xe8, 0x58, 0x24, 0xbb, 0x82,
+ 0x57, 0xbe, 0x0f, 0x8c, 0xe8, 0x4f, 0x24, 0xbb,
+ 0x99, 0x57, 0xbe, 0x07, 0x8c, 0xe8, 0x46, 0x24,
+ 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x58, 0x03, 0xb0,
+ 0x01, 0xe8, 0x63, 0x9b, 0xb9, 0x05, 0x00, 0xb0,
+ 0x03, 0xb4, 0x03, 0xe8, 0x2f, 0x2b, 0xb9, 0x56,
+ 0x03, 0xe8, 0x1e, 0x9c, 0xe8, 0xbc, 0x2c, 0x58,
+ 0xa2, 0xac, 0x64, 0xe8, 0xbd, 0x8c, 0xe8, 0xa3,
+ 0x98, 0xbb, 0xfe, 0x66, 0xe8, 0xde, 0x92, 0xbb,
+ 0x47, 0x33, 0xc7, 0x07, 0x57, 0x03, 0xb0, 0x01,
+ 0xe8, 0x34, 0x9b, 0xb8, 0xc8, 0x00, 0xe8, 0x41,
+ 0xa0, 0xbe, 0x1e, 0x00, 0xbf, 0xb5, 0x00, 0xe8,
+ 0x29, 0xb7, 0xe8, 0x99, 0x2b, 0xb0, 0x01, 0xe8,
+ 0xdb, 0x9a, 0xb8, 0x01, 0x00, 0xe8, 0x69, 0xaf,
+ 0xc6, 0x06, 0xdf, 0xdb, 0x03, 0xc6, 0x06, 0xf0,
+ 0xdb, 0x01, 0xc6, 0x06, 0xdc, 0x1c, 0x02, 0xe8,
+ 0x79, 0xc4, 0xc3, 0x80, 0x3e, 0xdf, 0xdb, 0x03,
+ 0x74, 0x07, 0xbb, 0xe2, 0x5d, 0xe8, 0x25, 0x21,
+ 0xc3, 0xb9, 0x05, 0x00, 0xb0, 0x03, 0xb4, 0x09,
+ 0xe8, 0xc2, 0x2a, 0xb9, 0x3a, 0x00, 0xb0, 0x0b,
+ 0xe8, 0xc3, 0x2a, 0xb9, 0x2e, 0x00, 0xb0, 0x38,
+ 0xe8, 0xc2, 0x2a, 0xb0, 0x55, 0xe8, 0xc4, 0x2a,
+ 0xb0, 0x75, 0xe8, 0xc6, 0x2a, 0xb9, 0x66, 0x03,
+ 0xe8, 0x94, 0x9b, 0xb9, 0x36, 0x00, 0xb0, 0x0f,
+ 0xb4, 0x09, 0xe8, 0x98, 0x2a, 0xb9, 0x67, 0x03,
+ 0xe8, 0x87, 0x9b, 0xe8, 0x25, 0x2c, 0xc6, 0x06,
+ 0xe6, 0xdb, 0x01, 0xe8, 0x72, 0xc0, 0xc6, 0x47,
+ 0x01, 0x66, 0xe8, 0xf7, 0x2e, 0xb8, 0x32, 0x00,
+ 0xe8, 0xd9, 0x9f, 0xc7, 0x06, 0xaf, 0x64, 0xe0,
+ 0x00, 0xc7, 0x06, 0xb1, 0x64, 0xc2, 0x00, 0xc6,
+ 0x06, 0xcc, 0x64, 0x00, 0xc6, 0x06, 0xdc, 0x64,
+ 0x01, 0xc6, 0x06, 0xcb, 0x64, 0x00, 0xe8, 0xd8,
+ 0xbe, 0xc6, 0x06, 0xdc, 0x1c, 0x03, 0xe8, 0xcd,
+ 0xa8, 0xbe, 0xd7, 0x76, 0xbb, 0xdf, 0x57, 0xc6,
+ 0x06, 0xdc, 0x1c, 0x02, 0xe8, 0x5e, 0x1c, 0xb0,
+ 0x59, 0xe8, 0x8c, 0xa7, 0xc3, 0xb9, 0x05, 0x00,
+ 0xb0, 0x03, 0xb4, 0x06, 0xe8, 0x36, 0x2a, 0xb9,
+ 0x6c, 0x03, 0xe8, 0x32, 0x9b, 0xe8, 0xc3, 0x2b,
+ 0xe8, 0x15, 0xc0, 0xc6, 0x47, 0x01, 0x00, 0xe8,
+ 0x9a, 0x2e, 0xb9, 0x1a, 0x00, 0xb0, 0x07, 0xb4,
+ 0x04, 0xe8, 0x19, 0x2a, 0xb9, 0x4f, 0x00, 0xb0,
+ 0x0f, 0xe8, 0x1a, 0x2a, 0xbb, 0x47, 0x33, 0xc7,
+ 0x47, 0x02, 0x6d, 0x03, 0xb0, 0x02, 0xe8, 0x27,
+ 0x9a, 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x02, 0x70,
+ 0x03, 0xb0, 0x02, 0xe8, 0x21, 0x9a, 0xe8, 0xe3,
+ 0x2a, 0xe8, 0x04, 0x97, 0xbb, 0x0e, 0x6f, 0xe8,
+ 0xb3, 0x91, 0xe8, 0xd3, 0xbf, 0xc6, 0x47, 0x02,
+ 0x6a, 0xe8, 0x58, 0x2e, 0xbb, 0x47, 0x33, 0xc7,
+ 0x07, 0x6e, 0x03, 0xb0, 0x01, 0xe8, 0xf8, 0x99,
+ 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x6f, 0x03, 0xb0,
+ 0x01, 0xe8, 0xf3, 0x99, 0xe8, 0xb5, 0x2a, 0xb0,
+ 0x5c, 0xe8, 0x0c, 0xa7, 0xb0, 0x01, 0xe8, 0x98,
+ 0x99, 0xc6, 0x06, 0xe7, 0xdb, 0x01, 0xc3, 0xb9,
+ 0x20, 0x00, 0xb0, 0x05, 0xb4, 0x0a, 0xe8, 0xac,
+ 0x29, 0xb9, 0x05, 0x00, 0xb0, 0x11, 0xe8, 0xad,
+ 0x29, 0xb9, 0x34, 0x00, 0xb0, 0x17, 0xe8, 0xac,
+ 0x29, 0xb9, 0x71, 0x03, 0xe8, 0x88, 0x9a, 0xe8,
+ 0x7e, 0xbf, 0xc6, 0x47, 0x02, 0x6b, 0xe8, 0xbf,
+ 0x2d, 0xe8, 0xb8, 0x9a, 0xb0, 0x56, 0xe8, 0xcf,
+ 0xa6, 0xb0, 0x55, 0xe8, 0xba, 0xa6, 0xc6, 0x06,
+ 0xe8, 0xdb, 0x01, 0xc3, 0xbb, 0x8f, 0x5e, 0xe8,
+ 0xcb, 0x1f, 0xc3, 0x80, 0x3e, 0xda, 0xdb, 0x01,
+ 0x75, 0x07, 0xbb, 0xf2, 0x53, 0xe8, 0xbd, 0x1f,
+ 0xc3, 0xbb, 0xdd, 0x53, 0xe8, 0xb6, 0x1f, 0xb9,
+ 0x05, 0x00, 0xb0, 0x02, 0xb4, 0x07, 0xe8, 0x54,
+ 0x29, 0xb0, 0x12, 0xe8, 0x58, 0x29, 0xb9, 0x2a,
+ 0x03, 0xe8, 0x5c, 0x9a, 0xe8, 0xe3, 0x96, 0xbb,
+ 0xbf, 0x60, 0xe8, 0x08, 0x91, 0xc6, 0x06, 0xda,
+ 0xdb, 0x01, 0xc3, 0xe8, 0xd4, 0x96, 0xbb, 0x11,
+ 0x68, 0xe8, 0xf9, 0x90, 0xb9, 0x05, 0x00, 0xb0,
+ 0x03, 0xb4, 0x05, 0xe8, 0x27, 0x29, 0xb0, 0x1e,
+ 0xe8, 0x32, 0x29, 0xb9, 0x1a, 0x00, 0xb0, 0x0e,
+ 0xe8, 0x23, 0x29, 0xbb, 0x47, 0x33, 0xc7, 0x07,
+ 0x53, 0x03, 0xb9, 0x51, 0x03, 0xe8, 0x02, 0x9a,
+ 0xe8, 0xa0, 0x2a, 0xbb, 0x47, 0x33, 0xc7, 0x07,
+ 0x52, 0x03, 0xb0, 0x01, 0xe8, 0x28, 0x99, 0xe8,
+ 0xea, 0x29, 0xb0, 0x53, 0xe8, 0x31, 0xa6, 0xb0,
+ 0x52, 0xe8, 0x3c, 0xa6, 0xb0, 0x01, 0xe8, 0xc8,
+ 0x98, 0xc6, 0x06, 0xe2, 0xdb, 0x01, 0xc3, 0xe8,
+ 0x0c, 0x97, 0xbb, 0x41, 0x0a, 0xe8, 0xa5, 0x90,
+ 0xb9, 0x05, 0x00, 0xb0, 0x02, 0xb4, 0x0a, 0xe8,
+ 0xd3, 0x28, 0xb0, 0x2c, 0xe8, 0xd7, 0x28, 0xbb,
+ 0x47, 0x33, 0xc7, 0x07, 0x82, 0x02, 0xb9, 0x81,
+ 0x02, 0xe8, 0xd4, 0x99, 0xe8, 0xe7, 0x96, 0xbb,
+ 0xff, 0x0a, 0xe8, 0x80, 0x90, 0xb8, 0xaa, 0x00,
+ 0xe8, 0xef, 0x9d, 0xe8, 0xd8, 0x96, 0xbb, 0xa0,
+ 0x0b, 0xe8, 0x71, 0x90, 0x8b, 0x36, 0xaf, 0x64,
+ 0xbb, 0xb1, 0x64, 0x8b, 0x3f, 0xff, 0x0f, 0xe8,
+ 0xc9, 0xb4, 0xe8, 0xf0, 0x9d, 0xbb, 0x10, 0x0c,
+ 0xe8, 0x5a, 0x90, 0xb0, 0x32, 0xe8, 0xd8, 0xa5,
+ 0xe8, 0xd2, 0x1b, 0xc3, 0xe8, 0xe0, 0x99, 0xe8,
+ 0x6e, 0xbe, 0xc6, 0x07, 0x00, 0x53, 0xe8, 0xf3,
+ 0x2c, 0xb9, 0x05, 0x00, 0xb0, 0x02, 0xb4, 0x09,
+ 0xe8, 0x72, 0x28, 0xb0, 0x05, 0xe8, 0x76, 0x28,
+ 0xb0, 0x09, 0xe8, 0x78, 0x28, 0xb9, 0x0e, 0x00,
+ 0xb0, 0x13, 0xe8, 0x77, 0x28, 0xb9, 0x05, 0x00,
+ 0xb0, 0x32, 0xe8, 0x76, 0x28, 0xb9, 0x1e, 0x02,
+ 0xe8, 0x47, 0x99, 0x5b, 0xb0, 0x0f, 0x88, 0x47,
+ 0x01, 0xe8, 0x6d, 0x2d, 0xb0, 0x03, 0xe8, 0x2c,
+ 0x98, 0xb0, 0x09, 0xe8, 0x1b, 0x98, 0xe8, 0x6b,
+ 0x99, 0xc3, 0xb9, 0x38, 0x00, 0xb0, 0x0b, 0xb4,
+ 0x08, 0xe8, 0x31, 0x28, 0xb9, 0x24, 0x00, 0xb0,
+ 0x0d, 0xb4, 0x0c, 0xe8, 0x30, 0x28, 0xb9, 0x30,
+ 0x00, 0xb0, 0x16, 0xb4, 0x0a, 0xe8, 0x2d, 0x28,
+ 0xb9, 0x38, 0x00, 0xb0, 0x39, 0xb4, 0x08, 0xe8,
+ 0x2a, 0x28, 0xb9, 0x24, 0x00, 0xb0, 0x3b, 0xb4,
+ 0x0c, 0xe8, 0x27, 0x28, 0xb9, 0x30, 0x00, 0xb0,
+ 0x44, 0xb4, 0x0a, 0xe8, 0x24, 0x28, 0xb9, 0x36,
+ 0x00, 0xb0, 0x78, 0xb4, 0x08, 0xe8, 0x21, 0x28,
+ 0xb9, 0x38, 0x00, 0xb0, 0x8d, 0xb4, 0x0a, 0xe8,
+ 0x1e, 0x28, 0xb0, 0x90, 0xe8, 0x20, 0x28, 0xb0,
+ 0x93, 0xe8, 0x22, 0x28, 0xbb, 0x47, 0x33, 0xc7,
+ 0x07, 0x4d, 0x02, 0xb9, 0x4c, 0x02, 0xe8, 0xe7,
+ 0x98, 0xe8, 0x22, 0x9d, 0xbb, 0x7f, 0x36, 0xe8,
+ 0x23, 0x1e, 0xb0, 0x22, 0xe8, 0x11, 0xa5, 0xc6,
+ 0x06, 0xa1, 0xdb, 0x01, 0xc3, 0xb9, 0x05, 0x00,
+ 0xb0, 0x03, 0xb4, 0x03, 0xe8, 0xb6, 0x27, 0xb9,
+ 0x41, 0x00, 0xb0, 0x10, 0xe8, 0xb7, 0x27, 0xb0,
+ 0x12, 0xe8, 0xb9, 0x27, 0xb0, 0x14, 0xe8, 0xbb,
+ 0x27, 0xb0, 0x16, 0xe8, 0xbd, 0x27, 0xb0, 0x18,
+ 0xe8, 0xbf, 0x27, 0xb0, 0x1a, 0xe8, 0xc1, 0x27,
+ 0xb0, 0x1c, 0xe8, 0xc3, 0x27, 0xb9, 0x2f, 0x00,
+ 0xb0, 0x21, 0xe8, 0xc2, 0x27, 0xb9, 0x6c, 0x02,
+ 0xe8, 0x74, 0x98, 0xb9, 0x38, 0x00, 0xb0, 0x03,
+ 0xb4, 0x03, 0xe8, 0x78, 0x27, 0xb0, 0x06, 0xe8,
+ 0x7c, 0x27, 0xb0, 0x09, 0xe8, 0x7e, 0x27, 0xb0,
+ 0x0c, 0xe8, 0x80, 0x27, 0xb0, 0x0f, 0xe8, 0x82,
+ 0x27, 0xb0, 0x12, 0xe8, 0x84, 0x27, 0xc6, 0x06,
+ 0xe6, 0x1c, 0xd9, 0xc6, 0x06, 0x35, 0x33, 0x14,
+ 0xc6, 0x06, 0x36, 0x33, 0x25, 0xb8, 0xce, 0x3a,
+ 0xa3, 0x37, 0x33, 0xb8, 0x26, 0x0f, 0xa3, 0x39,
+ 0x33, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x6f, 0x02,
+ 0xb9, 0x6d, 0x02, 0xe8, 0xa9, 0x98, 0xc6, 0x06,
+ 0x35, 0x33, 0x01, 0xc6, 0x06, 0x36, 0x33, 0x09,
+ 0xb8, 0xe6, 0x3a, 0xa3, 0x37, 0x33, 0xb8, 0x1e,
+ 0x0f, 0xa3, 0x39, 0x33, 0xb9, 0x23, 0x00, 0xb0,
+ 0x01, 0xb4, 0x03, 0xe8, 0x17, 0x27, 0xbb, 0x47,
+ 0x33, 0xc7, 0x07, 0x70, 0x02, 0xb9, 0x6e, 0x02,
+ 0xe8, 0x7c, 0x98, 0xe8, 0x36, 0x98, 0xb8, 0x96,
+ 0x00, 0xe8, 0x3e, 0x9c, 0xbb, 0xfd, 0x3a, 0xe8,
+ 0x53, 0x1d, 0xb0, 0x2b, 0xe8, 0x41, 0xa4, 0xe8,
+ 0x3b, 0x1a, 0xc3, 0xbb, 0xa1, 0x46, 0xe8, 0x44,
+ 0x1d, 0xc3, 0xbb, 0x00, 0x30, 0xe8, 0xad, 0x8e,
+ 0xb9, 0x05, 0x00, 0xb0, 0x18, 0xb4, 0x03, 0xe8,
+ 0xdb, 0x26, 0xb9, 0x1a, 0x00, 0xb0, 0x20, 0xe8,
+ 0xdc, 0x26, 0xb9, 0x05, 0x00, 0xb0, 0x2a, 0xe8,
+ 0xdb, 0x26, 0xb9, 0x0f, 0x00, 0xb0, 0x4d, 0xe8,
+ 0xda, 0x26, 0xb0, 0x4f, 0xe8, 0xdc, 0x26, 0xb0,
+ 0x52, 0xe8, 0xde, 0x26, 0xb9, 0x16, 0x00, 0xb0,
+ 0x5b, 0xe8, 0xdd, 0x26, 0xb9, 0x16, 0x00, 0xb0,
+ 0x66, 0xe8, 0xdc, 0x26, 0xb9, 0x1a, 0x00, 0xb0,
+ 0x72, 0xe8, 0xdb, 0x26, 0xb9, 0x18, 0x00, 0xb0,
+ 0x7c, 0xe8, 0xda, 0x26, 0xb0, 0x1a, 0xb4, 0x01,
+ 0xe8, 0xa3, 0x9b, 0xbb, 0x47, 0x33, 0xc7, 0x07,
+ 0x33, 0x02, 0xb9, 0x32, 0x02, 0xe8, 0xa6, 0x97,
+ 0xb0, 0x06, 0xe8, 0x68, 0x96, 0xb0, 0x01, 0xb4,
+ 0x00, 0xe8, 0xf5, 0xaa, 0xe8, 0x09, 0xab, 0xbb,
+ 0x3f, 0x36, 0xe8, 0xc8, 0x1c, 0xb0, 0x1b, 0xe8,
+ 0xb6, 0xa3, 0xb0, 0x1c, 0xe8, 0xa1, 0xa3, 0xc3,
+ 0xbb, 0x13, 0x49, 0xe8, 0xb7, 0x1c, 0xc3, 0xb0,
+ 0x20, 0xe8, 0xa4, 0xa3, 0xb9, 0x25, 0x00, 0xb0,
+ 0x0e, 0xb4, 0x04, 0xe8, 0x4f, 0x26, 0xb9, 0x10,
+ 0x00, 0xb0, 0x11, 0xb4, 0x09, 0xe8, 0x4e, 0x26,
+ 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x02, 0x35, 0x02,
+ 0xb9, 0x34, 0x02, 0xe8, 0x29, 0x97, 0xe8, 0x1f,
+ 0xbc, 0xc6, 0x07, 0x18, 0xe8, 0x5a, 0x2a, 0xe8,
+ 0xcc, 0x26, 0xb9, 0x27, 0x00, 0xb0, 0x05, 0xb4,
+ 0x00, 0xe8, 0x21, 0x26, 0xb9, 0x46, 0x02, 0xe8,
+ 0x10, 0x97, 0xe8, 0x47, 0x97, 0xbe, 0x3f, 0x00,
+ 0xbf, 0xc3, 0x00, 0xc6, 0x06, 0xc3, 0x64, 0x01,
+ 0xe8, 0x38, 0xb2, 0xbb, 0x47, 0x33, 0xc7, 0x47,
+ 0x02, 0x3b, 0x02, 0xb0, 0x02, 0xe8, 0x20, 0x96,
+ 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x02, 0x3c, 0x02,
+ 0xb0, 0x02, 0xe8, 0x13, 0x96, 0xbb, 0x47, 0x33,
+ 0xc7, 0x47, 0x02, 0x3d, 0x02, 0xb0, 0x02, 0xe8,
+ 0x06, 0x96, 0xb9, 0x28, 0x00, 0xb0, 0x01, 0xb4,
+ 0x08, 0xe8, 0xd9, 0x25, 0xb0, 0x03, 0xe8, 0xdd,
+ 0x25, 0xb0, 0x05, 0xe8, 0xdf, 0x25, 0xb0, 0x07,
+ 0xe8, 0xe1, 0x25, 0xbb, 0x47, 0x33, 0xc7, 0x47,
+ 0x02, 0x3e, 0x02, 0xb0, 0x02, 0xe8, 0xe0, 0x95,
+ 0xb0, 0x01, 0xb4, 0x00, 0xe8, 0x32, 0xaa, 0xe8,
+ 0x46, 0xaa, 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x02,
+ 0x3f, 0x02, 0xb0, 0x02, 0xe8, 0xc9, 0x95, 0xbb,
+ 0x47, 0x33, 0xc7, 0x47, 0x02, 0x40, 0x02, 0xb0,
+ 0x02, 0xe8, 0xbc, 0x95, 0xbb, 0x47, 0x33, 0xc7,
+ 0x47, 0x02, 0x41, 0x02, 0xb0, 0x02, 0xe8, 0xaf,
+ 0x95, 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x02, 0x42,
+ 0x02, 0xb0, 0x02, 0xe8, 0xa2, 0x95, 0xbb, 0x47,
+ 0x33, 0xc7, 0x47, 0x02, 0x43, 0x02, 0xb0, 0x02,
+ 0xe8, 0x95, 0x95, 0xbb, 0x47, 0x33, 0xc7, 0x47,
+ 0x02, 0x44, 0x02, 0xb0, 0x02, 0xe8, 0x88, 0x95,
+ 0xb9, 0x37, 0x00, 0xb0, 0x12, 0xb4, 0x01, 0xe8,
+ 0x5b, 0x25, 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x02,
+ 0x45, 0x02, 0xb0, 0x02, 0xe8, 0x71, 0x95, 0xe8,
+ 0xec, 0x25, 0xc6, 0x06, 0x33, 0x33, 0x01, 0xc6,
+ 0x06, 0xdd, 0x1c, 0x02, 0xb0, 0x02, 0xe8, 0x24,
+ 0x95, 0xc6, 0x06, 0x9f, 0xdb, 0x01, 0xc3, 0xb9,
+ 0x14, 0x00, 0xb0, 0x09, 0xb4, 0x06, 0xe8, 0x2c,
+ 0x25, 0xb9, 0x12, 0x02, 0xe8, 0x18, 0x96, 0xe8,
+ 0xb9, 0x26, 0xc7, 0x06, 0xf3, 0xb4, 0x10, 0x00,
+ 0xc6, 0x06, 0xdc, 0x1c, 0x01, 0xe8, 0x3f, 0x27,
+ 0xb9, 0x13, 0x02, 0xc6, 0x06, 0xdc, 0x1c, 0x01,
+ 0xe8, 0xfc, 0x95, 0xb9, 0x24, 0x00, 0xb0, 0x04,
+ 0xb4, 0x0c, 0xe8, 0x00, 0x25, 0xb9, 0x14, 0x02,
+ 0xe8, 0xef, 0x95, 0xb9, 0x15, 0x02, 0xe8, 0xe9,
+ 0x95, 0xe8, 0xdc, 0xba, 0xb0, 0x09, 0x88, 0x07,
+ 0xe8, 0x0e, 0x2a, 0xc7, 0x06, 0xaf, 0x64, 0xec,
+ 0x00, 0xc7, 0x06, 0xb1, 0x64, 0x5f, 0x00, 0xc6,
+ 0x06, 0xc3, 0x64, 0x01, 0xc6, 0x06, 0xcb, 0x64,
+ 0x01, 0xc6, 0x06, 0xcd, 0x64, 0x00, 0xe8, 0xfb,
+ 0x95, 0xb9, 0x09, 0x00, 0xe8, 0x14, 0x2c, 0xc3,
+ 0xbb, 0x46, 0x67, 0xe8, 0x9c, 0xba, 0x83, 0xc3,
+ 0x03, 0xff, 0x37, 0x53, 0xc7, 0x07, 0x3f, 0x01,
+ 0xbe, 0xec, 0x00, 0xbf, 0xbe, 0x00, 0xe8, 0xda,
+ 0xb0, 0xb9, 0x05, 0x00, 0xb0, 0x04, 0xb4, 0x0b,
+ 0xe8, 0xa2, 0x24, 0xb9, 0x0e, 0x00, 0xb0, 0x0e,
+ 0xe8, 0xa3, 0x24, 0xb0, 0x21, 0xe8, 0xa5, 0x24,
+ 0xb9, 0x05, 0x00, 0xb0, 0x2b, 0xe8, 0xa4, 0x24,
+ 0xe8, 0xe4, 0x95, 0xe8, 0x72, 0xba, 0x53, 0xc6,
+ 0x47, 0x02, 0x00, 0xe8, 0xf6, 0x28, 0xe8, 0x30,
+ 0x00, 0xb9, 0x83, 0x02, 0xe8, 0x6b, 0x95, 0x5b,
+ 0xc6, 0x47, 0x02, 0x2b, 0xe8, 0xa1, 0x28, 0xe8,
+ 0x32, 0x00, 0xe8, 0x97, 0x95, 0xbe, 0xec, 0x00,
+ 0xbf, 0xb3, 0x00, 0xc6, 0x06, 0xc3, 0x64, 0x03,
+ 0xe8, 0x88, 0xb0, 0x5b, 0x8f, 0x07, 0xb0, 0x2c,
+ 0xe8, 0x9d, 0xa1, 0xb0, 0x2e, 0xe8, 0x88, 0xa1,
+ 0xc3, 0x1e, 0xa1, 0xb5, 0x32, 0x8e, 0xd8, 0x33,
+ 0xdb, 0x8a, 0x07, 0xc6, 0x07, 0x00, 0x1f, 0x2e,
+ 0xa2, 0xd5, 0x85, 0xc3, 0x2e, 0xa0, 0xd5, 0x85,
+ 0x1e, 0x8b, 0x1e, 0xb5, 0x32, 0x8e, 0xdb, 0x33,
+ 0xdb, 0x88, 0x07, 0x1f, 0xc3, 0x00, 0xbb, 0xbf,
+ 0x48, 0xe8, 0x79, 0x1a, 0xc3, 0xbb, 0xd6, 0x48,
+ 0xe8, 0x72, 0x1a, 0xc3, 0xbb, 0x5c, 0x49, 0xe8,
+ 0x6b, 0x1a, 0xc3, 0x80, 0x3e, 0xb0, 0xdb, 0x01,
+ 0x74, 0x07, 0xbb, 0x86, 0x3d, 0xe8, 0x5d, 0x1a,
+ 0xc3, 0xb0, 0x06, 0xe8, 0xdb, 0x93, 0xb9, 0x19,
+ 0x00, 0xb0, 0x0a, 0xb4, 0x0a, 0xe8, 0xf5, 0x23,
+ 0xb0, 0x0e, 0xe8, 0xf9, 0x23, 0xb0, 0x12, 0xe8,
+ 0xfb, 0x23, 0xb9, 0x2f, 0x02, 0xe8, 0xe7, 0x94,
+ 0xe8, 0xcd, 0xb9, 0xb0, 0x17, 0x88, 0x47, 0x01,
+ 0xe8, 0xfe, 0x28, 0xe8, 0x06, 0x95, 0xc6, 0x06,
+ 0xb0, 0xdb, 0x02, 0xc3, 0xbb, 0x57, 0x34, 0x80,
+ 0x3e, 0xb0, 0xdb, 0x01, 0x75, 0x03, 0xbb, 0x82,
+ 0x48, 0xe8, 0x19, 0x1a, 0xc3, 0xb9, 0x0c, 0x00,
+ 0xb0, 0x04, 0xb4, 0x08, 0xe8, 0xb6, 0x23, 0xb9,
+ 0x32, 0x00, 0xb0, 0x14, 0xe8, 0xb7, 0x23, 0xb0,
+ 0x1d, 0xe8, 0xb9, 0x23, 0xb9, 0x2a, 0x02, 0xe8,
+ 0xb6, 0x94, 0xb0, 0x13, 0xe8, 0xe9, 0xa0, 0xb0,
+ 0x16, 0xe8, 0xd4, 0xa0, 0xc3, 0xb9, 0x05, 0x00,
+ 0xb0, 0x03, 0xb4, 0x0c, 0xe8, 0x8e, 0x23, 0xb9,
+ 0x38, 0x00, 0xb0, 0x0c, 0xe8, 0x8f, 0x23, 0xb0,
+ 0x0e, 0xe8, 0x91, 0x23, 0xb0, 0x10, 0xe8, 0x93,
+ 0x23, 0xb0, 0x12, 0xe8, 0x95, 0x23, 0xb0, 0x16,
+ 0xe8, 0x97, 0x23, 0xb0, 0x18, 0xe8, 0x99, 0x23,
+ 0xb9, 0x05, 0x00, 0xb0, 0x1c, 0xe8, 0x98, 0x23,
+ 0xb9, 0x37, 0x02, 0xe8, 0x72, 0x94, 0xb0, 0x0c,
+ 0xe8, 0xa5, 0xa0, 0xb0, 0x21, 0xe8, 0x90, 0xa0,
+ 0xc3, 0x80, 0x3e, 0x92, 0xdb, 0x01, 0x75, 0x07,
+ 0xbb, 0x40, 0x3d, 0xe8, 0x9f, 0x19, 0xc3, 0xc6,
+ 0x06, 0x92, 0xdb, 0x01, 0xe8, 0x44, 0x91, 0xbb,
+ 0xcd, 0x0f, 0xe8, 0x00, 0x8b, 0xc6, 0x06, 0xe6,
+ 0x1c, 0xd1, 0xb8, 0x07, 0x01, 0xe8, 0x3e, 0x98,
+ 0xb9, 0x05, 0x00, 0xb0, 0x10, 0xb4, 0x06, 0xe8,
+ 0x23, 0x23, 0xb9, 0x01, 0x00, 0xb0, 0x19, 0xe8,
+ 0x24, 0x23, 0xb0, 0x1d, 0xe8, 0x26, 0x23, 0xb0,
+ 0x22, 0xe8, 0x28, 0x23, 0xc6, 0x06, 0xdc, 0x64,
+ 0x00, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0xfa, 0x01,
+ 0xb9, 0xf8, 0x01, 0xe8, 0xf4, 0x93, 0xe8, 0xe7,
+ 0xb8, 0xc6, 0x07, 0x00, 0xe8, 0x29, 0x27, 0xc7,
+ 0x06, 0x30, 0x32, 0x00, 0x00, 0xc7, 0x06, 0x2e,
+ 0x32, 0x72, 0x00, 0xc7, 0x06, 0x2c, 0x32, 0xae,
+ 0x00, 0xb9, 0x18, 0x00, 0xb0, 0x02, 0xb4, 0x06,
+ 0xe8, 0xda, 0x22, 0xb9, 0x16, 0x00, 0xb0, 0x18,
+ 0xe8, 0xdb, 0x22, 0xb9, 0x01, 0x00, 0xb0, 0x1c,
+ 0xe8, 0xda, 0x22, 0xb0, 0x20, 0xe8, 0xdc, 0x22,
+ 0xb0, 0x25, 0xe8, 0xde, 0x22, 0xb9, 0x05, 0x00,
+ 0xb0, 0x2b, 0xe8, 0xdd, 0x22, 0xb9, 0x3d, 0x00,
+ 0xb0, 0x46, 0xe8, 0xdc, 0x22, 0xb9, 0x3d, 0x00,
+ 0xb0, 0x5b, 0xe8, 0xdb, 0x22, 0xc6, 0x06, 0x35,
+ 0x33, 0x06, 0xc6, 0x06, 0x36, 0x33, 0x11, 0xb8,
+ 0xfb, 0x3c, 0xa3, 0x37, 0x33, 0xb8, 0xcd, 0x70,
+ 0xa3, 0x39, 0x33, 0xbb, 0x47, 0x33, 0xc7, 0x07,
+ 0xfb, 0x01, 0xb9, 0xf9, 0x01, 0xe8, 0xf7, 0x93,
+ 0xe8, 0x6d, 0xb8, 0xb0, 0x04, 0x88, 0x07, 0xe8,
+ 0x9f, 0x27, 0xb8, 0x03, 0x00, 0xe8, 0xbd, 0x1c,
+ 0xb8, 0x14, 0x00, 0x01, 0x47, 0x03, 0x01, 0x47,
+ 0x07, 0xc6, 0x06, 0xcd, 0x64, 0x00, 0xc6, 0x06,
+ 0xcc, 0x64, 0x01, 0xc6, 0x06, 0xcb, 0x64, 0x01,
+ 0xff, 0x06, 0xaf, 0x64, 0xe8, 0xec, 0x23, 0xe8,
+ 0xcf, 0xb6, 0xb9, 0x0a, 0x00, 0xb0, 0x03, 0xb4,
+ 0x02, 0xe8, 0x49, 0x22, 0xbb, 0x47, 0x33, 0xc7,
+ 0x07, 0xf7, 0x01, 0xb0, 0x01, 0xe8, 0x60, 0x92,
+ 0xe8, 0xdb, 0x22, 0xc7, 0x06, 0xf3, 0xb4, 0x16,
+ 0x00, 0xb8, 0x01, 0x00, 0xe8, 0xaa, 0xa6, 0xb0,
+ 0x01, 0xe8, 0x11, 0x92, 0xc7, 0x06, 0xf3, 0xb4,
+ 0x14, 0x00, 0xb0, 0x0d, 0xe8, 0x06, 0x92, 0xb8,
+ 0x01, 0x00, 0xe8, 0x94, 0xa6, 0xe8, 0xa8, 0xa6,
+ 0xb0, 0x01, 0xe8, 0xf8, 0x91, 0xb0, 0x02, 0xe8,
+ 0xf3, 0x91, 0xb0, 0x0e, 0xe8, 0xee, 0x91, 0xb0,
+ 0x0f, 0xe8, 0xe9, 0x91, 0xb0, 0x10, 0xe8, 0xe4,
+ 0x91, 0xe8, 0x41, 0x14, 0xb8, 0x32, 0x00, 0xe8,
+ 0x52, 0x97, 0xe8, 0x47, 0x14, 0xbe, 0xa2, 0x00,
+ 0xbf, 0xa4, 0x00, 0xc6, 0x06, 0xc3, 0x64, 0x02,
+ 0xe8, 0x10, 0xae, 0xc6, 0x06, 0xe6, 0x1c, 0xe5,
+ 0xbb, 0x01, 0x3d, 0xbe, 0x46, 0x5f, 0xe8, 0xd5,
+ 0x1a, 0xc6, 0x06, 0xe6, 0x1c, 0xd8, 0xbb, 0x20,
+ 0x3d, 0xbe, 0x5a, 0x5f, 0xe8, 0xc7, 0x1a, 0xbe,
+ 0xa2, 0x00, 0xbf, 0xbf, 0x00, 0xc6, 0x06, 0xc3,
+ 0x64, 0x02, 0xe8, 0xe6, 0xad, 0xe8, 0xfd, 0x13,
+ 0xb8, 0x32, 0x00, 0xe8, 0x0e, 0x97, 0xe8, 0x97,
+ 0xb7, 0x32, 0xc0, 0x88, 0x47, 0x01, 0x88, 0x47,
+ 0x02, 0x88, 0x47, 0x03, 0x88, 0x47, 0x04, 0xc6,
+ 0x06, 0xdc, 0x1c, 0x03, 0xe8, 0x0d, 0x26, 0xbb,
+ 0x46, 0x67, 0xe8, 0x6d, 0xb7, 0x43, 0x33, 0xc0,
+ 0x89, 0x47, 0x02, 0x89, 0x47, 0x04, 0x89, 0x47,
+ 0x06, 0x89, 0x47, 0x08, 0xb9, 0x3e, 0x00, 0xb0,
+ 0x01, 0xb4, 0x0e, 0xe8, 0x77, 0x21, 0xb9, 0x09,
+ 0x00, 0xb0, 0x08, 0xe8, 0x78, 0x21, 0xe8, 0xc3,
+ 0x13, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x00, 0x02,
+ 0xb0, 0x01, 0xe8, 0x83, 0x91, 0xe8, 0x4c, 0x22,
+ 0xb0, 0x01, 0xb4, 0x00, 0xe8, 0xd2, 0xa5, 0xe8,
+ 0xe6, 0xa5, 0xe8, 0xa8, 0x96, 0xbb, 0x3a, 0x3d,
+ 0xe8, 0xa2, 0x17, 0xb0, 0x07, 0xb4, 0x01, 0xb9,
+ 0xe4, 0x00, 0xba, 0xab, 0x00, 0xe8, 0x45, 0x91,
+ 0xb0, 0x08, 0xb9, 0x22, 0x01, 0xe8, 0x3d, 0x91,
+ 0xc3, 0x80, 0x3e, 0x9a, 0xdb, 0x01, 0x74, 0x3b,
+ 0xe8, 0x0b, 0x00, 0xb0, 0x0a, 0xe8, 0x70, 0x9e,
+ 0xc6, 0x06, 0x9a, 0xdb, 0x01, 0xc3, 0xe8, 0xdc,
+ 0x8e, 0xbb, 0x5f, 0x1b, 0xe8, 0xde, 0x88, 0xb9,
+ 0x05, 0x00, 0xb0, 0x02, 0xb4, 0x03, 0xe8, 0x0c,
+ 0x21, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x1a, 0x02,
+ 0xb9, 0x19, 0x02, 0xe8, 0x27, 0x92, 0xe8, 0x54,
+ 0x96, 0xe8, 0xb9, 0x8e, 0xbb, 0xe0, 0x1b, 0xe8,
+ 0xbb, 0x88, 0xc3, 0xe8, 0xaf, 0x8e, 0xbb, 0xf0,
+ 0xda, 0xe8, 0x99, 0x88, 0xe8, 0xae, 0x88, 0xc3,
+ 0x80, 0x3e, 0x9a, 0xdb, 0x01, 0x74, 0xec, 0xe8,
+ 0xbc, 0xff, 0xb0, 0x0b, 0xe8, 0x21, 0x9e, 0xc6,
+ 0x06, 0x9a, 0xdb, 0x01, 0xc3, 0x80, 0x3e, 0x9b,
+ 0xdb, 0x01, 0x74, 0x76, 0xe8, 0x0b, 0x00, 0xb0,
+ 0x0a, 0xe8, 0x0c, 0x9e, 0xc6, 0x06, 0x9b, 0xdb,
+ 0x01, 0xc3, 0xe8, 0x27, 0x8f, 0xbb, 0x93, 0x22,
+ 0xe8, 0x7a, 0x88, 0xb9, 0x05, 0x00, 0xb0, 0x0a,
+ 0xb4, 0x03, 0xe8, 0xa8, 0x20, 0xbb, 0x47, 0x33,
+ 0xc7, 0x47, 0x02, 0x1b, 0x02, 0xb9, 0x1c, 0x02,
+ 0xe8, 0xc2, 0x91, 0xb8, 0x64, 0x00, 0xe8, 0xd1,
+ 0x95, 0xe8, 0x00, 0x8f, 0xbb, 0xb1, 0x24, 0xe8,
+ 0x53, 0x88, 0xe8, 0xd9, 0x95, 0xe8, 0x45, 0x8e,
+ 0xbb, 0xd7, 0x24, 0xe8, 0x47, 0x88, 0xe8, 0xeb,
+ 0x8e, 0xbb, 0x14, 0x25, 0xe8, 0x3e, 0x88, 0xe8,
+ 0xc4, 0x95, 0x8b, 0x3e, 0xb1, 0x64, 0x8b, 0x36,
+ 0xaf, 0x64, 0x57, 0x56, 0x47, 0xe8, 0x93, 0xac,
+ 0xe8, 0xb3, 0x95, 0xbb, 0x70, 0x25, 0xe8, 0x24,
+ 0x88, 0xe8, 0xaa, 0x95, 0x5e, 0x5f, 0xe8, 0x82,
+ 0xac, 0xc3, 0xe8, 0xbf, 0x8e, 0xbb, 0x02, 0xdb,
+ 0xe8, 0xfa, 0x87, 0xe8, 0x0f, 0x88, 0xc3, 0x80,
+ 0x3e, 0x9b, 0xdb, 0x01, 0x74, 0xec, 0xe8, 0x81,
+ 0xff, 0xb0, 0x0b, 0xe8, 0x82, 0x9d, 0xc6, 0x06,
+ 0x9b, 0xdb, 0x01, 0xc3, 0xb0, 0x17, 0xe8, 0x77,
+ 0x9d, 0xe8, 0x98, 0x8e, 0xbb, 0x34, 0x26, 0xe8,
+ 0xeb, 0x87, 0xb9, 0x05, 0x00, 0xb0, 0x06, 0xb4,
+ 0x0c, 0xe8, 0x19, 0x20, 0xbb, 0x47, 0x33, 0xc7,
+ 0x47, 0x02, 0x2c, 0x02, 0xb9, 0x2b, 0x02, 0xe8,
+ 0x33, 0x91, 0xe8, 0x77, 0x8e, 0xbb, 0x0a, 0x28,
+ 0xe8, 0xca, 0x87, 0xb9, 0x05, 0x00, 0xb0, 0x0a,
+ 0xb4, 0x0c, 0xe8, 0xf8, 0x1f, 0xbb, 0x47, 0x33,
+ 0xc7, 0x47, 0x02, 0x2e, 0x02, 0xb9, 0x2d, 0x02,
+ 0xe8, 0x12, 0x91, 0xe8, 0x56, 0x8e, 0xbb, 0x71,
+ 0x29, 0xe8, 0xa9, 0x87, 0xb0, 0x18, 0xe8, 0x17,
+ 0x9d, 0xc3, 0xb9, 0x2d, 0x00, 0xb0, 0x10, 0xb4,
+ 0x06, 0xe8, 0xd1, 0x1f, 0xe8, 0x28, 0x91, 0xe8,
+ 0x7f, 0xfb, 0xb9, 0x30, 0x02, 0xe8, 0xba, 0x90,
+ 0xe8, 0x89, 0xfb, 0xe8, 0xee, 0x90, 0xb0, 0x1a,
+ 0xe8, 0x05, 0x9d, 0xb0, 0x1b, 0xe8, 0xf0, 0x9c,
+ 0xe8, 0x03, 0x95, 0xe8, 0x6f, 0x8d, 0xbb, 0xcd,
+ 0x1e, 0xe8, 0x71, 0x87, 0x8b, 0x3e, 0xb1, 0x64,
+ 0x8b, 0x36, 0xaf, 0x64, 0x4e, 0xe8, 0xcb, 0xab,
+ 0xe8, 0x5a, 0x8d, 0xbb, 0x09, 0x1f, 0xe8, 0x5c,
+ 0x87, 0xc6, 0x06, 0xb1, 0xdb, 0x01, 0xc3, 0x80,
+ 0x3e, 0xb5, 0xdb, 0x01, 0x74, 0x07, 0xbb, 0x29,
+ 0x4a, 0xe8, 0xd9, 0x15, 0xc3, 0xe8, 0xec, 0x8d,
+ 0xbb, 0x92, 0x29, 0xe8, 0x3f, 0x87, 0xb9, 0x05,
+ 0x00, 0xb0, 0x03, 0xb4, 0x0e, 0xe8, 0x6d, 0x1f,
+ 0xb0, 0x14, 0xe8, 0x71, 0x1f, 0xbb, 0x47, 0x33,
+ 0xc7, 0x47, 0x02, 0x9f, 0x02, 0xb9, 0x9e, 0x02,
+ 0xe8, 0x5f, 0x90, 0xe8, 0xed, 0x20, 0xe8, 0xcb,
+ 0x00, 0xe8, 0xe4, 0x8d, 0xbb, 0x00, 0x2a, 0xe8,
+ 0x13, 0x87, 0xe8, 0xbf, 0x00, 0xc6, 0x06, 0xe6,
+ 0x1c, 0xe5, 0xc6, 0x06, 0x35, 0x33, 0x17, 0xc6,
+ 0x06, 0x36, 0x33, 0x26, 0xb8, 0x5b, 0x4a, 0xa3,
+ 0x37, 0x33, 0xb8, 0x4c, 0x8f, 0xa3, 0x39, 0x33,
+ 0xb9, 0x53, 0x00, 0xb0, 0x0c, 0xb4, 0x0c, 0xe8,
+ 0x23, 0x1f, 0xc6, 0x06, 0xdc, 0x64, 0x00, 0xb9,
+ 0xa1, 0x02, 0xe8, 0x8a, 0x90, 0xe8, 0xab, 0x20,
+ 0xe8, 0x01, 0x20, 0xc7, 0x06, 0xf3, 0xb4, 0x0b,
+ 0x00, 0xc6, 0x06, 0xdc, 0x1c, 0x01, 0xe8, 0x2e,
+ 0x21, 0xb9, 0x18, 0x00, 0xb0, 0x1f, 0xb4, 0x09,
+ 0xe8, 0xfa, 0x1e, 0xb0, 0x30, 0xe8, 0xfe, 0x1e,
+ 0xb9, 0x4f, 0x00, 0xb0, 0x32, 0xb4, 0x0c, 0xe8,
+ 0xfb, 0x1e, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0xa3,
+ 0x02, 0xb9, 0xa2, 0x02, 0xc6, 0x06, 0xdc, 0x1c,
+ 0x01, 0xe8, 0xce, 0x8f, 0xe8, 0x6c, 0x20, 0xe8,
+ 0xc2, 0x1f, 0xc7, 0x06, 0xf3, 0xb4, 0x1c, 0x00,
+ 0xc6, 0x06, 0xdc, 0x1c, 0x01, 0xe8, 0xef, 0x20,
+ 0xc7, 0x06, 0xaf, 0x64, 0x00, 0x00, 0xc7, 0x06,
+ 0xb1, 0x64, 0xa7, 0x00, 0xc6, 0x06, 0xc3, 0x64,
+ 0x02, 0xc6, 0x06, 0xcb, 0x64, 0x00, 0xc6, 0x06,
+ 0xcd, 0x64, 0x00, 0xe8, 0xd6, 0x8f, 0xbe, 0x42,
+ 0x00, 0xbf, 0xa7, 0x00, 0xe8, 0xcc, 0xaa, 0xbb,
+ 0x6f, 0x4a, 0xe8, 0xf0, 0x14, 0xe8, 0x16, 0x9c,
+ 0xb0, 0x1d, 0xe8, 0xcb, 0x9b, 0xb9, 0x0a, 0x00,
+ 0xe8, 0xd8, 0x25, 0xc3, 0xbb, 0x47, 0x33, 0xc7,
+ 0x47, 0x02, 0xa0, 0x02, 0xb0, 0x02, 0xe8, 0xa6,
+ 0x8e, 0xc3, 0xe8, 0xd2, 0x8f, 0xe8, 0x60, 0xb4,
+ 0xc6, 0x07, 0x00, 0xe8, 0xe6, 0x22, 0xb9, 0x05,
+ 0x00, 0xb0, 0x03, 0xb4, 0x05, 0xe8, 0x65, 0x1e,
+ 0xb0, 0x06, 0xe8, 0x69, 0x1e, 0xb0, 0x0a, 0xe8,
+ 0x6b, 0x1e, 0xb9, 0x5c, 0x00, 0xb0, 0x14, 0xe8,
+ 0x6a, 0x1e, 0xb0, 0x26, 0xe8, 0x6c, 0x1e, 0xb0,
+ 0x3a, 0xe8, 0x6e, 0x1e, 0xc6, 0x06, 0x35, 0x33,
+ 0x3a, 0xc6, 0x06, 0x36, 0x33, 0x43, 0xb8, 0x4a,
+ 0x46, 0xa3, 0x37, 0x33, 0xb8, 0x9e, 0x8e, 0xa3,
+ 0x39, 0x33, 0xc6, 0x06, 0xdc, 0x64, 0x00, 0xb9,
+ 0x5a, 0x02, 0xe8, 0x9a, 0x8f, 0xc6, 0x06, 0xdc,
+ 0x64, 0x01, 0xb9, 0x05, 0x00, 0xb0, 0x03, 0xb4,
+ 0x04, 0xe8, 0x19, 0x1e, 0xb9, 0x5b, 0x02, 0xe8,
+ 0x18, 0x8f, 0xe8, 0xfb, 0xb3, 0xc6, 0x07, 0x1b,
+ 0xe8, 0x3d, 0x22, 0xe8, 0x36, 0x8f, 0xc6, 0x06,
+ 0xa5, 0xdb, 0x01, 0xc3, 0xbb, 0x31, 0x3c, 0xe8,
+ 0x53, 0x14, 0xb9, 0x05, 0x00, 0xb0, 0x03, 0xb4,
+ 0x0a, 0xe8, 0xf1, 0x1d, 0xb9, 0x1a, 0x00, 0xb0,
+ 0x0d, 0xe8, 0xf2, 0x1d, 0xbb, 0x47, 0x33, 0xc7,
+ 0x07, 0x92, 0x02, 0xb9, 0x91, 0x02, 0xe8, 0xce,
+ 0x8e, 0xe8, 0x6f, 0x1f, 0xbb, 0x47, 0x33, 0xc7,
+ 0x07, 0x93, 0x02, 0xb0, 0x01, 0xe8, 0xf7, 0x8d,
+ 0xe8, 0xb9, 0x1e, 0xe8, 0x1f, 0x93, 0xbb, 0x3d,
+ 0x3c, 0xe8, 0x19, 0x14, 0xb0, 0x24, 0xe8, 0x07,
+ 0x9b, 0xb0, 0x09, 0xe8, 0x1c, 0x00, 0xb0, 0x07,
+ 0xe8, 0x17, 0x00, 0xbb, 0x46, 0x67, 0xe8, 0x89,
+ 0xb3, 0x43, 0xc7, 0x47, 0x06, 0x0a, 0x01, 0xc7,
+ 0x47, 0x08, 0xc1, 0x00, 0xc6, 0x06, 0xad, 0xdb,
+ 0x01, 0xc3, 0xb4, 0x01, 0xb9, 0x29, 0x01, 0xba,
+ 0xb5, 0x00, 0xe8, 0x98, 0x8d, 0xc3, 0xb9, 0x05,
+ 0x00, 0xb0, 0x03, 0xb4, 0x09, 0xe8, 0x85, 0x1d,
+ 0xb9, 0x1a, 0x00, 0xb0, 0x0d, 0xe8, 0x86, 0x1d,
+ 0xb9, 0x18, 0x00, 0xb0, 0x16, 0xe8, 0x85, 0x1d,
+ 0xb9, 0x50, 0x02, 0xe8, 0x71, 0x8e, 0xe8, 0x57,
+ 0xb3, 0xc6, 0x07, 0x00, 0xe8, 0x99, 0x21, 0xb9,
+ 0x01, 0x00, 0xb0, 0x05, 0xb4, 0x09, 0xe8, 0x5c,
+ 0x1d, 0xb0, 0x09, 0xe8, 0x60, 0x1d, 0xb0, 0x0d,
+ 0xe8, 0x62, 0x1d, 0xb9, 0x51, 0x02, 0xe8, 0x51,
+ 0x8e, 0xe8, 0x34, 0xb3, 0xc6, 0x07, 0x1c, 0xe8,
+ 0x76, 0x21, 0xe8, 0x6f, 0x8e, 0xb0, 0x23, 0xe8,
+ 0x86, 0x9a, 0xb0, 0x01, 0xe8, 0x12, 0x8d, 0xc3,
+ 0xb9, 0x05, 0x00, 0xb0, 0x03, 0xb4, 0x09, 0xe8,
+ 0x2b, 0x1d, 0xb9, 0x84, 0x02, 0xe8, 0x27, 0x8e,
+ 0xe8, 0x0d, 0xb3, 0xc6, 0x47, 0x01, 0x2d, 0xe8,
+ 0x4e, 0x21, 0xb9, 0x38, 0x00, 0xb0, 0x02, 0xb4,
+ 0x08, 0xe8, 0x11, 0x1d, 0xb9, 0x1a, 0x00, 0xb0,
+ 0x04, 0xe8, 0x12, 0x1d, 0xb9, 0x85, 0x02, 0xe8,
+ 0x08, 0x8e, 0xb9, 0x38, 0x00, 0xb0, 0x01, 0xb4,
+ 0x08, 0xe8, 0xf9, 0x1c, 0xb0, 0x06, 0xe8, 0x04,
+ 0x1d, 0xb9, 0x1a, 0x00, 0xb0, 0x03, 0xe8, 0xf5,
+ 0x1c, 0xb0, 0x08, 0xe8, 0xfe, 0x1c, 0xb9, 0x86,
+ 0x02, 0xe8, 0xe6, 0x8d, 0xb9, 0x05, 0x00, 0xb0,
+ 0x15, 0xb4, 0x09, 0xe8, 0xd7, 0x1c, 0xb9, 0x87,
+ 0x02, 0xe8, 0xf9, 0x8d, 0xb0, 0x02, 0xe8, 0xb4,
+ 0x8c, 0xb8, 0x03, 0x00, 0xe8, 0x0e, 0x17, 0xc7,
+ 0x47, 0x0d, 0x9c, 0x00, 0xc6, 0x06, 0xac, 0xdb,
+ 0x01, 0xc3, 0xbb, 0x0b, 0x5e, 0xe8, 0x0d, 0x13,
+ 0xc3, 0xbb, 0xa1, 0x46, 0xe8, 0x06, 0x13, 0xc3,
+ 0xbb, 0xc3, 0x46, 0xe8, 0xff, 0x12, 0xc3, 0xb9,
+ 0x05, 0x00, 0xb0, 0x02, 0xb4, 0x07, 0xe8, 0x9c,
+ 0x1c, 0xb9, 0x0f, 0x00, 0xb0, 0x0c, 0xe8, 0x9d,
+ 0x1c, 0xb9, 0x7e, 0x02, 0xe8, 0xa1, 0x8d, 0xb0,
+ 0x30, 0xe8, 0xd4, 0x99, 0xe8, 0x0d, 0x91, 0x72,
+ 0x1e, 0xb0, 0x30, 0xe8, 0xba, 0x99, 0xb9, 0x18,
+ 0x00, 0xb0, 0x1a, 0xb4, 0x07, 0xe8, 0x75, 0x1c,
+ 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x04, 0x8b, 0x02,
+ 0xb9, 0x8a, 0x02, 0xe8, 0x7a, 0x8d, 0xc3, 0xa1,
+ 0x1f, 0xc4, 0xe8, 0xc7, 0x9a, 0x3c, 0x31, 0x75,
+ 0xd8, 0x83, 0x3e, 0x52, 0x72, 0x05, 0x75, 0xd1,
+ 0xc6, 0x06, 0xcf, 0x00, 0x00, 0xb9, 0x05, 0x00,
+ 0xb0, 0x02, 0xb4, 0x07, 0xe8, 0x46, 0x1c, 0xb9,
+ 0x34, 0x00, 0xb0, 0x0d, 0xe8, 0x47, 0x1c, 0xb9,
+ 0x88, 0x02, 0xe8, 0x2a, 0x8d, 0xe8, 0x20, 0xb2,
+ 0xc6, 0x47, 0x01, 0x2e, 0xe8, 0x61, 0x20, 0xe8,
+ 0x5a, 0x8d, 0xb0, 0x31, 0xe8, 0x71, 0x99, 0xe8,
+ 0xaa, 0x90, 0x73, 0x03, 0xe9, 0x91, 0x00, 0xb9,
+ 0x1b, 0x00, 0xb0, 0x05, 0xb4, 0x07, 0xe8, 0x14,
+ 0x1c, 0xe8, 0xfc, 0xb1, 0xc6, 0x47, 0x01, 0x00,
+ 0xe8, 0x81, 0x20, 0xb9, 0x8c, 0x02, 0xe8, 0xf9,
+ 0x8c, 0xb9, 0x18, 0x00, 0xb0, 0x04, 0xb4, 0x07,
+ 0xe8, 0xfa, 0x1b, 0xb9, 0x05, 0x00, 0xb0, 0x0c,
+ 0xe8, 0xfb, 0x1b, 0xc7, 0x06, 0xaf, 0x64, 0xbb,
+ 0x00, 0xc7, 0x06, 0xb1, 0x64, 0xb3, 0x00, 0xc6,
+ 0x06, 0xcc, 0x64, 0x01, 0xc6, 0x06, 0xcb, 0x64,
+ 0x00, 0xc6, 0x06, 0xdc, 0x64, 0x00, 0xb9, 0x8d,
+ 0x02, 0xe8, 0xc6, 0x8c, 0xbb, 0x47, 0x33, 0xc7,
+ 0x47, 0x04, 0x8f, 0x02, 0xb9, 0x8e, 0x02, 0xe8,
+ 0xdd, 0x8c, 0xff, 0x36, 0xcf, 0x00, 0xc6, 0x06,
+ 0xcf, 0x00, 0x00, 0xbb, 0xf6, 0x3b, 0xe8, 0x0c,
+ 0x12, 0x8f, 0x06, 0xcf, 0x00, 0xb0, 0x31, 0xe8,
+ 0xe6, 0x98, 0xc7, 0x06, 0xf3, 0xb4, 0x1b, 0x00,
+ 0xb0, 0x02, 0xb4, 0x04, 0xe8, 0x1a, 0xa0, 0xb0,
+ 0x04, 0xe8, 0x75, 0x8b, 0xc6, 0x06, 0xa9, 0xdb,
+ 0x00, 0xc7, 0x06, 0xf3, 0xb4, 0x1a, 0x00, 0xc3,
+ 0xa1, 0x1f, 0xc4, 0xe8, 0xee, 0x99, 0x3c, 0x1d,
+ 0x74, 0x03, 0xe9, 0x62, 0xff, 0x83, 0x3e, 0x52,
+ 0x72, 0x05, 0x74, 0x03, 0xe9, 0x58, 0xff, 0xc6,
+ 0x06, 0xcf, 0x00, 0x00, 0xc7, 0x06, 0x1f, 0xc4,
+ 0x00, 0x00, 0xb9, 0x05, 0x00, 0xb0, 0x02, 0xb4,
+ 0x07, 0xe8, 0x61, 0x1b, 0xb9, 0x13, 0x00, 0xb0,
+ 0x0c, 0xe8, 0x62, 0x1b, 0xb9, 0x89, 0x02, 0xe8,
+ 0x48, 0x8c, 0xe8, 0x3b, 0xb1, 0xc6, 0x47, 0x01,
+ 0x2f, 0xe8, 0xc0, 0x1f, 0xe8, 0x75, 0x8c, 0xb8,
+ 0x2c, 0x01, 0xe8, 0x7d, 0x90, 0xb9, 0x44, 0x00,
+ 0xb0, 0x01, 0xb4, 0x0c, 0xe8, 0x36, 0x1b, 0xb0,
+ 0x05, 0xe8, 0x3a, 0x1b, 0xb0, 0x09, 0xe8, 0x3c,
+ 0x1b, 0xb0, 0x0d, 0xe8, 0x3e, 0x1b, 0xb0, 0x11,
+ 0xe8, 0x40, 0x1b, 0xb0, 0x15, 0xe8, 0x42, 0x1b,
+ 0xb0, 0x19, 0xe8, 0x44, 0x1b, 0xb0, 0x1d, 0xe8,
+ 0x46, 0x1b, 0xb0, 0x21, 0xe8, 0x48, 0x1b, 0xb0,
+ 0x25, 0xe8, 0x4a, 0x1b, 0xbb, 0x47, 0x33, 0xc7,
+ 0x47, 0x04, 0x7f, 0x02, 0xb0, 0x03, 0xe8, 0x68,
+ 0x8b, 0xe8, 0xe4, 0xb0, 0xc6, 0x07, 0x2a, 0xe8,
+ 0x6a, 0x1f, 0xe8, 0x1f, 0x8c, 0xb0, 0x06, 0xe8,
+ 0xc7, 0x8a, 0xb0, 0x05, 0xe8, 0xce, 0x8a, 0xc6,
+ 0x06, 0xab, 0xdb, 0x01, 0xc3, 0xbb, 0xd6, 0x2d,
+ 0xe8, 0xa2, 0x82, 0xe8, 0x31, 0x8c, 0xb9, 0x38,
+ 0x00, 0xb0, 0x10, 0xb4, 0x07, 0xe8, 0xcd, 0x1a,
+ 0xb0, 0x12, 0xe8, 0xd1, 0x1a, 0xb0, 0x14, 0xe8,
+ 0xd3, 0x1a, 0xb0, 0x16, 0xe8, 0xd5, 0x1a, 0xb0,
+ 0x18, 0xe8, 0xd7, 0x1a, 0xb0, 0x1a, 0xe8, 0xd9,
+ 0x1a, 0xb0, 0x1c, 0xe8, 0xdb, 0x1a, 0xb0, 0x1e,
+ 0xe8, 0xdd, 0x1a, 0xb9, 0x02, 0x00, 0xb0, 0x40,
+ 0xe8, 0xdc, 0x1a, 0xb9, 0x03, 0x00, 0xb0, 0x4a,
+ 0xe8, 0xdb, 0x1a, 0xc6, 0x06, 0x35, 0x33, 0x23,
+ 0xc6, 0x06, 0x36, 0x33, 0x32, 0xb8, 0xc7, 0x34,
+ 0xa3, 0x37, 0x33, 0xb8, 0xd4, 0x64, 0xa3, 0x39,
+ 0x33, 0xc6, 0x06, 0xe6, 0x1c, 0xd1, 0xb0, 0x01,
+ 0xb4, 0x03, 0xe8, 0x62, 0x8f, 0xbb, 0x47, 0x33,
+ 0xc7, 0x47, 0x04, 0x05, 0x02, 0xc7, 0x47, 0x06,
+ 0x06, 0x02, 0xb9, 0x04, 0x02, 0xe8, 0xd7, 0x8b,
+ 0xe8, 0xf8, 0x1b, 0xe8, 0x4e, 0x1b, 0xe8, 0xd8,
+ 0xae, 0xb0, 0x02, 0xe8, 0x3f, 0x8a, 0xb0, 0x03,
+ 0xe8, 0x3a, 0x8a, 0xb8, 0x03, 0x00, 0xe8, 0xc8,
+ 0x9e, 0xe8, 0xdc, 0x9e, 0xb8, 0x04, 0x00, 0xe8,
+ 0xbf, 0x9e, 0xe8, 0xd3, 0x9e, 0xb0, 0x02, 0xe8,
+ 0x86, 0x97, 0xc6, 0x06, 0x96, 0xdb, 0x01, 0xc3,
+ 0xbb, 0x2f, 0x3b, 0xe8, 0x87, 0x10, 0xe8, 0x86,
+ 0x8b, 0xb4, 0x02, 0xb0, 0x04, 0xe8, 0x36, 0x8f,
+ 0xb9, 0x05, 0x00, 0xb0, 0x03, 0xb4, 0x08, 0xe8,
+ 0x1b, 0x1a, 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x02,
+ 0x75, 0x02, 0xb9, 0x73, 0x02, 0xe8, 0x12, 0x8b,
+ 0xb9, 0x29, 0x00, 0xb0, 0x0a, 0xb4, 0x06, 0xe8,
+ 0x03, 0x1a, 0xb0, 0x2f, 0xe8, 0x07, 0x1a, 0xb9,
+ 0x37, 0x00, 0xb0, 0x34, 0xe8, 0x06, 0x1a, 0x80,
+ 0x3e, 0xa8, 0xdb, 0x01, 0x74, 0x15, 0xbb, 0x47,
+ 0x33, 0xc7, 0x47, 0x02, 0x76, 0x02, 0xb9, 0x74,
+ 0x02, 0xe8, 0x09, 0x8b, 0xbb, 0x59, 0x3b, 0xe8,
+ 0x33, 0x10, 0xc3, 0xbb, 0x47, 0x33, 0xc7, 0x47,
+ 0x02, 0x7a, 0x02, 0xb9, 0x74, 0x02, 0xe8, 0xd1,
+ 0x8a, 0xb0, 0x04, 0xe8, 0xaf, 0x89, 0xe8, 0x5a,
+ 0x1b, 0xe8, 0x62, 0x1a, 0xe8, 0x3a, 0xae, 0xb8,
+ 0x02, 0x00, 0xe8, 0x34, 0x9e, 0xe8, 0x48, 0x9e,
+ 0xbb, 0x6c, 0x3b, 0xe8, 0x07, 0x10, 0xc6, 0x06,
+ 0xa9, 0xdb, 0x01, 0xc3, 0x80, 0x3e, 0xab, 0xdb,
+ 0x01, 0x75, 0x07, 0xbb, 0x0b, 0x3c, 0xe8, 0xf4,
+ 0x0f, 0xc3, 0xb9, 0x05, 0x00, 0xb0, 0x0b, 0xb4,
+ 0x06, 0xe8, 0x91, 0x19, 0xb9, 0x31, 0x00, 0xb0,
+ 0x15, 0xe8, 0x92, 0x19, 0xe8, 0xe0, 0x8a, 0xc7,
+ 0x06, 0xb1, 0x64, 0x63, 0x00, 0xb9, 0x78, 0x02,
+ 0xe8, 0x7f, 0x8a, 0xe8, 0x62, 0xaf, 0xc6, 0x47,
+ 0x05, 0x28, 0xe8, 0xa3, 0x1d, 0xc7, 0x06, 0xaf,
+ 0x64, 0xe9, 0x00, 0xc7, 0x06, 0xb1, 0x64, 0x8b,
+ 0x00, 0xb9, 0x79, 0x02, 0xe8, 0x86, 0x8a, 0xc6,
+ 0x06, 0xa8, 0xdb, 0x01, 0xb0, 0x2f, 0xe8, 0x9f,
+ 0x96, 0x80, 0x3e, 0xaa, 0xdb, 0x01, 0x74, 0x0b,
+ 0xc6, 0x06, 0xaa, 0xdb, 0x01, 0xbb, 0x8b, 0x3b,
+ 0xe8, 0x9a, 0x0f, 0xc3, 0xb9, 0x05, 0x00, 0xb0,
+ 0x03, 0xb4, 0x0c, 0xe8, 0x37, 0x19, 0xb9, 0x06,
+ 0x00, 0xb0, 0x09, 0xe8, 0x38, 0x19, 0xb9, 0x27,
+ 0x03, 0xe8, 0x1b, 0x8a, 0xe8, 0x11, 0xaf, 0xc6,
+ 0x07, 0x53, 0xe8, 0x53, 0x1d, 0xe8, 0x4c, 0x8a,
+ 0xb0, 0x49, 0xe8, 0x63, 0x96, 0xb0, 0x02, 0xe8,
+ 0xfb, 0x88, 0xb0, 0x03, 0xe8, 0xea, 0x88, 0xc6,
+ 0x06, 0xef, 0xdb, 0x01, 0xc3, 0xbb, 0x8e, 0x4e,
+ 0xe8, 0x5a, 0x0f, 0xc3, 0xe8, 0x67, 0x00, 0x80,
+ 0x3e, 0xd2, 0xdb, 0x01, 0x75, 0x07, 0xbb, 0xc3,
+ 0x50, 0xe8, 0x49, 0x0f, 0xc3, 0x80, 0x3e, 0xcb,
+ 0xdb, 0x01, 0x74, 0x07, 0xbb, 0x01, 0x51, 0xe8,
+ 0x3b, 0x0f, 0xc3, 0xbb, 0xe1, 0x50, 0xe8, 0x34,
+ 0x0f, 0xb9, 0x05, 0x00, 0xb0, 0x03, 0xb4, 0x04,
+ 0xe8, 0xd2, 0x18, 0xb0, 0x27, 0xe8, 0xd6, 0x18,
+ 0xc6, 0x06, 0xe6, 0x1c, 0xd0, 0xc6, 0x06, 0x35,
+ 0x33, 0x09, 0xc6, 0x06, 0x36, 0x33, 0x23, 0xb8,
+ 0x24, 0x51, 0xa3, 0x37, 0x33, 0xb8, 0xc4, 0x9d,
+ 0xa3, 0x39, 0x33, 0xb9, 0xd8, 0x02, 0xe8, 0x1e,
+ 0x8a, 0xe8, 0xd8, 0x89, 0xe8, 0xea, 0x87, 0xbb,
+ 0x17, 0x3d, 0xe8, 0x68, 0x80, 0xc6, 0x06, 0xd2,
+ 0xdb, 0x01, 0xe8, 0x10, 0x00, 0xc3, 0x80, 0x3e,
+ 0xd1, 0xdb, 0x01, 0x74, 0x07, 0xbb, 0xa6, 0x50,
+ 0xe8, 0xe2, 0x0e, 0x58, 0xc3, 0x80, 0x3e, 0xd2,
+ 0xdb, 0x00, 0x74, 0x4e, 0x80, 0x3e, 0xd3, 0xdb,
+ 0x00, 0x74, 0x47, 0x80, 0x3e, 0xd4, 0xdb, 0x00,
+ 0x74, 0x40, 0xb8, 0x01, 0x01, 0xe8, 0x7e, 0x8d,
+ 0xb9, 0x59, 0x00, 0xb0, 0x02, 0xb4, 0x03, 0xe8,
+ 0x63, 0x18, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0xdb,
+ 0x02, 0xb0, 0x01, 0xe8, 0x7a, 0x88, 0xe8, 0x43,
+ 0x19, 0xe8, 0x3c, 0xae, 0xc6, 0x07, 0x46, 0xe8,
+ 0xc2, 0x1c, 0xb8, 0x01, 0x00, 0xe8, 0xc1, 0x9c,
+ 0xe8, 0xd5, 0x9c, 0xb0, 0x01, 0xe8, 0x25, 0x88,
+ 0xb0, 0x02, 0xe8, 0x14, 0x88, 0xb0, 0x03, 0xe8,
+ 0x0f, 0x88, 0xc3, 0xe8, 0x98, 0xff, 0x80, 0x3e,
+ 0xd3, 0xdb, 0x01, 0x75, 0x07, 0xbb, 0xc3, 0x50,
+ 0xe8, 0x7a, 0x0e, 0xc3, 0xbb, 0x38, 0x51, 0xe8,
+ 0x73, 0x0e, 0xb9, 0x05, 0x00, 0xb0, 0x03, 0xb4,
+ 0x04, 0xe8, 0x11, 0x18, 0xb0, 0x17, 0xe8, 0x15,
+ 0x18, 0xb9, 0xd9, 0x02, 0xe8, 0x19, 0x89, 0xe8,
+ 0x47, 0x87, 0xbb, 0x70, 0x3d, 0xe8, 0xc5, 0x7f,
+ 0xc6, 0x06, 0xd3, 0xdb, 0x01, 0xe8, 0x6d, 0xff,
+ 0xc3, 0xe8, 0x5a, 0xff, 0x80, 0x3e, 0xd4, 0xdb,
+ 0x01, 0x75, 0x07, 0xbb, 0xc3, 0x50, 0xe8, 0x3c,
+ 0x0e, 0xc3, 0xbb, 0x61, 0x51, 0xe8, 0x35, 0x0e,
+ 0xb9, 0x05, 0x00, 0xb0, 0x03, 0xb4, 0x04, 0xe8,
+ 0xd3, 0x17, 0xb0, 0x19, 0xe8, 0xd7, 0x17, 0xb9,
+ 0xda, 0x02, 0xe8, 0xdb, 0x88, 0xe8, 0x09, 0x87,
+ 0xbb, 0xd6, 0x3d, 0xe8, 0x87, 0x7f, 0xc6, 0x06,
+ 0xd4, 0xdb, 0x01, 0xe8, 0x2f, 0xff, 0xc3, 0xbb,
+ 0xfa, 0x4e, 0xe8, 0x08, 0x0e, 0xc3, 0xe8, 0x06,
+ 0x89, 0xe8, 0x94, 0xad, 0xc6, 0x47, 0x02, 0x40,
+ 0xe8, 0x19, 0x1c, 0xb9, 0x05, 0x00, 0xb0, 0x03,
+ 0xb4, 0x0a, 0xe8, 0x98, 0x17, 0xb9, 0x34, 0x00,
+ 0xb0, 0x0a, 0xe8, 0x99, 0x17, 0xb9, 0xc7, 0x02,
+ 0xe8, 0xa4, 0x88, 0x8b, 0x36, 0xaf, 0x64, 0x8b,
+ 0x3e, 0xb1, 0x64, 0xc6, 0x06, 0xc3, 0x64, 0x04,
+ 0xe8, 0xa8, 0xa3, 0xe8, 0x98, 0x86, 0xbb, 0x21,
+ 0x3b, 0xe8, 0x39, 0x7f, 0xbe, 0x2c, 0x01, 0xbf,
+ 0xbe, 0x00, 0xc6, 0x06, 0xc3, 0x64, 0x04, 0xe8,
+ 0x91, 0xa3, 0xb0, 0x40, 0xe8, 0xa9, 0x94, 0xb0,
+ 0x08, 0xe8, 0x41, 0x87, 0xbb, 0x47, 0x33, 0xc7,
+ 0x07, 0xc8, 0x02, 0xb0, 0x01, 0xe8, 0x70, 0x87,
+ 0xe8, 0x35, 0xad, 0xc6, 0x47, 0x02, 0x00, 0xe8,
+ 0xba, 0x1b, 0xb9, 0x0f, 0x00, 0xb0, 0x1a, 0xb4,
+ 0x02, 0xe8, 0x39, 0x17, 0xb0, 0x1c, 0xe8, 0x3d,
+ 0x17, 0xb9, 0x10, 0x00, 0xb0, 0x25, 0xe8, 0x3c,
+ 0x17, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0xc9, 0x02,
+ 0xb0, 0x01, 0xe8, 0x43, 0x87, 0xe8, 0xbe, 0x17,
+ 0xe8, 0x3b, 0x86, 0xbb, 0x0d, 0x3c, 0xe8, 0xdc,
+ 0x7e, 0xb9, 0x55, 0x00, 0xb0, 0x02, 0xb4, 0x03,
+ 0xe8, 0x0a, 0x17, 0xbb, 0x47, 0x33, 0xc7, 0x07,
+ 0xca, 0x02, 0xb0, 0x01, 0xe8, 0x21, 0x87, 0xe8,
+ 0xea, 0x17, 0xb8, 0x01, 0x00, 0xe8, 0x71, 0x9b,
+ 0xe8, 0x85, 0x9b, 0xb0, 0x01, 0xe8, 0xd5, 0x86,
+ 0xb9, 0x51, 0x00, 0xba, 0xa0, 0x00, 0xb0, 0x02,
+ 0xb4, 0x04, 0xe8, 0xe8, 0x86, 0xb9, 0x3f, 0x00,
+ 0xba, 0xa8, 0x00, 0xb0, 0x03, 0xb4, 0x04, 0xe8,
+ 0xdb, 0x86, 0xb9, 0x69, 0x00, 0xba, 0xa0, 0x00,
+ 0xb0, 0x0a, 0xb4, 0x01, 0xe8, 0xce, 0x86, 0xc6,
+ 0x06, 0xcc, 0xdb, 0x01, 0xc3, 0xe8, 0xa0, 0xdd,
+ 0x80, 0x3e, 0xcd, 0xdb, 0x01, 0x75, 0x07, 0xbb,
+ 0x3d, 0x4f, 0xe8, 0x08, 0x0d, 0xc3, 0xe8, 0x06,
+ 0x88, 0xe8, 0x94, 0xac, 0xc6, 0x47, 0x01, 0x00,
+ 0xe8, 0x19, 0x1b, 0xb9, 0x05, 0x00, 0xb0, 0x03,
+ 0xb4, 0x07, 0xe8, 0x98, 0x16, 0xb0, 0x21, 0xe8,
+ 0xcd, 0x16, 0xb9, 0x18, 0x00, 0xb0, 0x0d, 0xe8,
+ 0x94, 0x16, 0xb0, 0x13, 0xe8, 0x96, 0x16, 0xb0,
+ 0x17, 0xe8, 0x9f, 0x16, 0xb0, 0x1a, 0xe8, 0xa8,
+ 0x16, 0xb0, 0x1d, 0xe8, 0xaa, 0x16, 0xb9, 0x17,
+ 0x00, 0xb0, 0x15, 0xe8, 0x86, 0x16, 0xb9, 0x4a,
+ 0x00, 0xb0, 0x19, 0xe8, 0x8c, 0x16, 0xb9, 0xcc,
+ 0x02, 0xe8, 0x56, 0x87, 0xe8, 0x49, 0xac, 0xc6,
+ 0x47, 0x01, 0x42, 0xe8, 0x8a, 0x1a, 0xe8, 0x83,
+ 0x87, 0xc6, 0x06, 0xcd, 0xdb, 0x01, 0xc3, 0xe8,
+ 0x2e, 0xdd, 0xb9, 0x05, 0x00, 0xb0, 0x03, 0xb4,
+ 0x03, 0xe8, 0x41, 0x16, 0xb9, 0x56, 0x00, 0xb0,
+ 0x0b, 0xe8, 0x42, 0x16, 0xb9, 0xd0, 0x02, 0xe8,
+ 0x54, 0x87, 0xb0, 0x44, 0xe8, 0x69, 0x93, 0xb0,
+ 0x37, 0xe8, 0x74, 0x93, 0xc3, 0xe8, 0x7f, 0x87,
+ 0xe8, 0x0d, 0xac, 0xc6, 0x47, 0x04, 0x00, 0xe8,
+ 0x92, 0x1a, 0xb9, 0x57, 0x00, 0xb0, 0x07, 0xb4,
+ 0x08, 0xe8, 0x11, 0x16, 0xb9, 0xd2, 0x02, 0xe8,
+ 0x25, 0x87, 0xb9, 0x05, 0x00, 0xb0, 0x03, 0xb4,
+ 0x09, 0xe8, 0x01, 0x16, 0xb9, 0x58, 0x00, 0xb0,
+ 0x0c, 0xe8, 0x02, 0x16, 0xb9, 0x57, 0x00, 0xb0,
+ 0x18, 0xe8, 0x01, 0x16, 0xb9, 0xd3, 0x02, 0xe8,
+ 0x05, 0x87, 0xbb, 0x2b, 0x50, 0xe8, 0x3d, 0x0c,
+ 0xe8, 0x3a, 0x8b, 0xb9, 0x59, 0x00, 0xb0, 0x04,
+ 0xb4, 0x08, 0xe8, 0xd8, 0x15, 0xb9, 0xd4, 0x02,
+ 0xe8, 0xc7, 0x86, 0xe8, 0xba, 0xab, 0xc6, 0x47,
+ 0x04, 0x44, 0xe8, 0xfb, 0x19, 0xe8, 0xf4, 0x86,
+ 0xbb, 0x3e, 0x50, 0xe8, 0x17, 0x0c, 0xb0, 0x44,
+ 0xe8, 0x05, 0x93, 0xc6, 0x06, 0xd0, 0xdb, 0x01,
+ 0xc3, 0xb9, 0x05, 0x00, 0xb0, 0x04, 0xb4, 0x03,
+ 0xe8, 0xaa, 0x15, 0xb9, 0x3f, 0x00, 0xb0, 0x0c,
+ 0xe8, 0xab, 0x15, 0xb9, 0xd6, 0x02, 0xe8, 0xbd,
+ 0x86, 0xbb, 0x8a, 0x50, 0xe8, 0xee, 0x0b, 0xb0,
+ 0x45, 0xe8, 0xdc, 0x92, 0xb0, 0x46, 0xe8, 0xc7,
+ 0x92, 0xc3, 0xb9, 0x05, 0x00, 0xb0, 0x04, 0xb4,
+ 0x0e, 0xe8, 0x81, 0x15, 0xb9, 0x13, 0x00, 0xb0,
+ 0x0e, 0xe8, 0x82, 0x15, 0xb9, 0x19, 0x03, 0xe8,
+ 0x86, 0x86, 0xbb, 0x18, 0x52, 0xe8, 0xc5, 0x0b,
+ 0xb0, 0x3c, 0xe8, 0xb3, 0x92, 0xc6, 0x06, 0xd6,
+ 0xdb, 0x01, 0xc3, 0x80, 0x3e, 0xd6, 0xdb, 0x02,
+ 0x74, 0x07, 0xbb, 0x4f, 0x52, 0xe8, 0xad, 0x0b,
+ 0xc3, 0xb9, 0x05, 0x00, 0xb0, 0x04, 0xb4, 0x0e,
+ 0xe8, 0x4a, 0x15, 0xb0, 0x19, 0xe8, 0x4e, 0x15,
+ 0xb9, 0x22, 0x03, 0xe8, 0x52, 0x86, 0xbb, 0x72,
+ 0x52, 0xe8, 0x91, 0x0b, 0xb0, 0x3e, 0xe8, 0x7f,
+ 0x92, 0xb0, 0x4a, 0xe8, 0x6a, 0x92, 0xb0, 0x41,
+ 0xe8, 0x65, 0x92, 0xc3, 0xb0, 0x46, 0xe8, 0x93,
+ 0x92, 0x73, 0x39, 0xe8, 0x79, 0x86, 0xe8, 0x07,
+ 0xab, 0xc6, 0x07, 0x00, 0xe8, 0x8d, 0x19, 0xb9,
+ 0x05, 0x00, 0xb0, 0x03, 0xb4, 0x04, 0xe8, 0x0c,
+ 0x15, 0xb0, 0x12, 0xe8, 0x17, 0x15, 0xb9, 0x0d,
+ 0x00, 0xb0, 0x0c, 0xe8, 0x08, 0x15, 0xb9, 0x23,
+ 0x03, 0xe8, 0x21, 0x86, 0xb0, 0x07, 0xe8, 0xdc,
+ 0x84, 0xb0, 0x46, 0xe8, 0x3a, 0x92, 0xb0, 0x47,
+ 0xe8, 0x25, 0x92, 0xc3, 0xbb, 0xad, 0x53, 0xe8,
+ 0x3b, 0x0b, 0xc3, 0xb9, 0x05, 0x00, 0xb0, 0x04,
+ 0xb4, 0x0e, 0xe8, 0xd8, 0x14, 0xb0, 0x16, 0xe8,
+ 0xdc, 0x14, 0xb9, 0x24, 0x03, 0xe8, 0xe0, 0x85,
+ 0xbb, 0x8b, 0x52, 0xe8, 0x1f, 0x0b, 0xc3, 0xb9,
+ 0x05, 0x00, 0xb0, 0x03, 0xb4, 0x04, 0xe8, 0xbc,
+ 0x14, 0xb0, 0x10, 0xe8, 0xc0, 0x14, 0xb9, 0xbf,
+ 0x02, 0xe8, 0xc4, 0x85, 0x80, 0x3e, 0xc8, 0xdb,
+ 0x01, 0x74, 0x07, 0xbb, 0x80, 0x4d, 0xe8, 0xfc,
+ 0x0a, 0xc3, 0x80, 0x3e, 0xc6, 0xdb, 0x00, 0x74,
+ 0x22, 0xc6, 0x06, 0xc6, 0xdb, 0x00, 0x80, 0x3e,
+ 0xc5, 0xdb, 0x01, 0x75, 0x15, 0xbb, 0x47, 0x33,
+ 0xc7, 0x07, 0xbd, 0x02, 0xb0, 0x01, 0xe8, 0xae,
+ 0x84, 0xe8, 0x70, 0x15, 0xbb, 0xa6, 0x4d, 0xe8,
+ 0xd3, 0x0a, 0xc3, 0x80, 0x3e, 0xc5, 0xdb, 0x01,
+ 0x74, 0x07, 0xbb, 0x5b, 0x4d, 0xe8, 0xc5, 0x0a,
+ 0xc3, 0x80, 0x3e, 0xc7, 0xdb, 0x01, 0x74, 0x06,
+ 0xbb, 0x93, 0x4d, 0xe8, 0xb7, 0x0a, 0xbb, 0x47,
+ 0x33, 0xc7, 0x07, 0xbe, 0x02, 0xb0, 0x01, 0xe8,
+ 0x7d, 0x84, 0xe8, 0x3f, 0x15, 0xc6, 0x06, 0xc6,
+ 0xdb, 0x01, 0x80, 0x3e, 0xc7, 0xdb, 0x01, 0x74,
+ 0x0e, 0xe8, 0x3f, 0x83, 0xbb, 0x2c, 0x39, 0xe8,
+ 0x03, 0x7c, 0xc6, 0x06, 0xc7, 0xdb, 0x01, 0xc3,
+ 0xb9, 0x05, 0x00, 0xb0, 0x03, 0xb4, 0x06, 0xe8,
+ 0x2b, 0x14, 0xb9, 0x5b, 0x00, 0xb0, 0x0c, 0xe8,
+ 0x2c, 0x14, 0xb9, 0xc2, 0x02, 0xe8, 0x30, 0x85,
+ 0xb0, 0x36, 0xe8, 0x63, 0x91, 0xc6, 0x06, 0xc8,
+ 0xdb, 0x01, 0xc3, 0x80, 0x3e, 0xc6, 0xdb, 0x01,
+ 0x74, 0x07, 0xbb, 0xa5, 0x4e, 0xe8, 0x5d, 0x0a,
+ 0xc3, 0x80, 0x3e, 0xca, 0xdb, 0x01, 0x75, 0x07,
+ 0xbb, 0xe6, 0x4d, 0xe8, 0x4f, 0x0a, 0xc3, 0xb9,
+ 0x05, 0x00, 0xb0, 0x03, 0xb4, 0x04, 0xe8, 0xec,
+ 0x13, 0xb0, 0x18, 0xe8, 0xf7, 0x13, 0xb9, 0x5a,
+ 0x00, 0xb0, 0x12, 0xe8, 0xe8, 0x13, 0xb9, 0xc3,
+ 0x02, 0xe8, 0xec, 0x84, 0xb0, 0x3d, 0xe8, 0x0f,
+ 0x91, 0xc6, 0x06, 0xca, 0xdb, 0x01, 0xc3, 0x80,
+ 0x3e, 0xc6, 0xdb, 0x01, 0x74, 0x07, 0xbb, 0xa5,
+ 0x4e, 0xe8, 0x19, 0x0a, 0xc3, 0x80, 0x3e, 0xcb,
+ 0xdb, 0x01, 0x75, 0x07, 0xbb, 0x32, 0x4e, 0xe8,
+ 0x0b, 0x0a, 0xc3, 0xbb, 0x05, 0x4e, 0xe8, 0x04,
+ 0x0a, 0xb9, 0x05, 0x00, 0xb0, 0x03, 0xb4, 0x04,
+ 0xe8, 0xa2, 0x13, 0xb0, 0x1b, 0xe8, 0xa6, 0x13,
+ 0xb9, 0xc4, 0x02, 0xe8, 0xaa, 0x84, 0xc6, 0x06,
+ 0xcb, 0xdb, 0x01, 0xc3, 0xbb, 0x58, 0x4e, 0xe8,
+ 0xe3, 0x09, 0xc3, 0xb9, 0x05, 0x00, 0xb0, 0x03,
+ 0xb4, 0x05, 0xe8, 0x80, 0x13, 0xb9, 0x18, 0x00,
+ 0xb0, 0x0a, 0xe8, 0x81, 0x13, 0xb9, 0x1e, 0x03,
+ 0xe8, 0x85, 0x84, 0xb9, 0x3f, 0x00, 0xb0, 0x0b,
+ 0xb4, 0x05, 0xe8, 0x68, 0x13, 0xb9, 0x13, 0x00,
+ 0xb0, 0x14, 0xe8, 0x69, 0x13, 0xbb, 0x47, 0x33,
+ 0xc7, 0x07, 0x1f, 0x03, 0xb0, 0x01, 0xe8, 0x7e,
+ 0x83, 0x50, 0x52, 0xbe, 0x32, 0x00, 0xbf, 0xaa,
+ 0x00, 0xc6, 0x06, 0xc3, 0x64, 0x01, 0xe8, 0x72,
+ 0x9f, 0x5a, 0x58, 0xbf, 0xc7, 0x32, 0xb3, 0x1b,
+ 0x48, 0xf6, 0xe3, 0x03, 0xf8, 0xe8, 0x43, 0x7c,
+ 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x20, 0x03, 0xb0,
+ 0x01, 0xe8, 0x53, 0x83, 0xe8, 0x15, 0x14, 0xe8,
+ 0x7b, 0x88, 0xb9, 0x25, 0x03, 0xe8, 0x12, 0x84,
+ 0xe8, 0xb0, 0x14, 0xbe, 0x32, 0x00, 0xbf, 0xaa,
+ 0x00, 0xc6, 0x06, 0xc3, 0x64, 0x03, 0xe8, 0x3a,
+ 0x9f, 0xbb, 0x49, 0x53, 0xe8, 0x5e, 0x09, 0xc7,
+ 0x06, 0xaf, 0x64, 0x69, 0x00, 0xc7, 0x06, 0xb1,
+ 0x64, 0x9d, 0x00, 0xc6, 0x06, 0xcb, 0x64, 0x00,
+ 0xc6, 0x06, 0xcc, 0x64, 0x00, 0xc6, 0x06, 0xdc,
+ 0x64, 0x01, 0xe8, 0x64, 0xa7, 0xb9, 0x03, 0x00,
+ 0xe8, 0x30, 0x1a, 0xbb, 0x47, 0x33, 0xc7, 0x07,
+ 0xaa, 0x03, 0xc7, 0x06, 0xf3, 0xb4, 0x0b, 0x00,
+ 0xe8, 0xea, 0x15, 0xe8, 0x61, 0x80, 0xbb, 0x09,
+ 0x84, 0xe8, 0x91, 0x7a, 0xbb, 0x47, 0x33, 0xc7,
+ 0x07, 0xab, 0x03, 0xb9, 0xae, 0x03, 0xe8, 0xc1,
+ 0x83, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0xab, 0x03,
+ 0xc7, 0x47, 0x02, 0xa7, 0x03, 0xb9, 0xaf, 0x03,
+ 0xe8, 0xaf, 0x83, 0xbb, 0x47, 0x33, 0xc7, 0x07,
+ 0xac, 0x03, 0xc7, 0x47, 0x02, 0xa8, 0x03, 0xb9,
+ 0xb0, 0x03, 0xe8, 0x9d, 0x83, 0xbb, 0x47, 0x33,
+ 0xc7, 0x07, 0xad, 0x03, 0xc7, 0x47, 0x02, 0xa9,
+ 0x03, 0xb9, 0xb1, 0x03, 0xe8, 0x8b, 0x83, 0xbb,
+ 0x47, 0x33, 0xc7, 0x07, 0x00, 0x00, 0xe8, 0xab,
+ 0x83, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0xb2, 0x03,
+ 0xb0, 0x01, 0xe8, 0xd5, 0x82, 0xe8, 0xff, 0x7f,
+ 0xbb, 0x4f, 0x84, 0xe8, 0x2f, 0x7a, 0xbb, 0x47,
+ 0x33, 0xc7, 0x07, 0xb2, 0x03, 0xb0, 0x01, 0xe8,
+ 0xc0, 0x82, 0xe8, 0xea, 0x7f, 0xbb, 0xc7, 0x87,
+ 0xe8, 0x1a, 0x7a, 0xb9, 0x18, 0x00, 0xb0, 0x07,
+ 0xb4, 0x05, 0xe8, 0x48, 0x12, 0xbb, 0x47, 0x33,
+ 0xc7, 0x07, 0xb4, 0x03, 0xb9, 0xb3, 0x03, 0xe8,
+ 0x40, 0x83, 0xe8, 0xce, 0x13, 0xe8, 0xd6, 0x12,
+ 0xc7, 0x06, 0xaf, 0x64, 0xc6, 0x00, 0xc7, 0x06,
+ 0xb1, 0x64, 0xba, 0x00, 0xc6, 0x06, 0xcd, 0x64,
+ 0x00, 0xc6, 0x06, 0xdc, 0x64, 0x00, 0xc6, 0x06,
+ 0xcb, 0x64, 0x01, 0xe8, 0x93, 0xa6, 0xc7, 0x06,
+ 0xf3, 0xb4, 0x28, 0x00, 0xe8, 0x26, 0x15, 0xe8,
+ 0xe5, 0x7e, 0xbb, 0x90, 0x88, 0xe8, 0xcd, 0x79,
+ 0xe8, 0x0a, 0x7f, 0xbb, 0x2f, 0x8a, 0xe8, 0xc4,
+ 0x79, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x9b, 0x03,
+ 0xb0, 0x01, 0xe8, 0x55, 0x82, 0xe8, 0xc7, 0x7e,
+ 0xbb, 0xa7, 0x8a, 0xe8, 0xaf, 0x79, 0xbe, 0xed,
+ 0x00, 0xbf, 0xba, 0x00, 0xe8, 0x0c, 0x9e, 0xbe,
+ 0xed, 0x00, 0xbf, 0xb1, 0x00, 0xe8, 0x03, 0x9e,
+ 0xbe, 0xc0, 0x00, 0xbf, 0xb1, 0x00, 0xe8, 0xfa,
+ 0x9d, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0xb5, 0x03,
+ 0xb0, 0x01, 0xe8, 0x25, 0x82, 0xc6, 0x06, 0x45,
+ 0x33, 0xe7, 0xb0, 0x01, 0xbe, 0xb6, 0x03, 0xbb,
+ 0xf6, 0x8a, 0xe8, 0xaa, 0x7d, 0xb9, 0x20, 0x00,
+ 0xb0, 0x05, 0xb4, 0x09, 0xe8, 0xa6, 0x11, 0xb9,
+ 0x28, 0x00, 0xb0, 0x0e, 0xe8, 0xa7, 0x11, 0xbb,
+ 0x47, 0x33, 0xc7, 0x07, 0xb7, 0x03, 0xb9, 0xb8,
+ 0x03, 0xe8, 0x96, 0x82, 0xe8, 0x24, 0x13, 0xb9,
+ 0x0b, 0x00, 0xe8, 0xd6, 0x18, 0xe8, 0x44, 0x69,
+ 0xbb, 0x47, 0x33, 0xc7, 0x07, 0xb9, 0x03, 0xc7,
+ 0x06, 0xf3, 0xb4, 0x27, 0x00, 0xe8, 0x84, 0x14,
+ 0xc6, 0x06, 0x45, 0x33, 0xe3, 0xb0, 0x01, 0xbe,
+ 0xb9, 0x03, 0xbb, 0x4d, 0x8b, 0xe8, 0x5f, 0x7d,
+ 0xb9, 0x05, 0x00, 0xb0, 0x0f, 0xb4, 0x08, 0xe8,
+ 0x5b, 0x11, 0xbb, 0x47, 0x33, 0xc7, 0x07, 0xba,
+ 0x03, 0xb0, 0x01, 0xe8, 0xb4, 0x81, 0xb0, 0x01,
+ 0xbe, 0xbb, 0x03, 0xbb, 0x7a, 0x8b, 0xe8, 0x3e,
+ 0x7d, 0x8b, 0x16, 0xb3, 0x32, 0xbe, 0x00, 0xfa,
+ 0xb0, 0xfe, 0xe8, 0x5d, 0x0e, 0xff, 0x36, 0xa8,
+ 0x64, 0xc6, 0x06, 0xa8, 0x64, 0x00, 0xb8, 0x64,
+ 0x00, 0xe8, 0x88, 0x86, 0xe8, 0x62, 0x69, 0x8f,
+ 0x06, 0xa8, 0x64, 0xb9, 0x02, 0x00, 0xe8, 0x6a,
+ 0x18, 0xbb, 0x7c, 0xe4, 0xe8, 0xf7, 0x6c, 0x2e,
+ 0x80, 0x3e, 0xd7, 0x00, 0x80, 0x73, 0xf8, 0x2e,
+ 0x80, 0x3e, 0xd7, 0x00, 0x00, 0x74, 0xf0, 0xe9,
+ 0xad, 0x68, 0xb0, 0x03, 0xe8, 0x49, 0x8e, 0xb0,
+ 0x04, 0xe8, 0x34, 0x8e, 0xb0, 0x23, 0xe8, 0x2f,
+ 0x8e, 0xbb, 0x68, 0x34, 0xe8, 0x46, 0x07, 0xc3,
+ 0xb0, 0x04, 0xe8, 0x33, 0x8e, 0xb0, 0x05, 0xe8,
+ 0x1e, 0x8e, 0xbb, 0x90, 0x34, 0xe8, 0x35, 0x07,
+ 0xc3, 0xa1, 0xf3, 0xb4, 0x3d, 0x0f, 0x00, 0x74,
+ 0x0f, 0xbb, 0xce, 0x38, 0x3d, 0x10, 0x00, 0x74,
+ 0x03, 0xbb, 0xa7, 0x38, 0xe8, 0x1e, 0x07, 0xc3,
+ 0xbe, 0x9c, 0x00, 0xbf, 0xb4, 0x00, 0xc6, 0x06,
+ 0xc3, 0x64, 0x03, 0xe8, 0xe5, 0x9c, 0xb9, 0x05,
+ 0x00, 0xb0, 0x03, 0xb4, 0x07, 0xe8, 0xad, 0x10,
+ 0xb9, 0x26, 0x00, 0xb0, 0x10, 0xe8, 0xae, 0x10,
+ 0xb0, 0x16, 0xe8, 0xb0, 0x10, 0xb9, 0x66, 0x02,
+ 0xe8, 0x8c, 0x81, 0xb9, 0x05, 0x00, 0xb0, 0x03,
+ 0xb4, 0x07, 0xe8, 0x90, 0x10, 0xb9, 0x2c, 0x00,
+ 0xb0, 0x0a, 0xe8, 0x91, 0x10, 0xb9, 0x14, 0x00,
+ 0xb0, 0x1a, 0xe8, 0x90, 0x10, 0xb9, 0x67, 0x02,
+ 0xe8, 0x6f, 0x81, 0xe8, 0x0d, 0x12, 0xc7, 0x06,
+ 0xf3, 0xb4, 0x11, 0x00, 0xc6, 0x06, 0xdc, 0x1c,
+ 0x01, 0xe8, 0x93, 0x12, 0xb9, 0x40, 0x00, 0xb4,
+ 0x07, 0xb0, 0x01, 0xe8, 0x5f, 0x10, 0xb0, 0x15,
+ 0xe8, 0x63, 0x10, 0xb0, 0x2a, 0xe8, 0x65, 0x10,
+ 0xb0, 0x3f, 0xe8, 0x67, 0x10, 0xb9, 0x69, 0x02,
+ 0xc6, 0x06, 0xdc, 0x1c, 0x01, 0xc7, 0x06, 0x1f,
+ 0xc4, 0x00, 0x00, 0xe8, 0x87, 0x10, 0xe8, 0x9b,
+ 0x10, 0xe8, 0x0f, 0x10, 0xc7, 0x06, 0x23, 0xc4,
+ 0x05, 0x00, 0xc7, 0x06, 0x3b, 0x33, 0x00, 0x00,
+ 0xc7, 0x06, 0x3d, 0x33, 0x14, 0x00, 0xc6, 0x06,
+ 0xce, 0x00, 0x02, 0xe8, 0xe7, 0x82, 0x73, 0x3d,
+ 0xb9, 0x40, 0x00, 0xb4, 0x07, 0xb0, 0x01, 0xe8,
+ 0x13, 0x10, 0xb9, 0x6a, 0x02, 0xe8, 0x02, 0x81,
+ 0xb0, 0x05, 0xe8, 0xf0, 0x7f, 0xe8, 0xf0, 0xa5,
+ 0xc6, 0x07, 0x00, 0xe8, 0x32, 0x14, 0xb9, 0x1f,
+ 0x00, 0xb0, 0x01, 0xb4, 0x07, 0xe8, 0xf5, 0x0f,
+ 0xb9, 0x6b, 0x02, 0xe8, 0xe4, 0x80, 0xe8, 0x69,
+ 0x00, 0xb0, 0x2a, 0xe8, 0x22, 0x8d, 0xbb, 0x89,
+ 0x39, 0xe8, 0x39, 0x06, 0xc3, 0x51, 0xe8, 0x59,
+ 0x00, 0x59, 0x80, 0x3e, 0xcf, 0x00, 0x00, 0x74,
+ 0x20, 0x80, 0x3e, 0xcf, 0x00, 0x04, 0x74, 0x0d,
+ 0xbb, 0x32, 0x39, 0x83, 0xf9, 0x05, 0x74, 0x08,
+ 0xbb, 0xff, 0x38, 0xeb, 0x03, 0xbb, 0xdb, 0x38,
+ 0xc6, 0x06, 0xcf, 0x00, 0x00, 0xe8, 0x0d, 0x06,
+ 0xc3, 0xfe, 0x06, 0xa6, 0xdb, 0xa0, 0xa6, 0xdb,
+ 0xbb, 0xae, 0x39, 0x3c, 0x01, 0x74, 0x1f, 0xbb,
+ 0xf6, 0x39, 0x3c, 0x02, 0x74, 0x18, 0xbb, 0x28,
+ 0x3a, 0x3c, 0x03, 0x74, 0x11, 0xbb, 0x5a, 0x3a,
+ 0x3c, 0x04, 0x74, 0x0a, 0xbb, 0x85, 0x3a, 0x3c,
+ 0x05, 0x74, 0x03, 0xbb, 0xb7, 0x3a, 0xe8, 0xdc,
+ 0x05, 0xc3, 0xe8, 0x16, 0x11, 0xc7, 0x06, 0xf3,
+ 0xb4, 0x0f, 0x00, 0xe8, 0x86, 0x12, 0xc7, 0x06,
+ 0xaf, 0x64, 0x9c, 0x00, 0xc7, 0x06, 0xb1, 0x64,
+ 0xb4, 0x00, 0xc6, 0x06, 0xc3, 0x64, 0x03, 0xc6,
+ 0x06, 0xcb, 0x64, 0x01, 0xc6, 0x06, 0xcd, 0x64,
+ 0x01, 0xb9, 0x05, 0x00, 0xb0, 0x05, 0xb4, 0x07,
+ 0xe8, 0x52, 0x0f, 0xb9, 0x26, 0x00, 0xb0, 0x0e,
+ 0xe8, 0x53, 0x0f, 0xb9, 0x26, 0x00, 0xb0, 0x14,
+ 0xe8, 0x52, 0x0f, 0xb9, 0x05, 0x00, 0xb0, 0x19,
+ 0xe8, 0x51, 0x0f, 0xb9, 0x68, 0x02, 0xe8, 0x47,
+ 0x80, 0xc3, 0xa1, 0xf3, 0xb4, 0x3d, 0x0d, 0x00,
+ 0x74, 0x07, 0xbb, 0x58, 0x3c, 0xe8, 0x7d, 0x05,
+ 0xc3, 0xe8, 0x7b, 0x80, 0xbe, 0xac, 0x00, 0xbf,
+ 0xb5, 0x00, 0xc6, 0x06, 0xc3, 0x64, 0x01, 0xe8,
+ 0x41, 0x9b, 0xb9, 0x1a, 0x00, 0xb0, 0x13, 0xb4,
+ 0x07, 0xe8, 0x09, 0x0f, 0xb0, 0x1e, 0xe8, 0x14,
+ 0x0f, 0xb0, 0x29, 0xe8, 0x1d, 0x0f, 0xb0, 0x34,
+ 0xe8, 0x26, 0x0f, 0xb0, 0x3f, 0xe8, 0x2f, 0x0f,
+ 0xb9, 0x38, 0x00, 0xb0, 0x17, 0xe8, 0xf6, 0x0e,
+ 0xb0, 0x22, 0xe8, 0xff, 0x0e, 0xb0, 0x2d, 0xe8,
+ 0x08, 0x0f, 0xb0, 0x38, 0xe8, 0x11, 0x0f, 0xb9,
+ 0x95, 0x02, 0xe8, 0xcd, 0x7f, 0xbe, 0x14, 0x77,
+ 0xbb, 0x80, 0x3c, 0xc6, 0x06, 0xdc, 0x1c, 0x01,
+ 0xe8, 0xe2, 0x00, 0xb9, 0x38, 0x00, 0xb0, 0x0a,
+ 0xb4, 0x07, 0xe8, 0xc0, 0x0e, 0xb0, 0x15, 0xe8,
+ 0xc4, 0x0e, 0xb9, 0x08, 0x00, 0xb0, 0x30, 0xe8,
+ 0xc3, 0x0e, 0xb9, 0x38, 0x00, 0xb0, 0x75, 0xe8,
+ 0xc2, 0x0e, 0xb0, 0x80, 0xe8, 0xc4, 0x0e, 0xb0,
+ 0x8b, 0xe8, 0xc6, 0x0e, 0xb0, 0x96, 0xe8, 0xc8,
+ 0x0e, 0xb0, 0xa1, 0xe8, 0xca, 0x0e, 0xb0, 0xac,
+ 0xe8, 0xcc, 0x0e, 0xb0, 0xb7, 0xe8, 0xce, 0x0e,
+ 0x83, 0x2e, 0xb1, 0x64, 0x14, 0xbb, 0x47, 0x33,
+ 0xc7, 0x47, 0x02, 0x97, 0x02, 0xb9, 0x96, 0x02,
+ 0xe8, 0x6f, 0x7f, 0xe8, 0x18, 0x0f, 0xe8, 0x5f,
+ 0xa4, 0xc6, 0x47, 0x01, 0x31, 0xe8, 0xa0, 0x12,
+ 0xbe, 0xf5, 0x76, 0xbb, 0x9a, 0x3c, 0xc6, 0x06,
+ 0xdc, 0x1c, 0x01, 0xe8, 0x77, 0x00, 0xc7, 0x06,
+ 0xaf, 0x64, 0xa2, 0x00, 0xc7, 0x06, 0xb1, 0x64,
+ 0xb8, 0x00, 0xb9, 0x1a, 0x00, 0xb0, 0x06, 0xb4,
+ 0x07, 0xe8, 0x49, 0x0e, 0xb0, 0x11, 0xe8, 0x54,
+ 0x0e, 0xb9, 0x38, 0x00, 0xb0, 0x0a, 0xe8, 0x45,
+ 0x0e, 0xb0, 0x15, 0xe8, 0x4e, 0x0e, 0xb9, 0x13,
+ 0x00, 0xb0, 0x1b, 0xe8, 0x4d, 0x0e, 0xb9, 0x18,
+ 0x00, 0xb0, 0x26, 0xe8, 0x4c, 0x0e, 0xb9, 0x17,
+ 0x00, 0xb0, 0x2c, 0xe8, 0x4b, 0x0e, 0xb9, 0x98,
+ 0x02, 0xe8, 0x0e, 0x7f, 0xe8, 0xac, 0x0f, 0xbb,
+ 0x47, 0x33, 0xc7, 0x47, 0x02, 0x99, 0x02, 0xb0,
+ 0x02, 0xe8, 0x2c, 0x7e, 0xe8, 0x5e, 0x83, 0xbb,
+ 0xbc, 0x3c, 0xe8, 0x58, 0x04, 0xe8, 0x55, 0x83,
+ 0xe8, 0x29, 0x7f, 0xe8, 0x4f, 0x83, 0xbb, 0xea,
+ 0x3c, 0xe8, 0x49, 0x04, 0xb0, 0x25, 0xe8, 0x37,
+ 0x8b, 0xe8, 0x31, 0x01, 0xc3, 0x06, 0x53, 0x56,
+ 0xb8, 0x00, 0xa0, 0x8e, 0xc0, 0xe8, 0x25, 0x00,
+ 0xb8, 0x00, 0xa0, 0xb9, 0x00, 0x7d, 0xe8, 0xd7,
+ 0x10, 0x5e, 0x5b, 0xe8, 0x27, 0x08, 0xe8, 0x23,
+ 0x00, 0xb8, 0x96, 0x00, 0xe8, 0x25, 0x83, 0xe8,
+ 0x0b, 0x00, 0xe8, 0x2a, 0x91, 0xe8, 0x80, 0x0c,
+ 0xe8, 0x11, 0x00, 0x07, 0xc3, 0x80, 0x3e, 0xad,
+ 0x64, 0x01, 0x75, 0x04, 0xe8, 0x7d, 0x10, 0xc3,
+ 0xe8, 0x93, 0x10, 0xc3, 0x80, 0x3e, 0xad, 0x64,
+ 0x01, 0x75, 0x04, 0xe8, 0x7b, 0x10, 0xc3, 0xe8,
+ 0x91, 0x10, 0xe8, 0x5c, 0x10, 0xc3, 0xbb, 0x84,
+ 0x49, 0xe8, 0xe9, 0x03, 0xc3, 0xbb, 0xd1, 0x49,
+ 0xe8, 0xe2, 0x03, 0xc6, 0x06, 0xb5, 0xdb, 0x01,
+ 0xc3, 0x83, 0x3e, 0xf3, 0xb4, 0x24, 0x74, 0x07,
+ 0xbb, 0xa9, 0x52, 0xe8, 0xcf, 0x03, 0xc3, 0x80,
+ 0x3e, 0xf1, 0xdb, 0x01, 0x75, 0x07, 0xbb, 0xf6,
+ 0x52, 0xe8, 0xc1, 0x03, 0xc3, 0xc6, 0x06, 0xf1,
+ 0xdb, 0x01, 0xe8, 0xba, 0x7e, 0xbe, 0x66, 0x00,
+ 0xbf, 0xc3, 0x00, 0xc6, 0x06, 0xc3, 0x64, 0x02,
+ 0xe8, 0x80, 0x99, 0xb9, 0x05, 0x00, 0xb0, 0x03,
+ 0xb4, 0x05, 0xe8, 0x48, 0x0d, 0xb9, 0x4b, 0x00,
+ 0xb0, 0x0c, 0xe8, 0x49, 0x0d, 0xb9, 0x1a, 0x03,
+ 0xe8, 0x54, 0x7e, 0xb8, 0x01, 0x00, 0xe8, 0xc7,
+ 0x91, 0x53, 0xe8, 0x88, 0x82, 0xbb, 0x46, 0x67,
+ 0xe8, 0x07, 0xa3, 0x83, 0xc3, 0x03, 0xc7, 0x07,
+ 0x00, 0x00, 0xc7, 0x47, 0x04, 0x00, 0x00, 0x53,
+ 0xbe, 0x97, 0x00, 0xbf, 0xc5, 0x00, 0xc6, 0x06,
+ 0xc3, 0x64, 0x02, 0xe8, 0x3d, 0x99, 0xb9, 0x1b,
+ 0x03, 0xe8, 0xfe, 0x7d, 0xc7, 0x06, 0xaf, 0x64,
+ 0xba, 0x00, 0xff, 0x06, 0xb1, 0x64, 0xe8, 0x2b,
+ 0x7e, 0xbe, 0xdc, 0x00, 0xbf, 0xc6, 0x00, 0xc6,
+ 0x06, 0xc3, 0x64, 0x04, 0xe8, 0x1c, 0x99, 0x5b,
+ 0xc7, 0x47, 0x04, 0xc8, 0x00, 0x5b, 0xc7, 0x07,
+ 0x01, 0x00, 0xb0, 0x02, 0xe8, 0xc6, 0x7c, 0xbb,
+ 0xa9, 0x58, 0xe8, 0xa0, 0x74, 0xb0, 0x01, 0xb4,
+ 0x02, 0xb9, 0x0e, 0x01, 0xba, 0xc1, 0x00, 0xe8,
+ 0xd3, 0x7c, 0xb0, 0x03, 0xb4, 0x01, 0xb9, 0xfe,
+ 0x00, 0xba, 0xc1, 0x00, 0xe8, 0xc6, 0x7c, 0xc6,
+ 0x06, 0xd7, 0xdb, 0x01, 0xc3, 0xe8, 0x06, 0x82,
+ 0xff, 0x06, 0xea, 0xdb, 0xa1, 0xea, 0xdb, 0x3d,
+ 0x07, 0x00, 0x73, 0x3b, 0x2d, 0x02, 0x00, 0xbb,
+ 0x35, 0x60, 0xd1, 0xe0, 0x03, 0xd8, 0xff, 0x36,
+ 0xf3, 0xb4, 0x53, 0xb9, 0x0b, 0x00, 0xe8, 0xe2,
+ 0x13, 0xe8, 0x85, 0x02, 0x5b, 0xff, 0x17, 0xc6,
+ 0x06, 0xdc, 0x1c, 0x02, 0x8f, 0x06, 0xf3, 0xb4,
+ 0xb9, 0x06, 0x00, 0xe8, 0xcd, 0x13, 0x83, 0x3e,
+ 0xf3, 0xb4, 0x0b, 0x75, 0x07, 0x83, 0x3e, 0xec,
+ 0xdb, 0x01, 0x74, 0x03, 0xe8, 0x98, 0x0e, 0xc3,
+ 0xbb, 0x47, 0x33, 0xc7, 0x07, 0xda, 0x03, 0xc7,
+ 0x47, 0x02, 0xdb, 0x03, 0xc7, 0x06, 0xf3, 0xb4,
+ 0x22, 0x00, 0xe8, 0x67, 0x0f, 0xbb, 0x47, 0x33,
+ 0xc7, 0x07, 0xda, 0x03, 0xc7, 0x47, 0x02, 0xdb,
+ 0x03, 0xb0, 0x01, 0xe8, 0xac, 0x7c, 0xc6, 0x06,
+ 0x45, 0x33, 0xd9, 0xc6, 0x06, 0x46, 0x33, 0xd0,
+ 0xb0, 0x01, 0xb4, 0x02, 0xbe, 0xdc, 0x03, 0xbf,
+ 0xdd, 0x03, 0xbb, 0x60, 0x6f, 0xe8, 0x9e, 0x76,
+ 0xbb, 0x47, 0x33, 0xc7, 0x07, 0xde, 0x03, 0xc7,
+ 0x47, 0x02, 0xdf, 0x03, 0xb0, 0x01, 0xe8, 0x81,
+ 0x7c, 0xe8, 0xba, 0x0c, 0xc3, 0xbb, 0x47, 0x33,
+ 0xc7, 0x47, 0x02, 0x77, 0x03, 0xc7, 0x47, 0x04,
+ 0x78, 0x03, 0xc7, 0x06, 0xf3, 0xb4, 0x1e, 0x00,
+ 0xe8, 0x11, 0x0f, 0xbb, 0x47, 0x33, 0xc7, 0x47,
+ 0x02, 0x77, 0x03, 0xc7, 0x47, 0x04, 0x78, 0x03,
+ 0xb0, 0x02, 0xe8, 0x55, 0x7c, 0xc6, 0x06, 0x45,
+ 0x33, 0xd9, 0xb0, 0x02, 0xbe, 0x79, 0x03, 0xbb,
+ 0xb8, 0x6f, 0xe8, 0xda, 0x77, 0xb9, 0x1a, 0x00,
+ 0xb0, 0x03, 0xb4, 0x0a, 0xe8, 0xd6, 0x0b, 0xbb,
+ 0x47, 0x33, 0xc7, 0x47, 0x02, 0x7b, 0x03, 0xc7,
+ 0x47, 0x04, 0x7c, 0x03, 0xb0, 0x03, 0xe8, 0x29,
+ 0x7c, 0xc6, 0x06, 0x45, 0x33, 0xd0, 0xc6, 0x06,
+ 0x46, 0x33, 0xd9, 0xb0, 0x03, 0xb4, 0x02, 0xbe,
+ 0x7a, 0x03, 0xbf, 0x79, 0x03, 0xbb, 0xf0, 0x6f,
+ 0xe8, 0x1b, 0x76, 0xc3, 0xbb, 0x47, 0x33, 0xc7,
+ 0x47, 0x02, 0x7e, 0x03, 0xc7, 0x47, 0x04, 0x7d,
+ 0x03, 0xc7, 0x06, 0xf3, 0xb4, 0x20, 0x00, 0xe8,
+ 0xa2, 0x0e, 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x02,
+ 0x7e, 0x03, 0xc7, 0x47, 0x04, 0x7d, 0x03, 0xb0,
+ 0x02, 0xe8, 0xe6, 0x7b, 0xc6, 0x06, 0x45, 0x33,
+ 0xd9, 0xb0, 0x03, 0xbe, 0x7f, 0x03, 0xbb, 0x6e,
+ 0x70, 0xe8, 0x6b, 0x77, 0xb9, 0x4b, 0x00, 0xb0,
+ 0x09, 0xb4, 0x0b, 0xe8, 0x67, 0x0b, 0xbb, 0x47,
+ 0x33, 0xc7, 0x47, 0x02, 0x82, 0x03, 0xc7, 0x47,
+ 0x04, 0x81, 0x03, 0xb0, 0x02, 0xe8, 0xba, 0x7b,
+ 0xc6, 0x06, 0x45, 0x33, 0xd0, 0xc6, 0x06, 0x46,
+ 0x33, 0xd9, 0xb0, 0x02, 0xb4, 0x03, 0xbe, 0x80,
+ 0x03, 0xbf, 0x7f, 0x03, 0xbb, 0x96, 0x70, 0xe8,
+ 0xac, 0x75, 0xc3, 0xbb, 0x47, 0x33, 0xc7, 0x07,
+ 0x85, 0x03, 0xc7, 0x47, 0x02, 0x84, 0x03, 0xc7,
+ 0x06, 0xf3, 0xb4, 0x1d, 0x00, 0xe8, 0x34, 0x0e,
+ 0xbb, 0x47, 0x33, 0xc7, 0x07, 0x85, 0x03, 0xc7,
+ 0x47, 0x02, 0x84, 0x03, 0xb0, 0x02, 0xe8, 0x79,
+ 0x7b, 0xc6, 0x06, 0x45, 0x33, 0xd0, 0xc6, 0x06,
+ 0x46, 0x33, 0xd9, 0xb0, 0x01, 0xb4, 0x02, 0xbe,
+ 0x87, 0x03, 0xbf, 0x86, 0x03, 0xbb, 0x61, 0x71,
+ 0xe8, 0x6b, 0x75, 0xb9, 0x38, 0x00, 0xb0, 0x03,
+ 0xb4, 0x04, 0xe8, 0xf0, 0x0a, 0xb0, 0x05, 0xe8,
+ 0xf4, 0x0a, 0xb0, 0x07, 0xe8, 0xf6, 0x0a, 0xb0,
+ 0x09, 0xe8, 0xf8, 0x0a, 0xbb, 0x47, 0x33, 0xc7,
+ 0x07, 0x89, 0x03, 0xc7, 0x47, 0x02, 0x88, 0x03,
+ 0xb0, 0x01, 0xe8, 0x35, 0x7b, 0xb0, 0x01, 0xb4,
+ 0x02, 0xbe, 0x87, 0x03, 0xbf, 0x86, 0x03, 0xbb,
+ 0xc6, 0x71, 0xe8, 0x31, 0x75, 0xc3, 0xff, 0x36,
+ 0xf3, 0xb4, 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x02,
+ 0x8b, 0x03, 0xc7, 0x47, 0x04, 0x8a, 0x03, 0xc7,
+ 0x06, 0xf3, 0xb4, 0x23, 0x00, 0xe8, 0xb4, 0x0d,
+ 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x02, 0x8b, 0x03,
+ 0xc7, 0x47, 0x04, 0x8a, 0x03, 0xb0, 0x03, 0xe8,
+ 0xf8, 0x7a, 0xc6, 0x06, 0x45, 0x33, 0xd9, 0xc6,
+ 0x06, 0x46, 0x33, 0xd0, 0xb0, 0x03, 0xb4, 0x02,
+ 0xbe, 0x8c, 0x03, 0xbf, 0x8d, 0x03, 0xbb, 0x43,
+ 0x72, 0xe8, 0xea, 0x74, 0xc6, 0x06, 0x46, 0x33,
+ 0xd9, 0xc6, 0x06, 0x45, 0x33, 0xd0, 0xb0, 0x02,
+ 0xb4, 0x03, 0xbe, 0x8e, 0x03, 0xbf, 0x8c, 0x03,
+ 0xbb, 0x18, 0x73, 0xe8, 0xd0, 0x74, 0xc7, 0x06,
+ 0xf3, 0xb4, 0x0b, 0x00, 0xe8, 0x41, 0xa0, 0xc6,
+ 0x47, 0x03, 0x33, 0xe8, 0x5e, 0x0d, 0x58, 0x3d,
+ 0x0b, 0x00, 0x75, 0x08, 0xc6, 0x06, 0xdc, 0x1c,
+ 0x02, 0xe8, 0xba, 0x88, 0xbb, 0x47, 0x33, 0xc7,
+ 0x47, 0x02, 0x8f, 0x03, 0xb0, 0x02, 0xe8, 0x99,
+ 0x7a, 0xbb, 0x47, 0x33, 0xc7, 0x47, 0x02, 0x83,
+ 0x03, 0xb0, 0x02, 0xe8, 0x51, 0x7a, 0xe8, 0x13,
+ 0x0b, 0xb8, 0xc8, 0x00, 0xe8, 0x5b, 0x7f, 0xb0,
+ 0x08, 0xe8, 0xf5, 0x79, 0xb8, 0x02, 0x08, 0xe8,
+ 0x8f, 0x8e, 0xc7, 0x06, 0xec, 0xdb, 0x01, 0x00,
+ 0xc3, 0x06, 0xb8, 0x00, 0xa0, 0x8e, 0xc0, 0xe8,
+ 0x1d, 0x00, 0xb8, 0x00, 0xa0, 0xb9, 0x00, 0x7d,
+ 0xe8, 0xfd, 0x0c, 0xbe, 0x14, 0x77, 0xbb, 0x0a,
+ 0x58, 0xe8, 0x49, 0x04, 0xe8, 0x17, 0x00, 0xb8,
+ 0x96, 0x00, 0xe8, 0x47, 0x7f, 0x07, 0xc3, 0x80,
+ 0x3e, 0xad, 0x64, 0x01, 0x75, 0x04, 0xe8, 0xab,
+ 0x0c, 0xc3, 0xe8, 0xc1, 0x0c, 0xc3, 0x80, 0x3e,
+ 0xad, 0x64, 0x01, 0x75, 0x04, 0xe8, 0xa9, 0x0c,
+ 0xc3, 0xe8, 0xbf, 0x0c, 0xe8, 0x8a, 0x0c, 0xc3,
+ 0xa1, 0x50, 0x72, 0xe8, 0x07, 0x04, 0x83, 0xc3,
+ 0x13, 0x8a, 0x07, 0x43, 0x0a, 0xc0, 0x75, 0xf9,
+ 0x80, 0x3f, 0x00, 0x74, 0xf4, 0x80, 0x3f, 0x01,
+ 0x75, 0x03, 0xbb, 0x50, 0x34, 0xe8, 0x04, 0x00,
+ 0xe8, 0xb4, 0x00, 0xc3, 0x06, 0xb8, 0xd4, 0x19,
+ 0x8e, 0xc0, 0xe8, 0xe0, 0x02, 0x8b, 0x0e, 0xaf,
+ 0x64, 0x8b, 0xd0, 0x52, 0xd1, 0xea, 0x2b, 0xca,
+ 0x73, 0x03, 0xb9, 0x02, 0x00, 0x26, 0x89, 0x0e,
+ 0x00, 0x00, 0x5a, 0x03, 0xca, 0x81, 0xf9, 0x3f,
+ 0x01, 0x76, 0x0d, 0xb9, 0x3f, 0x01, 0x2b, 0xca,
+ 0x83, 0xe9, 0x02, 0x26, 0x89, 0x0e, 0x00, 0x00,
+ 0x83, 0xee, 0x02, 0x81, 0xfe, 0x04, 0x00, 0x72,
+ 0x0e, 0x26, 0x8b, 0x14, 0x8b, 0xc8, 0x2b, 0xca,
+ 0xd1, 0xe9, 0x26, 0x89, 0x0c, 0xeb, 0xe9, 0xc6,
+ 0x06, 0xe6, 0x1c, 0xd1, 0xe8, 0x77, 0x02, 0xb8,
+ 0x3e, 0x00, 0x8b, 0xc8, 0xf7, 0x26, 0xd8, 0x64,
+ 0xf7, 0x36, 0xda, 0x64, 0x2b, 0xc8, 0xa1, 0xb1,
+ 0x64, 0x2b, 0xc1, 0x72, 0x12, 0x05, 0x08, 0x00,
+ 0x26, 0x8b, 0x0e, 0x0a, 0x00, 0x41, 0x2d, 0x0b,
+ 0x00, 0x72, 0x04, 0xe2, 0xf9, 0xeb, 0x03, 0xb8,
+ 0x01, 0x00, 0xf7, 0x26, 0xb6, 0x00, 0x26, 0x01,
+ 0x06, 0x00, 0x00, 0xc6, 0x06, 0xdb, 0x1c, 0x02,
+ 0xe8, 0x8b, 0x87, 0xc6, 0x06, 0xdb, 0x1c, 0x03,
+ 0xbb, 0x92, 0x32, 0xa1, 0x96, 0x32, 0x26, 0x8b,
+ 0x0e, 0x0c, 0x00, 0xf7, 0xe1, 0x8b, 0xc8, 0xc1,
+ 0xe9, 0x03, 0x83, 0xc1, 0x3c, 0xe8, 0xdb, 0x07,
+ 0x07, 0xc6, 0x06, 0xe8, 0x64, 0x01, 0xc3, 0xe8,
+ 0xf4, 0x94, 0xe8, 0x70, 0x8a, 0x2e, 0x80, 0x3e,
+ 0xd7, 0x00, 0x01, 0x74, 0x19, 0x80, 0x3e, 0x96,
+ 0x32, 0x00, 0x74, 0x08, 0xbb, 0x92, 0x32, 0xe8,
+ 0xcc, 0x07, 0x72, 0x0a, 0xe8, 0xa4, 0x05, 0x72,
+ 0x05, 0xe8, 0x70, 0x05, 0x73, 0xd9, 0xe8, 0xfc,
+ 0x9c, 0xe8, 0x3d, 0x9d, 0xc6, 0x06, 0xdb, 0x1c,
+ 0x01, 0xc6, 0x06, 0xdc, 0x1c, 0x02, 0xe8, 0x2d,
+ 0x87, 0xc6, 0x06, 0xdc, 0x1c, 0x03, 0xc6, 0x06,
+ 0xdb, 0x1c, 0x00, 0xc3, 0x51, 0xe8, 0x04, 0xff,
+ 0x59, 0xbb, 0x92, 0x32, 0xe8, 0x84, 0x07, 0xe8,
+ 0xa4, 0x94, 0xe8, 0x20, 0x8a, 0xbb, 0x92, 0x32,
+ 0xe8, 0x8b, 0x07, 0x72, 0x0a, 0xe8, 0x63, 0x05,
+ 0x72, 0x05, 0xe8, 0x2f, 0x05, 0x73, 0xe8, 0xe8,
+ 0xbc, 0xff, 0xc3, 0xa0, 0x96, 0xda, 0xbf, 0xc7,
+ 0x32, 0xb1, 0x1b, 0x48, 0xf6, 0xe1, 0x03, 0xf8,
+ 0xa1, 0xa4, 0xda, 0x89, 0x05, 0x57, 0xe8, 0xcb,
+ 0xfe, 0x5f, 0x57, 0xa1, 0xa4, 0xda, 0x89, 0x05,
+ 0xe8, 0x6b, 0x94, 0xe8, 0xe7, 0x89, 0x5f, 0x57,
+ 0xa1, 0xa4, 0xda, 0x89, 0x05, 0x2e, 0x80, 0x3e,
+ 0xd7, 0x00, 0x01, 0x74, 0x19, 0x80, 0x3e, 0x96,
+ 0x32, 0x00, 0x74, 0x08, 0xbb, 0x92, 0x32, 0xe8,
+ 0x3c, 0x07, 0x72, 0x0a, 0xe8, 0x14, 0x05, 0x72,
+ 0x05, 0xe8, 0xe0, 0x04, 0x73, 0xcb, 0x5f, 0xe8,
+ 0x6c, 0xff, 0xc3, 0x06, 0xb8, 0xd4, 0x19, 0x8e,
+ 0xc0, 0x57, 0xe8, 0x70, 0x01, 0x5f, 0x50, 0x8b,
+ 0x45, 0x0a, 0x33, 0xd2, 0xf7, 0x36, 0xb6, 0x00,
+ 0x8b, 0x45, 0x0c, 0xd1, 0xe8, 0x03, 0xd0, 0x58,
+ 0x8b, 0xca, 0x8b, 0xd0, 0x52, 0xd1, 0xea, 0x2b,
+ 0xca, 0x73, 0x03, 0xb9, 0x02, 0x00, 0x26, 0x89,
+ 0x0e, 0x00, 0x00, 0x5a, 0x03, 0xca, 0x81, 0xf9,
+ 0x3f, 0x01, 0x76, 0x0b, 0xb9, 0x3f, 0x01, 0x2b,
+ 0xca, 0x49, 0x26, 0x89, 0x0e, 0x00, 0x00, 0x83,
+ 0xee, 0x02, 0x81, 0xfe, 0x04, 0x00, 0x72, 0x0e,
+ 0x26, 0x8b, 0x14, 0x8b, 0xc8, 0x2b, 0xca, 0xd1,
+ 0xe9, 0x26, 0x89, 0x0c, 0xeb, 0xe9, 0x57, 0xa0,
+ 0xe7, 0x1c, 0xa2, 0xe6, 0x1c, 0xe8, 0xf6, 0x00,
+ 0x5f, 0x8b, 0x45, 0x0a, 0x33, 0xd2, 0xf7, 0x36,
+ 0xb6, 0x00, 0x05, 0x08, 0x00, 0x26, 0x8b, 0x0e,
+ 0x0a, 0x00, 0x41, 0x2d, 0x0b, 0x00, 0x72, 0x04,
+ 0xe2, 0xf9, 0xeb, 0x03, 0xb8, 0x01, 0x00, 0xb9,
+ 0x40, 0x01, 0xf7, 0xe1, 0x26, 0x01, 0x06, 0x00,
+ 0x00, 0xc6, 0x06, 0xdb, 0x1c, 0x02, 0xe8, 0x15,
+ 0x86, 0xc6, 0x06, 0xdb, 0x1c, 0x03, 0xbb, 0x92,
+ 0x32, 0xa1, 0x96, 0x32, 0x26, 0x8b, 0x0e, 0x0c,
+ 0x00, 0xf7, 0xe1, 0x8b, 0xc8, 0xc1, 0xe9, 0x03,
+ 0x83, 0xc1, 0x3c, 0xe8, 0x65, 0x06, 0x07, 0xc3,
+ 0x06, 0xb8, 0xd4, 0x19, 0x8e, 0xc0, 0x26, 0x89,
+ 0x36, 0x00, 0x00, 0xe8, 0xb7, 0x00, 0x83, 0xee,
+ 0x02, 0x81, 0xfe, 0x04, 0x00, 0x72, 0x0e, 0x26,
+ 0x8b, 0x14, 0x8b, 0xc8, 0x2b, 0xca, 0xd1, 0xe9,
+ 0x26, 0x89, 0x0c, 0xeb, 0xe9, 0xe8, 0x7e, 0x00,
+ 0xc6, 0x06, 0xdb, 0x1c, 0x02, 0xe8, 0xc6, 0x85,
+ 0xc6, 0x06, 0xdb, 0x1c, 0x03, 0xbb, 0x92, 0x32,
+ 0xa1, 0x96, 0x32, 0x26, 0x8b, 0x0e, 0x0c, 0x00,
+ 0xf7, 0xe1, 0x8b, 0xc8, 0xc1, 0xe9, 0x03, 0x83,
+ 0xc1, 0x3c, 0xe8, 0x16, 0x06, 0x07, 0xc3, 0x06,
+ 0xb8, 0xd4, 0x19, 0x8e, 0xc0, 0x26, 0x89, 0x36,
+ 0x00, 0x00, 0x53, 0xe8, 0x63, 0x88, 0x5b, 0xe8,
+ 0x75, 0x00, 0x83, 0xee, 0x02, 0x81, 0xfe, 0x04,
+ 0x00, 0x72, 0x0e, 0x26, 0x8b, 0x14, 0x8b, 0xc8,
+ 0x2b, 0xca, 0xd1, 0xe9, 0x26, 0x89, 0x0c, 0xeb,
+ 0xe9, 0xe8, 0x2a, 0x00, 0x07, 0xc3, 0xe8, 0x7f,
+ 0xff, 0xe8, 0x81, 0x88, 0x80, 0x3e, 0x96, 0x32,
+ 0x00, 0x74, 0x08, 0xbb, 0x92, 0x32, 0xe8, 0xe5,
+ 0x05, 0x72, 0x0a, 0xe8, 0x8e, 0x03, 0x72, 0x05,
+ 0xe8, 0xb8, 0x03, 0x73, 0xe4, 0xc6, 0x06, 0xdb,
+ 0x1c, 0x01, 0xe8, 0x51, 0x85, 0xc3, 0xbf, 0x04,
+ 0x00, 0xbe, 0x0e, 0x00, 0x57, 0x56, 0x26, 0x03,
+ 0x35, 0xe8, 0x21, 0x01, 0x5e, 0x5f, 0x81, 0xc6,
+ 0xc0, 0x0d, 0x83, 0xc7, 0x02, 0x43, 0x8a, 0x07,
+ 0x0a, 0xc0, 0x75, 0xe8, 0xc3, 0x53, 0xc6, 0x06,
+ 0xda, 0x1c, 0x01, 0xe8, 0x28, 0x85, 0xc6, 0x06,
+ 0xda, 0x1c, 0x00, 0xe8, 0xeb, 0x87, 0x5b, 0x33,
+ 0xc0, 0x26, 0xa3, 0x0c, 0x00, 0x26, 0xa3, 0x0a,
+ 0x00, 0xbe, 0x04, 0x00, 0x53, 0xe8, 0x40, 0x01,
+ 0x26, 0x01, 0x0e, 0x0c, 0x00, 0x26, 0x89, 0x04,
+ 0x26, 0xff, 0x06, 0x0a, 0x00, 0x83, 0xc6, 0x02,
+ 0x43, 0x8a, 0x07, 0x0a, 0xc0, 0x75, 0xe6, 0x5b,
+ 0x8b, 0xce, 0x33, 0xc0, 0x83, 0xee, 0x02, 0x81,
+ 0xfe, 0x04, 0x00, 0x72, 0x0b, 0x26, 0x8b, 0x14,
+ 0x3b, 0xc2, 0x73, 0xf0, 0x8b, 0xc2, 0xeb, 0xec,
+ 0x8b, 0xf1, 0xc3, 0x8b, 0x0e, 0xc0, 0x00, 0x8b,
+ 0x16, 0xc2, 0x00, 0xa1, 0x52, 0x72, 0xa3, 0x50,
+ 0x72, 0x0b, 0xc0, 0x74, 0x54, 0xc6, 0x06, 0x3d,
+ 0x66, 0x05, 0x83, 0x3e, 0x1f, 0xc4, 0x00, 0x74,
+ 0x12, 0xe8, 0x16, 0x7c, 0x80, 0x3e, 0xdb, 0xbb,
+ 0x01, 0x74, 0x4f, 0xa1, 0x50, 0x72, 0xe8, 0x7c,
+ 0x00, 0xeb, 0x18, 0xc6, 0x06, 0x3d, 0x66, 0x01,
+ 0x0a, 0xdb, 0x74, 0x05, 0xc6, 0x06, 0x3d, 0x66,
+ 0x03, 0xe8, 0x69, 0x00, 0x80, 0x3e, 0x3d, 0x66,
+ 0x01, 0x75, 0x08, 0x8b, 0x77, 0x09, 0x8b, 0x7f,
+ 0x0b, 0xeb, 0x06, 0x8b, 0x77, 0x0d, 0x8b, 0x7f,
+ 0x0f, 0x8a, 0x47, 0x11, 0xa2, 0xc3, 0x64, 0xe8,
+ 0x38, 0x00, 0xe8, 0xa9, 0x97, 0x72, 0x2e, 0xeb,
+ 0x11, 0xc6, 0x06, 0x3d, 0x66, 0x00, 0xc6, 0x06,
+ 0xc3, 0x64, 0x00, 0x8b, 0xf1, 0x8b, 0xfa, 0xe8,
+ 0x24, 0x97, 0xc6, 0x06, 0xc5, 0x64, 0x00, 0xc6,
+ 0x06, 0xc6, 0x64, 0x01, 0x89, 0x36, 0xb7, 0x64,
+ 0x89, 0x3e, 0xb9, 0x64, 0x89, 0x36, 0xbb, 0x64,
+ 0x89, 0x3e, 0xbd, 0x64, 0xc3, 0xb0, 0x36, 0xe9,
+ 0x36, 0x0f, 0x83, 0xfe, 0xff, 0x75, 0x0d, 0x83,
+ 0xff, 0xff, 0x75, 0x08, 0x8b, 0x3e, 0xb1, 0x64,
+ 0x8b, 0x36, 0xaf, 0x64, 0xc3, 0x48, 0xbb, 0x54,
+ 0x72, 0x50, 0xe8, 0x8d, 0x9b, 0x58, 0xd1, 0xe0,
+ 0x03, 0xd8, 0x8b, 0x1f, 0xc3, 0x8a, 0x0f, 0x0a,
+ 0xc9, 0x74, 0x4c, 0x80, 0xe9, 0x1f, 0xb5, 0x00,
+ 0xbf, 0x38, 0x01, 0xd1, 0xe1, 0x03, 0xf9, 0x8b,
+ 0x3d, 0x81, 0xc7, 0x3a, 0x01, 0x8b, 0x0d, 0x83,
+ 0xc7, 0x02, 0x8a, 0x26, 0xe6, 0x1c, 0x51, 0x56,
+ 0x51, 0x56, 0x8a, 0x05, 0x0a, 0xc0, 0x74, 0x0b,
+ 0xfe, 0xc8, 0x0a, 0xc0, 0x74, 0x02, 0x8a, 0xc4,
+ 0x26, 0x88, 0x04, 0x47, 0x46, 0xfe, 0xcd, 0x75,
+ 0xe9, 0x5e, 0x59, 0x81, 0xc6, 0x40, 0x01, 0xfe,
+ 0xc9, 0x75, 0xdd, 0x5e, 0x59, 0x8a, 0xc5, 0xb4,
+ 0x00, 0x03, 0xf0, 0x4e, 0x43, 0xeb, 0xae, 0xc3,
+ 0x52, 0x33, 0xc0, 0x8b, 0xd0, 0x8a, 0x0f, 0x0a,
+ 0xc9, 0x74, 0x1f, 0x42, 0x80, 0xe9, 0x1f, 0xb5,
+ 0x00, 0xbf, 0x38, 0x01, 0xd1, 0xe1, 0x03, 0xf9,
+ 0x8b, 0x3d, 0x81, 0xc7, 0x3a, 0x01, 0x8b, 0x0d,
+ 0x8a, 0xcd, 0xb5, 0x00, 0x03, 0xc1, 0x48, 0x43,
+ 0xeb, 0xdb, 0x8b, 0xca, 0x5a, 0xc3, 0xb8, 0x04,
+ 0x00, 0xe8, 0x87, 0x0c, 0xbb, 0x9e, 0x33, 0xd1,
+ 0xe0, 0x03, 0xd8, 0x8b, 0x1f, 0xe8, 0x6d, 0xfb,
+ 0xc3, 0x33, 0xc0, 0xcd, 0x33, 0x0b, 0xc0, 0x74,
+ 0x01, 0xc3, 0xc6, 0x06, 0xd9, 0x00, 0x01, 0xba,
+ 0x5f, 0x33, 0xb4, 0x09, 0xcd, 0x21, 0xb4, 0x08,
+ 0xcd, 0x21, 0xc3, 0x06, 0xba, 0x00, 0xa0, 0x8e,
+ 0xc2, 0x50, 0xe8, 0xfe, 0x00, 0x58, 0x80, 0x3e,
+ 0xd8, 0x00, 0x00, 0x74, 0x02, 0x07, 0xc3, 0x0a,
+ 0xc0, 0x75, 0x12, 0xa1, 0xc0, 0x00, 0x3b, 0x06,
+ 0xc4, 0x00, 0x75, 0x09, 0xa1, 0xc2, 0x00, 0x3b,
+ 0x06, 0xc6, 0x00, 0x74, 0x58, 0xe8, 0x57, 0x00,
+ 0xba, 0x40, 0x01, 0xa1, 0xc2, 0x00, 0xa3, 0xc6,
+ 0x00, 0xf7, 0xe2, 0x8b, 0xf0, 0xa1, 0xc0, 0x00,
+ 0xa3, 0xc4, 0x00, 0x03, 0xf0, 0x89, 0x36, 0xc8,
+ 0x00, 0xba, 0x08, 0x00, 0xb8, 0x40, 0x01, 0x2b,
+ 0x06, 0xc0, 0x00, 0x3b, 0xc2, 0x77, 0x02, 0x8b,
+ 0xd0, 0xbb, 0xda, 0x00, 0xb9, 0x0c, 0x00, 0x8b,
+ 0xf9, 0x8b, 0xca, 0x8a, 0x07, 0x3c, 0x01, 0x74,
+ 0x03, 0x26, 0x88, 0x04, 0x43, 0x46, 0xe2, 0xf3,
+ 0x8b, 0xcf, 0x81, 0xc6, 0x40, 0x01, 0x83, 0xc3,
+ 0x08, 0x2b, 0xf2, 0x2b, 0xda, 0x81, 0xfe, 0xff,
+ 0xf9, 0x73, 0x02, 0xe2, 0xda, 0x07, 0xc3, 0x1e,
+ 0xba, 0x40, 0x01, 0xa1, 0xc6, 0x00, 0xf7, 0xe2,
+ 0x8b, 0xf0, 0x03, 0x36, 0xc4, 0x00, 0xba, 0x08,
+ 0x00, 0xb8, 0x40, 0x01, 0x2b, 0x06, 0xc4, 0x00,
+ 0x3b, 0xc2, 0x77, 0x02, 0x8b, 0xd0, 0x8b, 0x1e,
+ 0xc8, 0x00, 0xb9, 0x0c, 0x00, 0xa1, 0xb1, 0x32,
+ 0x8e, 0xd8, 0x8b, 0xf9, 0x8b, 0xca, 0x8a, 0x07,
+ 0x26, 0x88, 0x04, 0x43, 0x46, 0xe2, 0xf7, 0x8b,
+ 0xcf, 0x81, 0xc3, 0x40, 0x01, 0x81, 0xc6, 0x40,
+ 0x01, 0x2b, 0xda, 0x2b, 0xf2, 0x81, 0xfe, 0xff,
+ 0xf9, 0x73, 0x02, 0xe2, 0xdd, 0x1f, 0xc3, 0xb0,
+ 0x01, 0xe8, 0x27, 0xff, 0xc3, 0xc6, 0x06, 0xd8,
+ 0x00, 0x01, 0x06, 0x9c, 0xb8, 0x00, 0xa0, 0x8e,
+ 0xc0, 0xfa, 0xe8, 0x9a, 0xff, 0xa1, 0xc0, 0x00,
+ 0xa3, 0xc4, 0x00, 0xa1, 0xc2, 0x00, 0xa3, 0xc6,
+ 0x00, 0xe8, 0x8b, 0xff, 0x9d, 0x07, 0xc3, 0xc6,
+ 0x06, 0xd8, 0x00, 0x00, 0x9c, 0xfa, 0xe8, 0xce,
+ 0xff, 0x9d, 0xc3, 0xc6, 0x06, 0xca, 0x00, 0x00,
+ 0xc6, 0x06, 0xcb, 0x00, 0x00, 0x8b, 0x0e, 0xc0,
+ 0x00, 0x8b, 0x16, 0xc2, 0x00, 0x33, 0xdb, 0x2e,
+ 0xa0, 0xd7, 0x00, 0x3c, 0x4d, 0x75, 0x09, 0x81,
+ 0xf9, 0x3f, 0x01, 0x73, 0x36, 0x41, 0xeb, 0x33,
+ 0x3c, 0x4b, 0x75, 0x07, 0x0b, 0xc9, 0x74, 0x2b,
+ 0x49, 0xeb, 0x28, 0x3c, 0x48, 0x75, 0x07, 0x0b,
+ 0xd2, 0x74, 0x20, 0x4a, 0xeb, 0x1d, 0x3c, 0x50,
+ 0x75, 0x09, 0x81, 0xfa, 0xc7, 0x00, 0x73, 0x13,
+ 0x42, 0xeb, 0x10, 0x3c, 0x1d, 0x75, 0x05, 0x80,
+ 0xcb, 0x01, 0xeb, 0x07, 0x3c, 0x38, 0x75, 0x19,
+ 0x80, 0xcb, 0x02, 0x80, 0x3e, 0xd9, 0x00, 0x01,
+ 0x74, 0x1d, 0x53, 0x51, 0x52, 0xd1, 0xe1, 0xb8,
+ 0x04, 0x00, 0xcd, 0x33, 0x5a, 0x59, 0x5b, 0xeb,
+ 0x0e, 0x80, 0x3e, 0xd9, 0x00, 0x01, 0x74, 0x07,
+ 0xb8, 0x03, 0x00, 0xcd, 0x33, 0xd1, 0xe9, 0x89,
+ 0x0e, 0xc0, 0x00, 0x89, 0x16, 0xc2, 0x00, 0xf6,
+ 0xc3, 0x02, 0x74, 0x05, 0xc6, 0x06, 0xcb, 0x00,
+ 0x01, 0xf6, 0xc3, 0x01, 0x74, 0x05, 0xc6, 0x06,
+ 0xca, 0x00, 0x01, 0xc3, 0x80, 0x3e, 0xcf, 0x00,
+ 0x02, 0x75, 0x07, 0xc6, 0x06, 0xcf, 0x00, 0x00,
+ 0xeb, 0x0e, 0x80, 0x3e, 0xcb, 0x00, 0x00, 0x74,
+ 0x13, 0x80, 0x3e, 0xcd, 0x00, 0x01, 0x74, 0x11,
+ 0xc6, 0x06, 0xcb, 0x00, 0x01, 0xc6, 0x06, 0xcd,
+ 0x00, 0x01, 0xf9, 0xc3, 0xc6, 0x06, 0xcd, 0x00,
+ 0x00, 0xf8, 0xc3, 0x80, 0x3e, 0xcf, 0x00, 0x04,
+ 0x75, 0x07, 0xc6, 0x06, 0xcf, 0x00, 0x00, 0xeb,
+ 0x0e, 0x80, 0x3e, 0xca, 0x00, 0x00, 0x74, 0x13,
+ 0x80, 0x3e, 0xcc, 0x00, 0x01, 0x74, 0x11, 0xc6,
+ 0x06, 0xca, 0x00, 0x01, 0xc6, 0x06, 0xcc, 0x00,
+ 0x01, 0xf9, 0xc3, 0xc6, 0x06, 0xcc, 0x00, 0x00,
+ 0xf8, 0xc3, 0xe8, 0x06, 0xff, 0xe8, 0xcb, 0xff,
+ 0x72, 0x05, 0xe8, 0x97, 0xff, 0x73, 0xf3, 0xc3,
+ 0x50, 0x52, 0xba, 0xda, 0x03, 0xec, 0xa8, 0x08,
+ 0x75, 0xf8, 0xec, 0xa8, 0x08, 0x74, 0xfb, 0x5a,
+ 0x58, 0xc3, 0x1e, 0x8e, 0xda, 0xb7, 0x00, 0x2a,
+ 0xf8, 0x8a, 0xe7, 0xf6, 0xc7, 0x80, 0x74, 0x04,
+ 0xb4, 0x40, 0x02, 0xe7, 0x50, 0xa8, 0x80, 0x74,
+ 0x04, 0x34, 0xff, 0xfe, 0xc0, 0xb4, 0x00, 0x8b,
+ 0xc8, 0xb8, 0x40, 0x00, 0x33, 0xd2, 0xf7, 0xf1,
+ 0x8b, 0xc8, 0x58, 0xfc, 0x50, 0x51, 0x56, 0xb9,
+ 0x40, 0x00, 0xfb, 0xe8, 0xba, 0xff, 0xfa, 0xba,
+ 0xc8, 0x03, 0x32, 0xc0, 0xee, 0x42, 0xfa, 0xac,
+ 0x2a, 0xc4, 0x73, 0x02, 0x32, 0xc0, 0xee, 0xac,
+ 0x2a, 0xc4, 0x73, 0x02, 0x32, 0xc0, 0xee, 0xac,
+ 0x2a, 0xc4, 0x73, 0x02, 0x32, 0xc0, 0xee, 0xac,
+ 0x2a, 0xc4, 0x73, 0x02, 0x32, 0xc0, 0xee, 0xac,
+ 0x2a, 0xc4, 0x73, 0x02, 0x32, 0xc0, 0xee, 0xac,
+ 0x2a, 0xc4, 0x73, 0x02, 0x32, 0xc0, 0xee, 0xe2,
+ 0xce, 0xfb, 0xb9, 0x40, 0x00, 0xe8, 0x78, 0xff,
+ 0xfa, 0xac, 0x2a, 0xc4, 0x73, 0x02, 0x32, 0xc0,
+ 0xee, 0xac, 0x2a, 0xc4, 0x73, 0x02, 0x32, 0xc0,
+ 0xee, 0xac, 0x2a, 0xc4, 0x73, 0x02, 0x32, 0xc0,
+ 0xee, 0xac, 0x2a, 0xc4, 0x73, 0x02, 0x32, 0xc0,
+ 0xee, 0xac, 0x2a, 0xc4, 0x73, 0x02, 0x32, 0xc0,
+ 0xee, 0xac, 0x2a, 0xc4, 0x73, 0x02, 0x32, 0xc0,
+ 0xee, 0xe2, 0xce, 0xfb, 0x5e, 0x59, 0x58, 0x02,
+ 0xe7, 0x49, 0x74, 0x03, 0xe9, 0x75, 0xff, 0x1f,
+ 0xc3, 0xbb, 0x3e, 0x66, 0xe8, 0xfb, 0x97, 0x8b,
+ 0x36, 0xaf, 0x64, 0x8b, 0x3e, 0xb1, 0x64, 0x8b,
+ 0x07, 0x3d, 0xff, 0xff, 0x74, 0x25, 0x53, 0x8b,
+ 0x4f, 0x04, 0x8b, 0x57, 0x06, 0x8b, 0x5f, 0x02,
+ 0xe8, 0x1c, 0x00, 0x5b, 0x72, 0x05, 0x83, 0xc3,
+ 0x09, 0xeb, 0xe4, 0x8a, 0x47, 0x08, 0x3a, 0x06,
+ 0x08, 0x66, 0x74, 0x06, 0xa2, 0x08, 0x66, 0xe8,
+ 0x19, 0x00, 0xc3, 0x32, 0xc0, 0xeb, 0xef, 0x3b,
+ 0xf0, 0x72, 0x0e, 0x3b, 0xf1, 0x77, 0x0a, 0x3b,
+ 0xfb, 0x72, 0x06, 0x3b, 0xfa, 0x77, 0x02, 0xf9,
+ 0xc3, 0xf8, 0xc3, 0x80, 0x3e, 0xad, 0x64, 0x00,
+ 0x74, 0x31, 0xbe, 0x09, 0x66, 0xb9, 0x0d, 0x00,
+ 0xb3, 0xf2, 0x51, 0x8a, 0x24, 0x8a, 0x6c, 0x01,
+ 0x8a, 0x4c, 0x02, 0x2a, 0xe0, 0x73, 0x02, 0x32,
+ 0xe4, 0x2a, 0xe8, 0x73, 0x02, 0x32, 0xed, 0x2a,
+ 0xc8, 0x73, 0x02, 0x32, 0xc9, 0x50, 0xe8, 0x37,
+ 0x00, 0x58, 0x83, 0xc6, 0x03, 0xfe, 0xc3, 0x59,
+ 0xe2, 0xd8, 0xc3, 0xbe, 0x30, 0x66, 0xb9, 0x0d,
+ 0x00, 0xb3, 0xf2, 0x51, 0x8a, 0x24, 0x8a, 0xec,
+ 0x8a, 0xcc, 0x2a, 0xe0, 0x73, 0x02, 0x32, 0xe4,
+ 0x2a, 0xe8, 0x73, 0x02, 0x32, 0xed, 0x2a, 0xc8,
+ 0x73, 0x02, 0x32, 0xc9, 0x50, 0xe8, 0x08, 0x00,
+ 0x58, 0x46, 0xfe, 0xc3, 0x59, 0xe2, 0xdc, 0xc3,
+ 0xba, 0xc8, 0x03, 0x8a, 0xc3, 0xee, 0xeb, 0x00,
+ 0x42, 0x8a, 0xc4, 0xee, 0xeb, 0x00, 0x8a, 0xc5,
+ 0xee, 0xeb, 0x00, 0x8a, 0xc1, 0xee, 0xc3, 0x1e,
+ 0x06, 0xa1, 0xb1, 0x32, 0x8e, 0xc0, 0xa1, 0xb3,
+ 0x32, 0x8e, 0xd8, 0x33, 0xff, 0x33, 0xf6, 0xb9,
+ 0x00, 0x7d, 0xfc, 0xf3, 0xa5, 0x07, 0x1f, 0xc3,
+ 0x1e, 0x06, 0xe8, 0x4b, 0xfe, 0xb8, 0x00, 0xa0,
+ 0x8e, 0xc0, 0xa1, 0xb1, 0x32, 0x8e, 0xd8, 0x33,
+ 0xff, 0x33, 0xf6, 0xb9, 0x00, 0x7d, 0xfc, 0xf3,
+ 0xa5, 0x07, 0x1f, 0xc3, 0xe8, 0xe1, 0xff, 0xe8,
+ 0xf5, 0xfc, 0xc3, 0xbe, 0x86, 0x32, 0x8b, 0x04,
+ 0x8b, 0x54, 0x02, 0x03, 0xc1, 0x73, 0x01, 0x42,
+ 0x89, 0x07, 0x89, 0x57, 0x02, 0xc3, 0xbe, 0x86,
+ 0x32, 0x8b, 0x04, 0x8b, 0x54, 0x02, 0x8b, 0x4f,
+ 0x02, 0x8b, 0x37, 0x3b, 0xd1, 0x77, 0x08, 0x72,
+ 0x04, 0x3b, 0xc6, 0x73, 0x02, 0xf8, 0xc3, 0xf9,
+ 0xc3, 0x8a, 0x0e, 0x42, 0x32, 0xb5, 0x00, 0x80,
+ 0xf9, 0x01, 0x75, 0x05, 0xc6, 0x06, 0xa8, 0x64,
+ 0x04, 0x80, 0xf9, 0x03, 0x75, 0x05, 0xc6, 0x06,
+ 0xa8, 0x64, 0x05, 0x80, 0xf9, 0x04, 0x75, 0x05,
+ 0xc6, 0x06, 0xa8, 0x64, 0x05, 0xba, 0x44, 0x00,
+ 0xa1, 0xc1, 0x32, 0xa3, 0xac, 0x00, 0xc7, 0x06,
+ 0xaa, 0x00, 0x00, 0x01, 0xe8, 0x29, 0x06, 0xb8,
+ 0x00, 0x01, 0xa3, 0x4a, 0x32, 0xa1, 0xc1, 0x32,
+ 0xa3, 0x4c, 0x32, 0xb4, 0x01, 0x8b, 0x1e, 0x43,
+ 0x32, 0x8b, 0x0e, 0xc3, 0x32, 0x8b, 0x3e, 0xc5,
+ 0x32, 0x8a, 0x16, 0x45, 0x32, 0x8a, 0x36, 0x46,
+ 0x32, 0xff, 0x1e, 0x4a, 0x32, 0xb8, 0x3b, 0x0b,
+ 0x8e, 0xd8, 0x8e, 0xc0, 0xc3, 0xe8, 0x3b, 0x00,
+ 0xbb, 0x4e, 0x32, 0xba, 0x0a, 0x00, 0x8b, 0x3e,
+ 0x7d, 0x32, 0x8b, 0x0f, 0x0b, 0xc9, 0x74, 0x25,
+ 0x8a, 0x47, 0x03, 0xa2, 0x7c, 0x32, 0x33, 0xc0,
+ 0x89, 0x07, 0x89, 0x47, 0x02, 0x3b, 0xf9, 0x74,
+ 0x13, 0x89, 0x0e, 0x7d, 0x32, 0xb0, 0x01, 0xb4,
+ 0x05, 0xff, 0x1e, 0x4a, 0x32, 0xb8, 0x3b, 0x0b,
+ 0x8e, 0xd8, 0x8e, 0xc0, 0xc3, 0x83, 0xc3, 0x04,
+ 0x4a, 0x75, 0xcf, 0xc7, 0x06, 0x7a, 0x32, 0x00,
+ 0x00, 0xba, 0x0a, 0x00, 0xbb, 0x4e, 0x32, 0x8b,
+ 0x0f, 0x0b, 0xc9, 0x74, 0x07, 0x8a, 0x47, 0x02,
+ 0xa2, 0x7a, 0x32, 0xc3, 0x83, 0xc3, 0x04, 0x4a,
+ 0x75, 0xed, 0xc3, 0xe8, 0xdd, 0xff, 0xbb, 0x4e,
+ 0x32, 0xba, 0x0a, 0x00, 0x8b, 0x0f, 0x0b, 0xc9,
+ 0x74, 0x14, 0x89, 0x0e, 0x7d, 0x32, 0xb0, 0x01,
+ 0xb4, 0x05, 0xff, 0x1e, 0x4a, 0x32, 0xb8, 0x3b,
+ 0x0b, 0x8e, 0xd8, 0x8e, 0xc0, 0xc3, 0x83, 0xc3,
+ 0x04, 0x4a, 0x75, 0xe0, 0xc3, 0xbb, 0x4e, 0x32,
+ 0x89, 0x0f, 0x89, 0x47, 0x02, 0xc3, 0x89, 0x4f,
+ 0x04, 0x89, 0x47, 0x06, 0xc3, 0x89, 0x4f, 0x08,
+ 0x89, 0x47, 0x0a, 0xc3, 0x89, 0x4f, 0x0c, 0x89,
+ 0x47, 0x0e, 0xc3, 0x89, 0x4f, 0x10, 0x89, 0x47,
+ 0x12, 0xc3, 0x89, 0x4f, 0x14, 0x89, 0x47, 0x16,
+ 0xc3, 0x89, 0x4f, 0x18, 0x89, 0x47, 0x1a, 0xc3,
+ 0x89, 0x4f, 0x1c, 0x89, 0x47, 0x1e, 0xc3, 0x89,
+ 0x4f, 0x20, 0x89, 0x47, 0x22, 0xc3, 0x89, 0x4f,
+ 0x24, 0x89, 0x47, 0x26, 0xc3, 0x81, 0xe9, 0xf3,
+ 0x01, 0xba, 0x2c, 0x00, 0xa1, 0xbf, 0x32, 0xa3,
+ 0xac, 0x00, 0xc7, 0x06, 0xaa, 0x00, 0x00, 0x00,
+ 0xe8, 0x15, 0x05, 0xc3, 0xbe, 0xc7, 0x32, 0xbb,
+ 0x47, 0x33, 0xb9, 0x01, 0x00, 0x53, 0x51, 0x56,
+ 0x49, 0xb0, 0x1b, 0xf6, 0xe1, 0x03, 0xf0, 0xd1,
+ 0xe1, 0x03, 0xd9, 0x8b, 0x0f, 0x0b, 0xc9, 0x74,
+ 0x1b, 0x81, 0xe9, 0xf3, 0x01, 0xba, 0x2c, 0x00,
+ 0x8b, 0x44, 0x16, 0xa3, 0xac, 0x00, 0xc7, 0x06,
+ 0xaa, 0x00, 0x00, 0x00, 0xe8, 0xe1, 0x04, 0xb8,
+ 0x01, 0x00, 0x89, 0x04, 0x5e, 0x59, 0x5b, 0x41,
+ 0x80, 0xf9, 0x04, 0x76, 0xc8, 0xc3, 0xbe, 0xc7,
+ 0x32, 0xbb, 0x47, 0x33, 0xb9, 0x01, 0x00, 0x53,
+ 0x51, 0x56, 0x8b, 0xd1, 0x49, 0xb0, 0x1b, 0xf6,
+ 0xe1, 0x03, 0xf0, 0xd1, 0xe1, 0x03, 0xd9, 0x8b,
+ 0x07, 0x0b, 0xc0, 0x74, 0x26, 0x8b, 0x0e, 0xf3,
+ 0xb4, 0x49, 0xc1, 0xe1, 0x02, 0x03, 0xca, 0xba,
+ 0x38, 0x00, 0xe8, 0x2b, 0x00, 0x8b, 0x44, 0x16,
+ 0xa3, 0xac, 0x00, 0xc7, 0x06, 0xaa, 0x00, 0x00,
+ 0x00, 0x56, 0xe8, 0x93, 0x04, 0x5e, 0xb8, 0x01,
+ 0x00, 0x89, 0x04, 0x5e, 0x59, 0x5b, 0x41, 0x80,
+ 0xf9, 0x04, 0x76, 0xbb, 0xbf, 0x47, 0x33, 0xb9,
+ 0x08, 0x00, 0x33, 0xc0, 0xfc, 0xf3, 0xab, 0xc3,
+ 0x83, 0xf9, 0x51, 0x75, 0x0e, 0x80, 0x3e, 0xad,
+ 0xdb, 0x01, 0x75, 0x07, 0xb9, 0xa0, 0x00, 0xba,
+ 0x2c, 0x00, 0xc3, 0x81, 0xf9, 0x89, 0x00, 0x75,
+ 0x1c, 0x80, 0x3e, 0xc5, 0xdb, 0x01, 0x75, 0x15,
+ 0x80, 0x3e, 0xc6, 0xdb, 0x01, 0x75, 0x07, 0xb9,
+ 0xcb, 0x00, 0xba, 0x2c, 0x00, 0xc3, 0xb9, 0xca,
+ 0x00, 0xba, 0x2c, 0x00, 0xc3, 0x83, 0xf9, 0x19,
+ 0x75, 0x0e, 0x80, 0x3e, 0xdf, 0xdb, 0x02, 0x75,
+ 0x07, 0xb9, 0x4c, 0x01, 0xba, 0x2c, 0x00, 0xc3,
+ 0x83, 0xf9, 0x25, 0x75, 0x1c, 0x80, 0x3e, 0xe2,
+ 0xdb, 0x01, 0x75, 0x07, 0xb9, 0x5f, 0x01, 0xba,
+ 0x2c, 0x00, 0xc3, 0x80, 0x3e, 0xe2, 0xdb, 0x02,
+ 0x75, 0x07, 0xb9, 0x6c, 0x01, 0xba, 0x2c, 0x00,
+ 0xc3, 0x80, 0x3e, 0xe7, 0xdb, 0x01, 0x75, 0x18,
+ 0x83, 0xf9, 0x1d, 0x75, 0x07, 0xb9, 0x7c, 0x01,
+ 0xba, 0x2c, 0x00, 0xc3, 0x83, 0xf9, 0x1e, 0x75,
+ 0x07, 0xb9, 0x7d, 0x01, 0xba, 0x2c, 0x00, 0xc3,
+ 0x83, 0x3e, 0xec, 0xdb, 0x01, 0x75, 0x0b, 0x83,
+ 0xf9, 0x2a, 0x75, 0x06, 0xb9, 0x90, 0x01, 0xba,
+ 0x2c, 0x00, 0xc3, 0xa1, 0xbf, 0x32, 0xa3, 0xac,
+ 0x00, 0x33, 0xc0, 0xa3, 0xaa, 0x00, 0xb9, 0x01,
+ 0x00, 0xba, 0x54, 0x00, 0xe8, 0xc9, 0x03, 0xc3,
+ 0x8b, 0x0e, 0xf3, 0xb4, 0xba, 0x25, 0x00, 0xa1,
+ 0xb5, 0x32, 0xa3, 0xac, 0x00, 0x33, 0xc0, 0xa3,
+ 0xaa, 0x00, 0xe8, 0xb3, 0x03, 0x83, 0x3e, 0xf3,
+ 0xb4, 0x07, 0x75, 0x11, 0xa0, 0xe6, 0xdb, 0x3c,
+ 0x02, 0x74, 0x0a, 0xe8, 0x08, 0x00, 0x3c, 0x01,
+ 0x74, 0x03, 0xe8, 0x01, 0x00, 0xc3, 0x1e, 0x8b,
+ 0x16, 0xb5, 0x32, 0x8e, 0xda, 0x33, 0xdb, 0xff,
+ 0x0f, 0x1f, 0xc3, 0xe8, 0x0f, 0x00, 0xe8, 0xf0,
+ 0xfb, 0xe8, 0x3b, 0x00, 0xc6, 0x06, 0x08, 0x66,
+ 0xfe, 0xe8, 0xe5, 0xfb, 0xc3, 0x89, 0x3e, 0xb7,
+ 0x64, 0x89, 0x36, 0xb9, 0x64, 0x89, 0x3e, 0xbb,
+ 0x64, 0x89, 0x36, 0xbd, 0x64, 0xa3, 0xaf, 0x64,
+ 0x89, 0x1e, 0xb1, 0x64, 0x88, 0x2e, 0xc3, 0x64,
+ 0x88, 0x0e, 0x07, 0x66, 0xe8, 0x49, 0x92, 0xc6,
+ 0x06, 0xdc, 0x1c, 0x02, 0xc6, 0x06, 0xda, 0x1c,
+ 0x01, 0xc6, 0x06, 0xc6, 0x64, 0x01, 0xc3, 0xc6,
+ 0x06, 0xc5, 0x64, 0x00, 0xc6, 0x06, 0x3d, 0x66,
+ 0x00, 0xc6, 0x06, 0x40, 0x67, 0xff, 0xc6, 0x06,
+ 0xc4, 0x64, 0x01, 0xe8, 0x12, 0x89, 0x80, 0x3e,
+ 0xad, 0x64, 0x01, 0x75, 0x0a, 0xe8, 0x84, 0x00,
+ 0xe8, 0x1d, 0x00, 0xe8, 0x8b, 0x00, 0xc3, 0xe8,
+ 0x94, 0x00, 0xe8, 0x13, 0x00, 0xb8, 0x00, 0xa0,
+ 0xb9, 0x00, 0x7d, 0xe8, 0xa2, 0x00, 0xe8, 0x92,
+ 0x00, 0xe8, 0x5d, 0x00, 0xe8, 0x59, 0xfc, 0xc3,
+ 0xe8, 0xa2, 0x01, 0xe8, 0x01, 0x00, 0xc3, 0xe8,
+ 0xf0, 0x05, 0xe8, 0x0f, 0x01, 0xe8, 0x2f, 0xfc,
+ 0xe8, 0x45, 0xfc, 0xff, 0x36, 0xce, 0x64, 0xc7,
+ 0x06, 0xce, 0x64, 0xff, 0xff, 0xe8, 0x86, 0x8f,
+ 0x8f, 0x06, 0xce, 0x64, 0xc6, 0x06, 0x33, 0x33,
+ 0x01, 0xe8, 0x22, 0x00, 0xc6, 0x06, 0xdd, 0x1c,
+ 0x02, 0xe8, 0xda, 0x7b, 0xbb, 0xa4, 0x32, 0x8b,
+ 0x0e, 0x90, 0x32, 0xe8, 0x3d, 0xfc, 0xc6, 0x06,
+ 0x33, 0x33, 0x00, 0xc6, 0x06, 0xdc, 0x1c, 0x03,
+ 0xc6, 0x06, 0xdd, 0x1c, 0x03, 0xc3, 0xbb, 0xa4,
+ 0x32, 0x33, 0xc0, 0x89, 0x07, 0x89, 0x47, 0x02,
+ 0xc3, 0xb8, 0x1b, 0x10, 0x33, 0xdb, 0xb9, 0xff,
+ 0x00, 0xcd, 0x10, 0xc3, 0x8b, 0x16, 0xb3, 0x32,
+ 0xbe, 0x00, 0xfa, 0xb0, 0xf0, 0xe8, 0x4a, 0xfa,
+ 0xc3, 0x8b, 0x16, 0xb3, 0x32, 0xbe, 0x00, 0xfa,
+ 0xb0, 0x10, 0xe8, 0x3d, 0xfa, 0xc3, 0x8b, 0x16,
+ 0xb3, 0x32, 0xbe, 0x00, 0xfa, 0xb0, 0xc0, 0xe8,
+ 0x30, 0xfa, 0xc3, 0x8b, 0x16, 0xb3, 0x32, 0xbe,
+ 0x00, 0xfa, 0xb0, 0x20, 0xe8, 0x23, 0xfa, 0xc3,
+ 0x06, 0x8e, 0xc0, 0x33, 0xc0, 0x8b, 0xf8, 0xfc,
+ 0xf3, 0xab, 0x07, 0xc3, 0xc6, 0x06, 0xdc, 0x1c,
+ 0x01, 0xe8, 0x0f, 0x00, 0xc3, 0xc6, 0x06, 0xdc,
+ 0x1c, 0x02, 0xe8, 0x06, 0x00, 0xc6, 0x06, 0xdc,
+ 0x1c, 0x03, 0xc3, 0x80, 0x3e, 0xad, 0x64, 0x01,
+ 0x75, 0x0a, 0xe8, 0x9f, 0xff, 0xe8, 0x1d, 0x00,
+ 0xe8, 0xa6, 0xff, 0xc3, 0xe8, 0xaf, 0xff, 0xe8,
+ 0x13, 0x00, 0xb8, 0x00, 0xa0, 0xb9, 0x00, 0x7d,
+ 0xe8, 0xbd, 0xff, 0xe8, 0xad, 0xff, 0xe8, 0x78,
+ 0xff, 0xe8, 0x74, 0xfb, 0xc3, 0xe8, 0xbd, 0x00,
+ 0xe8, 0x0f, 0x05, 0xe8, 0x2e, 0x00, 0xe8, 0x03,
+ 0xfd, 0xe8, 0x4b, 0xfb, 0xe8, 0x61, 0xfb, 0xe8,
+ 0x54, 0xff, 0xc6, 0x06, 0x33, 0x33, 0x01, 0xc6,
+ 0x06, 0xdd, 0x1c, 0x02, 0xe8, 0x07, 0x7b, 0xbb,
+ 0xa4, 0x32, 0x8b, 0x0e, 0x90, 0x32, 0xe8, 0x6a,
+ 0xfb, 0xc6, 0x06, 0x33, 0x33, 0x00, 0xc6, 0x06,
+ 0xdd, 0x1c, 0x03, 0xc3, 0x55, 0xbf, 0xc7, 0x32,
+ 0xb9, 0x36, 0x00, 0x33, 0xc0, 0xfc, 0xf3, 0xab,
+ 0xbe, 0xc7, 0x32, 0xbb, 0x9e, 0xd8, 0xbd, 0x46,
+ 0xd9, 0xb9, 0x01, 0x00, 0x53, 0x51, 0x56, 0x55,
+ 0x8b, 0x16, 0xf3, 0xb4, 0x4a, 0xc1, 0xe2, 0x02,
+ 0x03, 0xda, 0x03, 0xd9, 0x4b, 0xd1, 0xe2, 0x03,
+ 0xea, 0x49, 0x03, 0xe9, 0x03, 0xe9, 0xb0, 0x1b,
+ 0xf6, 0xe1, 0x41, 0x03, 0xf0, 0x8a, 0x2f, 0x0a,
+ 0xed, 0x74, 0x3e, 0x8a, 0xd1, 0xb6, 0x00, 0x8b,
+ 0x0e, 0xf3, 0xb4, 0x49, 0xc1, 0xe1, 0x02, 0x03,
+ 0xca, 0x51, 0x3e, 0x8b, 0x5e, 0x00, 0x83, 0xc6,
+ 0x16, 0xe8, 0x4f, 0x04, 0x59, 0xba, 0x38, 0x00,
+ 0xe8, 0x15, 0xfd, 0x8b, 0x04, 0xa3, 0xac, 0x00,
+ 0xc7, 0x06, 0xaa, 0x00, 0x00, 0x00, 0x56, 0xe8,
+ 0x7e, 0x01, 0x5e, 0x83, 0xee, 0x16, 0xb8, 0x01,
+ 0x00, 0x89, 0x04, 0x89, 0x44, 0x12, 0x89, 0x44,
+ 0x14, 0x5d, 0x5e, 0x59, 0x5b, 0x41, 0x80, 0xf9,
+ 0x04, 0x76, 0x91, 0x5d, 0xc3, 0x8b, 0x0e, 0xf3,
+ 0xb4, 0xba, 0x1d, 0x00, 0xa1, 0xb3, 0x32, 0xa3,
+ 0xac, 0x00, 0x33, 0xc0, 0xa3, 0xaa, 0x00, 0xe8,
+ 0x4e, 0x01, 0xe8, 0x9e, 0x00, 0xe8, 0x80, 0xfd,
+ 0xc3, 0xe8, 0x04, 0x00, 0xe8, 0x91, 0xfa, 0xc3,
+ 0xe8, 0xda, 0xff, 0xff, 0x36, 0x33, 0x33, 0xff,
+ 0x36, 0xdc, 0x1c, 0xff, 0x36, 0xdd, 0x1c, 0xc6,
+ 0x06, 0x33, 0x33, 0x00, 0xc6, 0x06, 0xdc, 0x1c,
+ 0x03, 0xc6, 0x06, 0xdd, 0x1c, 0x03, 0xfe, 0x0e,
+ 0x07, 0x66, 0xe8, 0xae, 0x80, 0xe8, 0xa3, 0x7d,
+ 0xe8, 0x0c, 0x7f, 0xe8, 0xb2, 0xf8, 0xe8, 0xf8,
+ 0x85, 0xe8, 0xab, 0x7f, 0xe8, 0x70, 0xf7, 0x8f,
+ 0x06, 0xdd, 0x1c, 0x8f, 0x06, 0xdc, 0x1c, 0x8f,
+ 0x06, 0x33, 0x33, 0xc3, 0xe8, 0x96, 0xff, 0xff,
+ 0x36, 0x33, 0x33, 0xff, 0x36, 0xdc, 0x1c, 0xff,
+ 0x36, 0xdd, 0x1c, 0xc6, 0x06, 0x33, 0x33, 0x00,
+ 0xc6, 0x06, 0xdc, 0x1c, 0x03, 0xc6, 0x06, 0xdd,
+ 0x1c, 0x03, 0xe8, 0xe1, 0x79, 0x8f, 0x06, 0xdd,
+ 0x1c, 0x8f, 0x06, 0xdc, 0x1c, 0x8f, 0x06, 0x33,
+ 0x33, 0xc3, 0xe8, 0x68, 0xff, 0xff, 0x36, 0x33,
+ 0x33, 0xff, 0x36, 0xdd, 0x1c, 0xc6, 0x06, 0x33,
+ 0x33, 0x00, 0xc6, 0x06, 0xdd, 0x1c, 0x03, 0xe8,
+ 0xbc, 0x79, 0x8f, 0x06, 0xdd, 0x1c, 0x8f, 0x06,
+ 0x33, 0x33, 0xc3, 0x06, 0xa1, 0xb5, 0x32, 0x8e,
+ 0xc0, 0xa3, 0xac, 0x00, 0xc7, 0x06, 0xaa, 0x00,
+ 0x00, 0x00, 0xe8, 0x13, 0x91, 0x53, 0x8a, 0x0f,
+ 0x0a, 0xc9, 0x74, 0x17, 0x80, 0xf9, 0xff, 0x74,
+ 0x16, 0xb5, 0x00, 0xba, 0x4c, 0x00, 0xe8, 0x87,
+ 0x00, 0xa1, 0xb3, 0x32, 0x8b, 0x1e, 0xaa, 0x00,
+ 0xe8, 0xb9, 0x6a, 0x5b, 0x43, 0xeb, 0xde, 0x5b,
+ 0x07, 0xc3, 0x06, 0x8b, 0x16, 0xb5, 0x32, 0x8e,
+ 0xc2, 0x89, 0x16, 0xac, 0x00, 0xc7, 0x06, 0xaa,
+ 0x00, 0x00, 0x00, 0x8a, 0xc8, 0xb5, 0x00, 0xba,
+ 0x4c, 0x00, 0xe8, 0x5b, 0x00, 0xa1, 0xb3, 0x32,
+ 0x8b, 0x1e, 0xaa, 0x00, 0xe8, 0x8d, 0x6a, 0x07,
+ 0xc3, 0xe8, 0xd6, 0xff, 0xe8, 0x81, 0xfc, 0xc3,
+ 0xb8, 0x00, 0x3d, 0xb1, 0x00, 0xcd, 0x21, 0x72,
+ 0x3c, 0xa3, 0xa2, 0x00, 0xb8, 0x02, 0x42, 0x33,
+ 0xc9, 0x33, 0xd2, 0x8b, 0x1e, 0xa2, 0x00, 0xcd,
+ 0x21, 0x72, 0x2a, 0x8b, 0xd8, 0xb0, 0x33, 0x0b,
+ 0xd2, 0x75, 0x22, 0x89, 0x1e, 0xa4, 0x00, 0xb8,
+ 0x00, 0x42, 0x33, 0xc9, 0x33, 0xd2, 0x8b, 0x1e,
+ 0xa2, 0x00, 0xcd, 0x21, 0x72, 0x0f, 0xb4, 0x3e,
+ 0x8b, 0x1e, 0xa2, 0x00, 0xcd, 0x21, 0x72, 0x05,
+ 0x8b, 0x0e, 0xa4, 0x00, 0xc3, 0xe9, 0xf8, 0x03,
+ 0x51, 0xb8, 0x00, 0x3d, 0xb1, 0x00, 0xcd, 0x21,
+ 0x72, 0x6a, 0xa3, 0xa2, 0x00, 0x59, 0xb8, 0x04,
+ 0x00, 0xf7, 0xe1, 0x8b, 0xca, 0x8b, 0xd0, 0x8b,
+ 0x1e, 0xa2, 0x00, 0xb8, 0x00, 0x42, 0xcd, 0x21,
+ 0x72, 0x52, 0x8b, 0x1e, 0xa2, 0x00, 0xb9, 0x08,
+ 0x00, 0xba, 0xae, 0x00, 0xb4, 0x3f, 0xcd, 0x21,
+ 0x72, 0x42, 0xbb, 0xae, 0x00, 0x8b, 0x17, 0x8b,
+ 0x4f, 0x02, 0x8b, 0x47, 0x04, 0x2b, 0xc2, 0xa3,
+ 0xa4, 0x00, 0x8b, 0x1e, 0xa2, 0x00, 0xb8, 0x00,
+ 0x42, 0xcd, 0x21, 0x72, 0x27, 0x8b, 0x1e, 0xa2,
+ 0x00, 0x8b, 0x0e, 0xa4, 0x00, 0x8b, 0x16, 0xaa,
+ 0x00, 0xa1, 0xac, 0x00, 0x8e, 0xd8, 0xb4, 0x3f,
+ 0xcd, 0x21, 0x72, 0x10, 0xb8, 0x3b, 0x0b, 0x8e,
+ 0xd8, 0xb4, 0x3e, 0x8b, 0x1e, 0xa2, 0x00, 0xcd,
+ 0x21, 0x72, 0x01, 0xc3, 0xe9, 0x81, 0x03, 0xb8,
+ 0x00, 0x3d, 0xb1, 0x00, 0xcd, 0x21, 0x72, 0x54,
+ 0xa3, 0xa2, 0x00, 0xb8, 0x02, 0x42, 0x33, 0xc9,
+ 0x33, 0xd2, 0x8b, 0x1e, 0xa2, 0x00, 0xcd, 0x21,
+ 0x72, 0x42, 0x8b, 0xd8, 0xb0, 0x33, 0x0b, 0xd2,
+ 0x75, 0x3a, 0x89, 0x1e, 0xa4, 0x00, 0xb8, 0x00,
+ 0x42, 0x33, 0xc9, 0x33, 0xd2, 0x8b, 0x1e, 0xa2,
+ 0x00, 0xcd, 0x21, 0x72, 0x27, 0x8b, 0x1e, 0xa2,
+ 0x00, 0x8b, 0x0e, 0xa4, 0x00, 0x8b, 0x16, 0xaa,
+ 0x00, 0xa1, 0xac, 0x00, 0x8e, 0xd8, 0xb4, 0x3f,
+ 0xcd, 0x21, 0x72, 0x10, 0xb8, 0x3b, 0x0b, 0x8e,
+ 0xd8, 0xb4, 0x3e, 0x8b, 0x1e, 0xa2, 0x00, 0xcd,
+ 0x21, 0x72, 0x01, 0xc3, 0xe9, 0x21, 0x03, 0xb8,
+ 0x00, 0x3d, 0xb1, 0x00, 0xcd, 0x21, 0x72, 0x3b,
+ 0xa3, 0xa2, 0x00, 0xb8, 0x00, 0x42, 0x33, 0xc9,
+ 0x8b, 0x16, 0xa8, 0x00, 0x8b, 0x1e, 0xa2, 0x00,
+ 0xcd, 0x21, 0x72, 0x27, 0x8b, 0x1e, 0xa2, 0x00,
+ 0x8b, 0x0e, 0xa6, 0x00, 0x8b, 0x16, 0xaa, 0x00,
+ 0xa1, 0xac, 0x00, 0x8e, 0xd8, 0xb4, 0x3f, 0xcd,
+ 0x21, 0x72, 0x10, 0xb8, 0x3b, 0x0b, 0x8e, 0xd8,
+ 0xb4, 0x3e, 0x8b, 0x1e, 0xa2, 0x00, 0xcd, 0x21,
+ 0x72, 0x01, 0xc3, 0xe9, 0xda, 0x02, 0x51, 0xb4,
+ 0x3c, 0xb1, 0x00, 0xcd, 0x21, 0x59, 0x72, 0x26,
+ 0xa3, 0xa2, 0x00, 0x8b, 0x1e, 0xa2, 0x00, 0x8b,
+ 0x16, 0xaa, 0x00, 0xa1, 0xac, 0x00, 0x8e, 0xd8,
+ 0xb4, 0x40, 0xcd, 0x21, 0x72, 0x10, 0xb8, 0x3b,
+ 0x0b, 0x8e, 0xd8, 0xb4, 0x3e, 0x8b, 0x1e, 0xa2,
+ 0x00, 0xcd, 0x21, 0x72, 0x01, 0xc3, 0xe9, 0xa7,
+ 0x02, 0xba, 0x13, 0x00, 0xb8, 0x00, 0x3d, 0xb1,
+ 0x00, 0xcd, 0x21, 0x72, 0x19, 0x8b, 0xd8, 0xb4,
+ 0x3e, 0xcd, 0x21, 0x72, 0x73, 0x8c, 0x1e, 0xac,
+ 0x00, 0xb8, 0x42, 0x32, 0xa3, 0xaa, 0x00, 0xba,
+ 0x13, 0x00, 0xe8, 0x02, 0xff, 0xc3, 0x3d, 0x02,
+ 0x00, 0x75, 0x5d, 0xb8, 0x03, 0x00, 0xcd, 0x10,
+ 0x8c, 0xc8, 0x8e, 0xd8, 0xba, 0x00, 0xb1, 0xb4,
+ 0x09, 0xcd, 0x21, 0xb8, 0x00, 0x4c, 0xcd, 0x21,
+ 0x53, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x63, 0x6f,
+ 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x69, 0x6c, 0x65,
+ 0x3a, 0x20, 0x53, 0x4f, 0x55, 0x4e, 0x44, 0x2e,
+ 0x53, 0x45, 0x54, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x20, 0x50,
+ 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x72, 0x75,
+ 0x6e, 0x20, 0x53, 0x4f, 0x55, 0x4e, 0x44, 0x53,
+ 0x45, 0x54, 0x2e, 0x45, 0x58, 0x45, 0x2e, 0x24,
+ 0xe9, 0x1d, 0x02, 0x89, 0x0e, 0x90, 0xdb, 0xb0,
+ 0x00, 0xb4, 0x05, 0xff, 0x1e, 0x4a, 0x32, 0xb8,
+ 0x3b, 0x0b, 0x8e, 0xd8, 0x8e, 0xc0, 0xc3, 0x00,
+ 0x00, 0x00, 0x00, 0x57, 0x8b, 0xc8, 0xbb, 0x5f,
+ 0xb1, 0x2e, 0x8b, 0x47, 0x02, 0x2e, 0x8b, 0x1f,
+ 0x8b, 0xf0, 0x8b, 0xfb, 0x8a, 0xd4, 0x8a, 0xe0,
+ 0x8a, 0xc7, 0x8a, 0xfb, 0x32, 0xdb, 0xd0, 0xda,
+ 0xd1, 0xd8, 0xd1, 0xdb, 0x03, 0xdf, 0x13, 0xc6,
+ 0x81, 0xc3, 0xe9, 0x62, 0x15, 0x19, 0x36, 0xbf,
+ 0x5f, 0xb1, 0x2e, 0x89, 0x1d, 0x2e, 0x89, 0x45,
+ 0x02, 0x33, 0xd2, 0xf7, 0xf1, 0x8b, 0xc2, 0x5f,
+ 0xc3, 0xb4, 0x62, 0xcd, 0x21, 0x53, 0xba, 0x28,
+ 0x25, 0x2b, 0xd3, 0x33, 0xc0, 0xe8, 0x1c, 0x00,
+ 0x05, 0x0f, 0x00, 0x83, 0xd2, 0x00, 0xbb, 0x10,
+ 0x00, 0xf7, 0xf3, 0x8b, 0xd8, 0x58, 0x06, 0x8e,
+ 0xc0, 0xb4, 0x4a, 0xcd, 0x21, 0x07, 0x72, 0x01,
+ 0xc3, 0xe9, 0x9c, 0x01, 0x53, 0xd1, 0xc2, 0xd1,
+ 0xc2, 0xd1, 0xc2, 0xd1, 0xc2, 0x8b, 0xda, 0x83,
+ 0xe2, 0x0f, 0x83, 0xe3, 0xf0, 0x03, 0xc3, 0x83,
+ 0xd2, 0x00, 0x5b, 0xc3, 0xbb, 0x06, 0xfa, 0xbe,
+ 0xb1, 0x32, 0xe8, 0x3e, 0x00, 0xbb, 0x00, 0xfd,
+ 0xbe, 0xb3, 0x32, 0xe8, 0x35, 0x00, 0xbb, 0x00,
+ 0xfa, 0xbe, 0xb5, 0x32, 0xe8, 0x2c, 0x00, 0xbb,
+ 0x00, 0xfd, 0xbe, 0xbf, 0x32, 0xe8, 0x23, 0x00,
+ 0xbb, 0x88, 0x14, 0xbe, 0xc1, 0x32, 0xe8, 0x1a,
+ 0x00, 0x80, 0x3e, 0x42, 0x32, 0x06, 0x74, 0x12,
+ 0xbb, 0x4e, 0x80, 0xbe, 0xc3, 0x32, 0xe8, 0x0a,
+ 0x00, 0xbb, 0xb8, 0x88, 0xbe, 0xc5, 0x32, 0xe8,
+ 0x01, 0x00, 0xc3, 0x53, 0x56, 0xe8, 0x11, 0x00,
+ 0xb4, 0x48, 0xcd, 0x21, 0x5e, 0x59, 0x72, 0x06,
+ 0x89, 0x04, 0xe8, 0x19, 0x00, 0xc3, 0xe9, 0x27,
+ 0x01, 0x8b, 0xc3, 0x05, 0x0f, 0x00, 0x73, 0x04,
+ 0xb0, 0x38, 0xeb, 0xf2, 0x33, 0xd2, 0xbb, 0x10,
+ 0x00, 0xf7, 0xf3, 0x8b, 0xd8, 0xc3, 0x06, 0x8e,
+ 0xc0, 0x33, 0xc0, 0x33, 0xff, 0xfc, 0xf3, 0xaa,
+ 0x07, 0xc3, 0x06, 0xbe, 0xc7, 0x32, 0xb9, 0x01,
+ 0x00, 0x51, 0x56, 0x49, 0xb0, 0x1b, 0xf6, 0xe1,
+ 0x03, 0xf0, 0x8b, 0x44, 0x16, 0x0b, 0xc0, 0x74,
+ 0x0b, 0x8e, 0xc0, 0xb4, 0x49, 0xcd, 0x21, 0x73,
+ 0x03, 0xe9, 0xe4, 0x00, 0x5e, 0x59, 0x41, 0x80,
+ 0xf9, 0x04, 0x76, 0xdd, 0x07, 0xc3, 0xa0, 0x42,
+ 0x32, 0x3c, 0x01, 0x74, 0x1d, 0x3c, 0x06, 0x74,
+ 0x19, 0x3c, 0x07, 0x74, 0x15, 0x3c, 0x03, 0x74,
+ 0x11, 0x3c, 0x04, 0x74, 0x0d, 0xc7, 0x06, 0x84,
+ 0x32, 0x6c, 0x00, 0xb8, 0x59, 0x00, 0xa3, 0x04,
+ 0x00, 0xc3, 0xc7, 0x06, 0x84, 0x32, 0x9c, 0x2e,
+ 0xb8, 0x0a, 0x00, 0xa3, 0x04, 0x00, 0xc3, 0x33,
+ 0xd2, 0xb8, 0xff, 0xff, 0xf7, 0x36, 0x84, 0x32,
+ 0xa3, 0x7f, 0x32, 0xa3, 0x81, 0x32, 0xc3, 0xb0,
+ 0x36, 0xe6, 0x43, 0xa1, 0x84, 0x32, 0xe6, 0x40,
+ 0x8a, 0xc4, 0xe6, 0x40, 0xc3, 0xb0, 0x36, 0xe6,
+ 0x43, 0x32, 0xc0, 0xe6, 0x40, 0xe6, 0x40, 0xc3,
+ 0x06, 0xb8, 0x08, 0x35, 0xcd, 0x21, 0x89, 0x1e,
+ 0x00, 0x00, 0x8c, 0x06, 0x02, 0x00, 0x07, 0x8b,
+ 0x16, 0x04, 0x00, 0x1e, 0x0e, 0x1f, 0xb8, 0x08,
+ 0x25, 0xcd, 0x21, 0x1f, 0xc3, 0x1e, 0x8b, 0x16,
+ 0x00, 0x00, 0x8b, 0x1e, 0x02, 0x00, 0x8e, 0xdb,
+ 0xb8, 0x08, 0x25, 0xcd, 0x21, 0x1f, 0xc3, 0x06,
+ 0xb8, 0x09, 0x35, 0xcd, 0x21, 0x2e, 0x89, 0x1e,
+ 0xd8, 0x00, 0x2e, 0x8c, 0x06, 0xda, 0x00, 0x07,
+ 0x1e, 0x0e, 0x1f, 0xba, 0xba, 0x00, 0xb8, 0x09,
+ 0x25, 0xcd, 0x21, 0x1f, 0xc3, 0x1e, 0x2e, 0x8b,
+ 0x16, 0xd8, 0x00, 0x2e, 0x8b, 0x1e, 0xda, 0x00,
+ 0x8e, 0xdb, 0xb8, 0x09, 0x25, 0xcd, 0x21, 0x1f,
+ 0xc3, 0xe8, 0x42, 0xff, 0xe8, 0xc8, 0xff, 0xfa,
+ 0xb0, 0xff, 0xe6, 0x21, 0xe8, 0x91, 0xff, 0xe8,
+ 0x75, 0xff, 0xb0, 0x00, 0xe6, 0x21, 0xfb, 0xb8,
+ 0x13, 0x00, 0xcd, 0x10, 0xe8, 0x58, 0xff, 0xc3,
+ 0x50, 0xb8, 0x03, 0x00, 0xcd, 0x10, 0x58, 0xb4,
+ 0x00, 0xbb, 0xa6, 0x2f, 0xd1, 0xe0, 0x03, 0xd8,
+ 0x8b, 0x17, 0xb4, 0x09, 0xcd, 0x21, 0x80, 0x3e,
+ 0x42, 0x32, 0x00, 0x74, 0x0d, 0xb4, 0x02, 0xff,
+ 0x1e, 0x4a, 0x32, 0xb8, 0x3b, 0x0b, 0x8e, 0xd8,
+ 0x8e, 0xc0, 0xeb, 0x00, 0xfa, 0xe4, 0x21, 0x50,
+ 0xb0, 0xff, 0xe6, 0x21, 0xfa, 0xe8, 0x3d, 0xff,
+ 0xe8, 0x62, 0xff, 0xe8, 0x8f, 0xff, 0x58, 0xe6,
+ 0x21, 0xfb, 0xb8, 0x00, 0x4c, 0xcd, 0x21, 0x00
+};
+
+// Data Segment
+// starts at offset 0xb5b0 in original executable
+#define DSEG_STARTBLK_SIZE 13214
+
+const static uint8 dsegStartBlock[DSEG_STARTBLK_SIZE] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x73, 0x6f, 0x75, 0x6e, 0x64,
+ 0x2e, 0x73, 0x65, 0x74, 0x00, 0x6f, 0x66, 0x66,
+ 0x2e, 0x72, 0x65, 0x73, 0x00, 0x6f, 0x6e, 0x2e,
+ 0x72, 0x65, 0x73, 0x00, 0x6c, 0x61, 0x6e, 0x5f,
+ 0x35, 0x30, 0x30, 0x2e, 0x72, 0x65, 0x73, 0x00,
+ 0x6c, 0x61, 0x6e, 0x5f, 0x30, 0x30, 0x30, 0x2e,
+ 0x72, 0x65, 0x73, 0x00, 0x73, 0x64, 0x72, 0x2e,
+ 0x72, 0x65, 0x73, 0x00, 0x6f, 0x6e, 0x73, 0x2e,
+ 0x72, 0x65, 0x73, 0x00, 0x76, 0x61, 0x72, 0x69,
+ 0x61, 0x2e, 0x72, 0x65, 0x73, 0x00, 0x6d, 0x6d,
+ 0x6d, 0x2e, 0x72, 0x65, 0x73, 0x00, 0x73, 0x61,
+ 0x6d, 0x5f, 0x73, 0x61, 0x6d, 0x2e, 0x72, 0x65,
+ 0x73, 0x00, 0x73, 0x61, 0x6d, 0x5f, 0x6d, 0x6d,
+ 0x6d, 0x2e, 0x72, 0x65, 0x73, 0x00, 0x75, 0x6e,
+ 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x2e, 0x72, 0x65,
+ 0x73, 0x00, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74,
+ 0x2e, 0x72, 0x65, 0x73, 0x00, 0x74, 0x65, 0x65,
+ 0x6e, 0x61, 0x67, 0x65, 0x30, 0x2e, 0x73, 0x61,
+ 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x3f, 0x01,
+ 0x00, 0x00, 0xdf, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0xdf, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0xdf, 0xff, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0xdf, 0xff, 0xff, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0xdf, 0xff, 0xff, 0xff, 0x00, 0x01,
+ 0x01, 0x01, 0xdf, 0xff, 0xff, 0xff, 0xff, 0x00,
+ 0x01, 0x01, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x01, 0xdf, 0xff, 0xdf, 0xff, 0x00, 0x00,
+ 0x00, 0x00, 0xdf, 0xdf, 0x01, 0xdf, 0xff, 0x00,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0xdf, 0xff, 0x00,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xdf, 0xff,
+ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xdf,
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x32, 0xe1,
+ 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xe0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x30, 0x25, 0x30, 0x34, 0x30, 0x39, 0x30,
+ 0x4d, 0x30, 0x52, 0x30, 0x57, 0x30, 0x76, 0x30,
+ 0x8a, 0x30, 0xa7, 0x30, 0xac, 0x30, 0xb1, 0x30,
+ 0xb6, 0x30, 0xbb, 0x30, 0xc0, 0x30, 0xc5, 0x30,
+ 0xca, 0x30, 0xcf, 0x30, 0xd4, 0x30, 0xd9, 0x30,
+ 0xde, 0x30, 0xe3, 0x30, 0xe8, 0x30, 0xed, 0x30,
+ 0xf2, 0x30, 0xf7, 0x30, 0xfc, 0x30, 0x01, 0x31,
+ 0x06, 0x31, 0x0b, 0x31, 0x10, 0x31, 0x15, 0x31,
+ 0x1a, 0x31, 0x1f, 0x31, 0x24, 0x31, 0x29, 0x31,
+ 0x2e, 0x31, 0x33, 0x31, 0x38, 0x31, 0x3d, 0x31,
+ 0x42, 0x31, 0x47, 0x31, 0x4c, 0x31, 0x51, 0x31,
+ 0x56, 0x31, 0x5b, 0x31, 0x60, 0x31, 0x65, 0x31,
+ 0x6a, 0x31, 0x6f, 0x31, 0xbd, 0x31, 0xc1, 0x31,
+ 0xc5, 0x31, 0xc9, 0x31, 0xcd, 0x31, 0xce, 0x31,
+ 0xd2, 0x31, 0xd6, 0x31, 0xda, 0x31, 0xde, 0x31,
+ 0x45, 0x30, 0x31, 0x68, 0x24, 0x46, 0x69, 0x6c,
+ 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, 0x6f,
+ 0x75, 0x6e, 0x64, 0x24, 0x45, 0x30, 0x33, 0x68,
+ 0x24, 0x54, 0x6f, 0x6f, 0x20, 0x6d, 0x61, 0x6e,
+ 0x79, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x66,
+ 0x69, 0x6c, 0x65, 0x73, 0x24, 0x45, 0x30, 0x35,
+ 0x68, 0x24, 0x45, 0x30, 0x36, 0x68, 0x24, 0x4d,
+ 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x20, 0x63, 0x6f,
+ 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x62, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x20, 0x64, 0x65, 0x73, 0x74,
+ 0x72, 0x6f, 0x79, 0x65, 0x64, 0x24, 0x49, 0x6e,
+ 0x73, 0x75, 0x66, 0x66, 0x69, 0x63, 0x69, 0x65,
+ 0x6e, 0x74, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x72,
+ 0x79, 0x24, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
+ 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x61,
+ 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x69,
+ 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x24, 0x45,
+ 0x30, 0x41, 0x68, 0x24, 0x45, 0x30, 0x42, 0x68,
+ 0x24, 0x45, 0x30, 0x43, 0x68, 0x24, 0x45, 0x30,
+ 0x44, 0x68, 0x24, 0x45, 0x30, 0x45, 0x68, 0x24,
+ 0x45, 0x30, 0x46, 0x68, 0x24, 0x45, 0x31, 0x30,
+ 0x68, 0x24, 0x45, 0x31, 0x31, 0x68, 0x24, 0x45,
+ 0x31, 0x32, 0x68, 0x24, 0x45, 0x31, 0x33, 0x68,
+ 0x24, 0x45, 0x31, 0x34, 0x68, 0x24, 0x45, 0x31,
+ 0x35, 0x68, 0x24, 0x45, 0x31, 0x36, 0x68, 0x24,
+ 0x45, 0x31, 0x37, 0x68, 0x24, 0x45, 0x31, 0x38,
+ 0x68, 0x24, 0x45, 0x31, 0x39, 0x68, 0x24, 0x45,
+ 0x31, 0x41, 0x68, 0x24, 0x45, 0x31, 0x42, 0x68,
+ 0x24, 0x45, 0x31, 0x43, 0x68, 0x24, 0x45, 0x31,
+ 0x44, 0x68, 0x24, 0x45, 0x31, 0x45, 0x68, 0x24,
+ 0x45, 0x31, 0x46, 0x68, 0x24, 0x45, 0x32, 0x30,
+ 0x68, 0x24, 0x45, 0x32, 0x31, 0x68, 0x24, 0x45,
+ 0x32, 0x32, 0x68, 0x24, 0x45, 0x32, 0x33, 0x68,
+ 0x24, 0x45, 0x32, 0x34, 0x68, 0x24, 0x45, 0x32,
+ 0x35, 0x68, 0x24, 0x45, 0x32, 0x36, 0x68, 0x24,
+ 0x45, 0x32, 0x37, 0x68, 0x24, 0x45, 0x32, 0x38,
+ 0x68, 0x24, 0x45, 0x32, 0x39, 0x68, 0x24, 0x45,
+ 0x32, 0x41, 0x68, 0x24, 0x45, 0x32, 0x42, 0x68,
+ 0x24, 0x45, 0x32, 0x43, 0x68, 0x24, 0x45, 0x32,
+ 0x44, 0x68, 0x24, 0x45, 0x32, 0x45, 0x68, 0x24,
+ 0x45, 0x32, 0x46, 0x68, 0x24, 0x45, 0x33, 0x30,
+ 0x68, 0x24, 0x45, 0x33, 0x31, 0x68, 0x24, 0x44,
+ 0x75, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e,
+ 0x74, 0x69, 0x2d, 0x76, 0x69, 0x72, 0x75, 0x73,
+ 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x61, 0x64,
+ 0x65, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e,
+ 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68,
+ 0x69, 0x73, 0x20, 0x67, 0x61, 0x6d, 0x65, 0x20,
+ 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6f, 0x72, 0x69,
+ 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x64, 0x69,
+ 0x73, 0x6b, 0x73, 0x2e, 0x24, 0x47, 0x45, 0x31,
+ 0x24, 0x47, 0x45, 0x32, 0x24, 0x47, 0x45, 0x33,
+ 0x24, 0x47, 0x45, 0x34, 0x24, 0x24, 0x47, 0x45,
+ 0x35, 0x24, 0x47, 0x45, 0x36, 0x24, 0x47, 0x45,
+ 0x37, 0x24, 0x47, 0x45, 0x38, 0x24, 0x47, 0x45,
+ 0x39, 0x24, 0x43, 0x61, 0x6c, 0x6c, 0x20, 0x79,
+ 0x6f, 0x75, 0x72, 0x73, 0x65, 0x6c, 0x66, 0x20,
+ 0x70, 0x69, 0x72, 0x61, 0x74, 0x65, 0x2c, 0x20,
+ 0x68, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x2c, 0x20,
+ 0x65, 0x6c, 0x69, 0x74, 0x65, 0x20, 0x6f, 0x72,
+ 0x20, 0x77, 0x68, 0x61, 0x74, 0x65, 0x76, 0x65,
+ 0x72, 0x2e, 0x20, 0x42, 0x75, 0x74, 0x20, 0x79,
+ 0x6f, 0x75, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61,
+ 0x20, 0x54, 0x48, 0x49, 0x45, 0x46, 0x2e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d,
+ 0x6f, 0x75, 0x73, 0x65, 0x20, 0x6e, 0x6f, 0x74,
+ 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x20,
+ 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6b, 0x65,
+ 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x2e,
+ 0x2e, 0x0d, 0x0a, 0x50, 0x72, 0x65, 0x73, 0x73,
+ 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6b, 0x65, 0x79,
+ 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x74,
+ 0x69, 0x6e, 0x75, 0x65, 0x2e, 0x24
+};
+
+const static char* messages[333] = {
+ "I have no idea what to do with it.", // 0
+ "I can't imagine what I could do with\nthis.", // 1
+ "I can't figure out what I should do\nwith this.", // 2
+ "I can't find any reason to mess\nwith it.", // 3
+ "Cool.", // 4
+ "That's no good.", // 5
+ "Wow! There's a car jack inside!\nGreat!", // 6
+ "There's something else inside the toolbox!\nA spanner!", // 7
+ "Last\nchance?", // 8
+ "I give up.", // 9
+ "I'm going to stay at least five meters\naway from these bees!", // 10
+ "There's nothing else in the boat.", // 11
+ "This wood is too hard to break.", // 12
+ "Booo!", // 13
+ "I don't think I should push\nmy luck.", // 14
+ "Just an ordinary hay stack. Now.", // 15
+ "And they say you can't find a needle\nin a hay stack.", // 16
+ "There are no more\npotatoes.", // 17
+ "Good I always asked mum for\ntrousers with BIG pockets...", // 18
+ "Life is brutal.", // 19
+ "Life is really brutal.", // 20
+ "Something tickled\nme!", // 21
+ "At least it's gone.", // 22
+ "Who knows what monsters\nmay live in there...", // 23
+ "I'd better not put my hands in there.\nSomething might bite them off\n(yuck)!", // 24
+ "I can see it's totally\nempty.", // 25
+ "One small step for man,\none big pain in the ...head...", // 26
+ "I won't take my chances\na second time...", // 27
+ "I really hope this is DINOSAUR\nbone...", // 28
+ "Wow! This must have shaken\nall the nearby walls!", // 29
+ "It's kinda dark here.", // 30
+ "I'm not going to wander here\nin the dark again.", // 31
+ "Shutting the valve shook the dirt from the wall\nand revealed the switch!", // 32
+ "Sorry, buddy, but I need your\nsunglasses.", // 33
+ "It's not the best place for diving...", // 34
+ "Not here...", // 35
+ "I really can't talk underwater!...", // 36
+ "I don't think swimming there is worth the effort.", // 37
+ "If I want to get this anchor I have to swim there\nwhen I have more air in my lungs...", // 38
+ "I was really hooked on this anchor!", // 39
+ "This seaweed is just like the flowers\nI gave mum on her last birthday.", // 40
+ "I wonder what fish do inside\nthis boat at night.", // 41
+ "I think I have to fish out something down\nthere.", // 42
+ "At least fish don't worry about the rain.", // 43
+ "I hope all this fish stuff is not a red herring.", // 44
+ "It's nice down there.", // 45
+ "Hey, let go, will ya?!", // 46
+ "Aaaaaaaaaaaaaahhh!...", // 47
+ "Oops.", // 48
+ "People leave food in unbelievable places.", // 49
+ "Come here, I've got something for\nyou...", // 50
+ "I can't catch it!", // 51
+ "The mouse is trapped!", // 52
+ "Yikes!", // 53
+ "Boy, this mouse has some nerve!", // 54
+ "There's nothing else in the drawers.", // 55
+ "I must get rid of this bush first.", // 56
+ "The mouse has gone!", // 57
+ "Nonsense.", // 58
+ "I understand. Good doggy.", // 59
+ "Here, boy.", // 60
+ "I hope we're friends now.", // 61
+ "I don't think this is the right place.", // 62
+ "Hundred moments later...", // 63
+ "Another hundred moments later...", // 64
+ "At least I found crude-oil and I'll be\nrich.", // 65
+ "That's my life.", // 66
+ "!?&!", // 67
+ "But grandpa, you promised!...", // 68
+ "Oh, all right. Let's go.", // 69
+ "Bye.", // 70
+ "No need to do it again.", // 71
+ "I really don't know how to talk to\ngirls...", // 72
+ "I usually don't work without a purpose.", // 73
+ "Only the nut is real.", // 74
+ "I wonder if hens can fly. Come here,\nbaby...", // 75
+ "First test failed.", // 76
+ "I'd already got rid of my frustrations.", // 77
+ "Nah, it's a road to nowhere.", // 78
+ "It opens the boot.", // 79
+ "It's shut tight.", // 80
+ "There's nothing else in the boot.", // 81
+ "The clothes are dry now.", // 82
+ "I'm sure these crows will kill me!", // 83
+ "If I want to get inside I must get rid of\nthis guard first or find some other\nway.", // 84
+ "The wall surface is too smooth to climb.", // 85
+ "I could climb it\nif there wasn't\nso much resin.", // 86
+ "The only green stuff I like is that rectangular\npiece of paper with some important-looking\nguy on it.", // 87
+ "I don't wanna touch it. Its spines could\nhurt my delicate hands.", // 88
+ "Thanks, I'm not hungry.", // 89
+ "I really don't have such long hands.", // 90
+ "It's too far to swim there.", // 91
+ "Echo!", // 92
+ "ECHO!", // 93
+ "Who's there?!", // 94
+ "WHO'S THERE?!", // 95
+ " DON'T COPY ME!...", // 96
+ " DON'T COPY ME!!!", // 97
+ "...OR I WILL THROW A ROCK DOWN THERE!", // 98
+ "OR I WILL...", // 99
+ "Are you still there?", // 100
+ "It's not a barrel-organ. And there's\nno bucket.", // 101
+ "I don't need to open it.", // 102
+ "Hmmm... Grass... Nah, children might\nbe watching.", // 103
+ "I won't find the nut just like that.\nThe grass is too dense.", // 104
+ "I'm not horny.", // 105
+ "No way I can jump so high,\ncause, er..., white men\ncan't jump.", // 106
+ "I don't need it.", // 107
+ "I'm not Santa Claus.", // 108
+ "I don't need plastic imitations.", // 109
+ "It's too fragile to carry around.", // 110
+ "I'd like to keep it open.", // 111
+ "I really don't want to walk around with\nsomeone else's socks.", // 112
+ "Thanks, I'm not tired.", // 113
+ "It's too big and I doubt if I'll ever\nneed it.", // 114
+ "I don't think there's any secret passage\ninside.", // 115
+ "There are no more interesting fruits here.", // 116
+ "They can jug me if I steal this.", // 117
+ "I'd better leave it. Women are really\noversensitive about flowers.", // 118
+ "Mirror, mirror on the wall,\nwho's the smartest of them all?", // 119
+ "Hey, don't think too long.", // 120
+ "A hint: someone in this room,\na male.", // 121
+ "OK, take your time.", // 122
+ "I'd better not interrupt its\nthought process.", // 123
+ "I don't want to have anything in common\nwith dentists.", // 124
+ "It's too heavy. Not that I'm wimp.", // 125
+ "Let's look what we've got here...", // 126
+ "'Strawberry jam'.", // 127
+ "'Gooseberry jam'.", // 128
+ "'Blackberry jam'.", // 129
+ "'Bilberry jam'.", // 130
+ "Get me out of this jam!", // 131
+ "Oh, and there is 'Rosemary jam'.", // 132
+ "I used to know someone called Rosemary.", // 133
+ "I don't want those jams.", // 134
+ "It's too dark to see clearly.", // 135
+ "YEEEOOOWWWW!", // 136
+ "(yawn)", // 137
+ "(laughter)", // 138
+ "I can't remove it with my hands - these\nthorns look really sharp.", // 139
+ "There's no fuel in the chainsaw.", // 140
+ "Thorns are too thin, the chainsaw\nis useless here.", // 141
+ "Yeah, great idea. Let's take this rock and\nwalk around a bit. Gee...", // 142
+ "I'd better leave them alone, they make\nthis place beautiful.", // 143
+ "I'm not sure if it's alive.", // 144
+ "I don't know what language it speaks.", // 145
+ "The hole is too narrow to fit my hand.", // 146
+ "Hey, you! Wake up! Bird attack!", // 147
+ "I don't have a search-warrant.", // 148
+ "I don't see anything interesting\nabout this hay stack.", // 149
+ "It's more complicated than that.", // 150
+ "It's pointless, the nut will slip between\nthe rake's teeth.", // 151
+ "The paddle is BROKEN.", // 152
+ "This branch is not a paddle. It doesn't\neven look like one.", // 153
+ "I'd better try somewhere else - I suppose this\nside is heavily guarded.", // 154
+ "I needed to sharpen it, not pulverize.", // 155
+ "I can't do anything here, it's too dark.", // 156
+ "Here, let's make your\npocket fat.", // 157
+ "It's a note from some bank. Strange,\nbut someone has also written \"NEVER! ANNE\"\non it.", // 158
+ "If I just show her the money,\nshe might take it.", // 159
+ "A hundred bucks!!!", // 160
+ "I want blood!", // 161
+ "I don't want to leave the mansion,\nI want blood!", // 162
+ "I'm a pathetic little wimp.", // 163
+ "Strange, but the drawer is stuck\nif the next drawer is open...", // 164
+ "Maybe these are not just ordinary\ndrawers!", // 165
+ "I cannot open the drawer\nif the next one is open!", // 166
+ "It's got a blue interior.", // 167
+ "It's got a red interior.", // 168
+ "It's got a grey interior.", // 169
+ "It's got a green interior.", // 170
+ "It's got a brown interior.", // 171
+ "It's got a pink interior.", // 172
+ "Wow! There's a dictaphone inside!", // 173
+ "There's a polaroid inside!\nI might need that.", // 174
+ "Something's got hold of the book!", // 175
+ "Wow! A secret compartment!", // 176
+ "I don't need to mess with it\nanymore.", // 177
+ "Fully automatic.", // 178
+ "Right now I don't need any more\nsheets.", // 179
+ "Nah, I don't want to deprave the kids.", // 180
+ "I don't want to read it again.\nI might like it.", // 181
+ "I just realised that the TV is off.", // 182
+ "Nothing happened.", // 183
+ "The tape started!", // 184
+ "That's much better.", // 185
+ "I don't want to sleep.", // 186
+ "It's just a cork.", // 187
+ "I don't need any more photos.", // 188
+ "Yeah, I can record this and scare\nthe cats.", // 189
+ "I already recorded what I wanted to.", // 190
+ "I can't record anything until I find some\nbatteries.", // 191
+ "No batteries, no fun.", // 192
+ "I don't think this is the right moment.", // 193
+ "I can't do anything with\nthis cook around.", // 194
+ "The bottle's the same, but\nI doubt if it's enough to\nfool anyone.", // 195
+ "I wanted to break it, not to\nflatten it!..", // 196
+ "I was always curious what's inside\nthese things.", // 197
+ "The rest is useless.", // 198
+ "Wow! Two 1.5V batteries!", // 199
+ "This one's taken, OK?", // 200
+ "It finally happened. I'm slightly mad.", // 201
+ "The paper burnt out completely!", // 202
+ "Burn, baby, burn!", // 203
+ "Voila.", // 204
+ "It's too hot to touch!", // 205
+ "It has frozen hard onto the shelf!", // 206
+ "Yummy.", // 207
+ "I never liked veal anyway.", // 208
+ "There's no reason to do it.", // 209
+ "I'd already fooled him once.", // 210
+ "Mike, activate the voice test.", // 211
+ "I won't cheat Mike with MY voice.", // 212
+ "...siiiiinging!...", // 213
+ "Mike, let's get on with the scent\ntest.", // 214
+ "Mike, run the view test.", // 215
+ "'A secret diary of John Noty. Authorised.'", // 216
+ "I can't hide here!", // 217
+ "There's John Noty outside! I can't go out!", // 218
+ "That was close.", // 219
+ "The cork is stuck in the hole.", // 220
+ "It fits perfectly!", // 221
+ "There's enough water in the sink.", // 222
+ "There's no hot water in the sink.", // 223
+ "The label has come off!", // 224
+ "The cork is a bit too small.", // 225
+ "There's no need to try them now.", // 226
+ "I don't want to turn myself into a salad.", // 227
+ "Nah...", // 228
+ "I'd better stop this ventilator first.", // 229
+ "I'd better catch John Noty first.", // 230
+ "Good this red stuff is only a chilli...", // 231
+ "The water looks very hot.", // 232
+ "The sink is full of hot water.", // 233
+ "I don't have anything\nto store these socks in.", // 234
+ "Here are my papers.", // 235
+ "I already got the permission.", // 236
+ "'Saving is a very fine thing. Especially\nwhen your parents have done it for you'", // 237
+ "'I love captain'", // 238
+ "'Soccer rulz'", // 239
+ "'Don't cut the trees, cuz one\nday you may become partisan\ntoo'", // 240
+ "'VISA accepted'", // 241
+ "The rest of graffiti is obscene.", // 242
+ "Sir, I'm Mark. A rookie.", // 243
+ "It's locked!", // 244
+ "Thanks.", // 245
+ "I don't have any idea what\nto do with it right\nnow.", // 246
+ "That gives me an idea...", // 247
+ "Now I got to check if it works...", // 248
+ "I think it's time to call captain...", // 249
+ "Hey! I finished the meal!", // 250
+ "Wow, he got welded to the bowl!...", // 251
+ "Gotcha.", // 252
+ "I don't want to touch\nhis pockets again.", // 253
+ "That doesn't work.", // 254
+ "Piece of cake.", // 255
+ "And how am I supposed to get back?", // 256
+ "Great.", // 257
+ "Oh, yeah, right...", // 258
+ "I can't pull it out.", // 259
+ "I don't want to touch it - I might get hurt.", // 260
+ "The fence blocks the way...", // 261
+ "I don't want to sleep.", // 262
+ "I can't reach it.", // 263
+ "Hello?", // 264
+ "He's totally addicted.", // 265
+ "What about a new...", // 266
+ "...hot off the press...", // 267
+ "...full-color...", // 268
+ "...special edition...", // 269
+ "... of 'Soldier News'?!", // 270
+ "Never again!", // 271
+ "What am I? A vacuum cleaner?!", // 272
+ " Sixty seven rude words later...", // 273
+ "Meanwhile in the mansion...", // 274
+ "Now it's open.", // 275
+ "C'mon, baby, it's all yours!", // 276
+ "I've got no reason to talk to him\nright now.", // 277
+ "Yeah, right!...", // 278
+ "The barman is too close...", // 279
+ "Yuck!", // 280
+ "I prefer water.", // 281
+ "I'm too weak to climb it.", // 282
+ "The springs would prick my back.", // 283
+ "No, thanks. This food seems still alive.", // 284
+ "The door is closed. What a surprise.", // 285
+ "It's empty.", // 286
+ "I should have paid more attention\nin geography classes...", // 287
+ "I don't need this mess.", // 288
+ "Thanks, but I've seen softer rocks.", // 289
+ "They are too blunt to be of any use.", // 290
+ "What's the use of the models?", // 291
+ "The barman will surely notice its\ndisappearing.", // 292
+ "It'd take too much time to drink it all.\nMaybe after the mission...", // 293
+ "\n\nI'm not a thief. And it's empty, by the way.", // 294
+ "There are too many of them to search.", // 295
+ "Captain surely wouldn't fit them.\nI must look elsewhere.", // 296
+ "Chickening? Me? Never!", // 297
+ "I can't open it.", // 298
+ "I don't need them.", // 299
+ "What am I? A Peeping Tom?", // 300
+ "I have big pockets, but there are limits.", // 301
+ "If I put it on I might have trouble walking\nup the stairs.", // 302
+ "I'd need 9 lives to read them all.", // 303
+ "Thanks, I'm not so tired.", // 304
+ "There's no need to turn it on.", // 305
+ "It won't bear my weight.", // 306
+ "I never learnt to how use one...", // 307
+ "They're so sharp they'd rip my trousers!", // 308
+ "Pfui! The cognac really didn't do any good...", // 309
+ "I don't have time for pleasures.", // 310
+ "I won't touch these socks with my bare hands!", // 311
+ "It's not Halloween.", // 312
+ "It can't be controlled manually! I hate it!", // 313
+ "I have nothing to play.", // 314
+ "I can't take it. It's not mine.", // 315
+ "Hey! What's the matter?!", // 316
+ "It's open!", // 317
+ "It's out of order.", // 318
+ "With captain watching?...\nBetter not...", // 319
+ "The sickle is too blunt.", // 320
+ "First I've got some business to take care of.", // 321
+ "Digging it out with the knife could\ntake a hundred years.", // 322
+ "I don't want to make more\nmess on this table.", // 323
+ "Should I throw the crumbs to the bird?", // 324
+ "I don't want to waste these tasty crumbs.", // 325
+ "Better not... I might slip and fall in...", // 326
+ "\"The history of blues\".", // 327
+ "\"Manchester United, or the Red Devils story\".", // 328
+ "\"Greyhounds and other hunting dogs\".", // 329
+ "\"Greenhorn, or my adventures in the Wild West\".", // 330
+ "\"Charlie Brown and his company\".", // 331
+ "\"Pink Panther: an unauthorised biography\"." // 332
+};
+
+#define DSEG_ENDBLK_SIZE 34651
+
+const static uint8 dsegEndBlock[DSEG_ENDBLK_SIZE] = {
+ 0x90, 0x9d, 0xe5, 0x9d, 0x54, 0x9e, 0xc3, 0x9e,
+ 0x3e, 0x9f, 0x0b, 0x30, 0x02, 0x31, 0x03, 0x32,
+ 0x04, 0x33, 0x05, 0x34, 0x06, 0x35, 0x07, 0x36,
+ 0x08, 0x37, 0x09, 0x38, 0x0a, 0x39, 0x0c, 0x2d,
+ 0x1e, 0x41, 0x30, 0x42, 0x2e, 0x43, 0x20, 0x44,
+ 0x12, 0x45, 0x21, 0x46, 0x22, 0x47, 0x23, 0x48,
+ 0x17, 0x49, 0x24, 0x4a, 0x25, 0x4b, 0x26, 0x4c,
+ 0x32, 0x4d, 0x31, 0x4e, 0x18, 0x4f, 0x19, 0x50,
+ 0x10, 0x51, 0x13, 0x52, 0x1f, 0x53, 0x14, 0x54,
+ 0x16, 0x55, 0x2f, 0x56, 0x11, 0x57, 0x2d, 0x58,
+ 0x15, 0x59, 0x2c, 0x5a, 0x33, 0x2c, 0x34, 0x2e,
+ 0x35, 0x3f, 0x39, 0x20, 0x28, 0x27, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x0a, 0x48, 0x01,
+ 0x00, 0x7c, 0x19, 0x48, 0x02, 0x00, 0xaf, 0x30,
+ 0x0e, 0x03, 0x02, 0xbe, 0x30, 0x26, 0x03, 0x03,
+ 0xe5, 0x30, 0x0e, 0x03, 0x01, 0xaf, 0x3f, 0x0e,
+ 0x04, 0x02, 0xbe, 0x3f, 0x26, 0x04, 0x03, 0xe5,
+ 0x3f, 0x0e, 0x04, 0x01, 0x9f, 0x4e, 0x0e, 0x05,
+ 0x02, 0xae, 0x4e, 0x36, 0x05, 0x03, 0xe5, 0x4e,
+ 0x0e, 0x05, 0x01, 0x9f, 0x5d, 0x0e, 0x06, 0x02,
+ 0xae, 0x5d, 0x36, 0x06, 0x03, 0xe5, 0x5d, 0x0e,
+ 0x06, 0x01, 0x9f, 0x6c, 0x0e, 0x07, 0x02, 0xae,
+ 0x6c, 0x36, 0x07, 0x03, 0xe5, 0x6c, 0x0e, 0x07,
+ 0x01, 0xa7, 0x7b, 0x0e, 0x08, 0x02, 0xb6, 0x7b,
+ 0x2e, 0x08, 0x03, 0xe5, 0x7b, 0x0e, 0x08, 0x01,
+ 0x8d, 0x94, 0x25, 0x0b, 0x00, 0x6c, 0xa3, 0x69,
+ 0x0a, 0x00, 0x79, 0xb2, 0x50, 0x0d, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x81, 0x0f, 0x41, 0x22,
+ 0xd3, 0x3e, 0x92, 0x51, 0x50, 0x64, 0x0e, 0x77,
+ 0xd0, 0x89, 0x8a, 0x9c, 0x00, 0x00, 0x52, 0xbd,
+ 0xb1, 0xce, 0x81, 0xe1, 0x4c, 0x6f, 0x61, 0x64,
+ 0x20, 0x67, 0x61, 0x6d, 0x65, 0x00, 0x53, 0x61,
+ 0x76, 0x65, 0x20, 0x67, 0x61, 0x6d, 0x65, 0x00,
+ 0x4d, 0x75, 0x73, 0x69, 0x63, 0x20, 0x76, 0x6f,
+ 0x6c, 0x75, 0x6d, 0x65, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x7f, 0x00, 0x53,
+ 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x76, 0x6f, 0x6c,
+ 0x75, 0x6d, 0x65, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7f, 0x00, 0x48, 0x65,
+ 0x72, 0x6f, 0x20, 0x73, 0x70, 0x65, 0x65, 0x64,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x7f, 0x00, 0x47,
+ 0x61, 0x6d, 0x65, 0x20, 0x73, 0x70, 0x65, 0x65,
+ 0x64, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7f, 0x00,
+ 0x54, 0x65, 0x78, 0x74, 0x20, 0x73, 0x70, 0x65,
+ 0x65, 0x64, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7f,
+ 0x00, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63,
+ 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x7f, 0x00, 0x20, 0x00, 0x51, 0x75, 0x69, 0x74,
+ 0x00, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20,
+ 0x74, 0x6f, 0x20, 0x67, 0x61, 0x6d, 0x65, 0x00,
+ 0x4f, 0x72, 0x64, 0x65, 0x72, 0x20, 0x69, 0x6e,
+ 0x66, 0x6f, 0x00, 0x00, 0x77, 0x64, 0x39, 0x77,
+ 0x0f, 0x8a, 0x44, 0x6f, 0x20, 0x79, 0x6f, 0x75,
+ 0x20, 0x72, 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x00,
+ 0x77, 0x61, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20,
+ 0x71, 0x75, 0x69, 0x74, 0x00, 0x28, 0x59, 0x2f,
+ 0x4e, 0x29, 0x3f, 0x00, 0x00, 0xf7, 0x57, 0x83,
+ 0x6a, 0x43, 0x7d, 0x03, 0x90, 0x46, 0x6f, 0x72,
+ 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x63, 0x61,
+ 0x6c, 0x6c, 0x3a, 0x00, 0x55, 0x4b, 0x3a, 0x20,
+ 0x50, 0x44, 0x20, 0x53, 0x65, 0x6c, 0x65, 0x63,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x30, 0x31,
+ 0x34, 0x37, 0x34, 0x20, 0x33, 0x32, 0x35, 0x38,
+ 0x30, 0x32, 0x00, 0x55, 0x53, 0x41, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72,
+ 0x65, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64,
+ 0x3a, 0x00, 0x55, 0x6e, 0x69, 0x6f, 0x6e, 0x20,
+ 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x20, 0x28, 0x38,
+ 0x30, 0x30, 0x29, 0x20, 0x35, 0x38, 0x33, 0x2d,
+ 0x34, 0x38, 0x33, 0x38, 0x00, 0x00, 0x44, 0x5f,
+ 0x04, 0x77, 0xc4, 0x84, 0x84, 0x92, 0x49, 0x20,
+ 0x63, 0x61, 0x6e, 0x27, 0x74, 0x20, 0x75, 0x73,
+ 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73,
+ 0x61, 0x76, 0x65, 0x67, 0x61, 0x6d, 0x65, 0x21,
+ 0x00, 0x28, 0x54, 0x68, 0x65, 0x20, 0x66, 0x69,
+ 0x6c, 0x65, 0x20, 0x69, 0x73, 0x20, 0x63, 0x6f,
+ 0x72, 0x72, 0x75, 0x70, 0x74, 0x65, 0x64, 0x20,
+ 0x6f, 0x72, 0x20, 0x77, 0x61, 0x73, 0x00, 0x73,
+ 0x61, 0x76, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x64,
+ 0x65, 0x72, 0x20, 0x64, 0x69, 0x66, 0x66, 0x65,
+ 0x72, 0x65, 0x6e, 0x74, 0x20, 0x67, 0x61, 0x6d,
+ 0x65, 0x00, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
+ 0x6e, 0x2e, 0x20, 0x53, 0x6f, 0x72, 0x72, 0x79,
+ 0x2e, 0x29, 0x00, 0x00, 0xc7, 0x32, 0x4f, 0x46,
+ 0x46, 0x00, 0xc7, 0x32, 0x31, 0x30, 0x80, 0x00,
+ 0xc6, 0x32, 0x32, 0x30, 0x80, 0x00, 0xc6, 0x32,
+ 0x33, 0x30, 0x80, 0x00, 0xc6, 0x32, 0x34, 0x30,
+ 0x80, 0x00, 0xc6, 0x32, 0x35, 0x30, 0x80, 0x00,
+ 0xc6, 0x32, 0x36, 0x30, 0x80, 0x00, 0xc6, 0x32,
+ 0x37, 0x30, 0x80, 0x00, 0xc6, 0x32, 0x38, 0x30,
+ 0x80, 0x00, 0xc6, 0x32, 0x39, 0x30, 0x80, 0x00,
+ 0xc5, 0x32, 0x4d, 0x41, 0x58, 0x00, 0xc7, 0x41,
+ 0x4f, 0x46, 0x46, 0x00, 0xc7, 0x41, 0x31, 0x30,
+ 0x80, 0x00, 0xc6, 0x41, 0x32, 0x30, 0x80, 0x00,
+ 0xc6, 0x41, 0x33, 0x30, 0x80, 0x00, 0xc6, 0x41,
+ 0x34, 0x30, 0x80, 0x00, 0xc6, 0x41, 0x35, 0x30,
+ 0x80, 0x00, 0xc6, 0x41, 0x36, 0x30, 0x80, 0x00,
+ 0xc6, 0x41, 0x37, 0x30, 0x80, 0x00, 0xc6, 0x41,
+ 0x38, 0x30, 0x80, 0x00, 0xc6, 0x41, 0x39, 0x30,
+ 0x80, 0x00, 0xc5, 0x41, 0x4d, 0x41, 0x58, 0x00,
+ 0xbb, 0x50, 0x53, 0x4c, 0x4f, 0x57, 0x20, 0x20,
+ 0x00, 0xb4, 0x50, 0x4e, 0x4f, 0x52, 0x4d, 0x41,
+ 0x4c, 0x00, 0xbb, 0x50, 0x46, 0x41, 0x53, 0x54,
+ 0x20, 0x20, 0x00, 0xb7, 0x50, 0x43, 0x52, 0x41,
+ 0x5a, 0x59, 0x20, 0x00, 0xbb, 0x5f, 0x53, 0x4c,
+ 0x4f, 0x57, 0x20, 0x20, 0x00, 0xb4, 0x5f, 0x4e,
+ 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x00, 0xbb, 0x5f,
+ 0x46, 0x41, 0x53, 0x54, 0x20, 0x20, 0x00, 0xb7,
+ 0x5f, 0x43, 0x52, 0x41, 0x5a, 0x59, 0x20, 0x00,
+ 0xb8, 0x6e, 0x43, 0x4c, 0x49, 0x43, 0x4b, 0x20,
+ 0x00, 0xbb, 0x6e, 0x53, 0x4c, 0x4f, 0x57, 0x20,
+ 0x20, 0x00, 0xb4, 0x6e, 0x4e, 0x4f, 0x52, 0x4d,
+ 0x41, 0x4c, 0x00, 0xbb, 0x6e, 0x46, 0x41, 0x53,
+ 0x54, 0x20, 0x20, 0x00, 0xb7, 0x6e, 0x43, 0x52,
+ 0x41, 0x5a, 0x59, 0x20, 0x00, 0xbe, 0x7d, 0x4d,
+ 0x4f, 0x4e, 0x4f, 0x20, 0x00, 0xbb, 0x7d, 0x43,
+ 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0x3b, 0x0c, 0xca,
+ 0x0c, 0x00, 0x3b, 0x1b, 0xca, 0x0c, 0x00, 0x3b,
+ 0x2a, 0xca, 0x0c, 0x00, 0x3b, 0x39, 0xca, 0x0c,
+ 0x00, 0x3b, 0x48, 0xca, 0x0c, 0x00, 0x3b, 0x57,
+ 0xca, 0x0c, 0x00, 0x3b, 0x66, 0xca, 0x0c, 0x00,
+ 0x3b, 0x75, 0xca, 0x0c, 0x00, 0x3b, 0x84, 0xca,
+ 0x0c, 0x00, 0x3b, 0x93, 0xca, 0x0c, 0x00, 0x6e,
+ 0xaf, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xcc, 0xdd, 0x43, 0x61, 0x6e, 0x63, 0x65,
+ 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x5f, 0x00, 0x0d, 0x0a, 0x48,
+ 0x45, 0x4c, 0x4c, 0x4f, 0x2c, 0x20, 0x56, 0x4f,
+ 0x59, 0x45, 0x55, 0x52, 0x21, 0x0d, 0x0a, 0xaf,
+ 0xb3, 0xa6, 0x64, 0x00, 0x0a, 0x01, 0x01, 0x02,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x28, 0x1b, 0x1c, 0x28,
+ 0x1d, 0x1e, 0x28, 0x1b, 0x28, 0x1f, 0x20, 0x28,
+ 0x1b, 0x1c, 0x28, 0x1d, 0x28, 0x1f, 0x28, 0x1b,
+ 0x00, 0x28, 0x1b, 0x1c, 0x28, 0x1d, 0x1e, 0x28,
+ 0x1b, 0x28, 0x1f, 0x20, 0x28, 0x1b, 0x1c, 0x28,
+ 0x1d, 0x28, 0x1f, 0x28, 0x1b, 0x00, 0x2a, 0x26,
+ 0x2a, 0x2a, 0x27, 0x2a, 0x27, 0x2a, 0x2a, 0x26,
+ 0x2a, 0x26, 0x2a, 0x2a, 0x2a, 0x27, 0x26, 0x2a,
+ 0x2a, 0x27, 0x00, 0x21, 0x22, 0x23, 0x24, 0x29,
+ 0x25, 0x29, 0x29, 0x25, 0x29, 0x21, 0x22, 0x21,
+ 0x24, 0x29, 0x21, 0x29, 0x29, 0x21, 0x29, 0x00,
+ 0x00, 0x00, 0x01, 0x46, 0x65, 0x82, 0x65, 0xb2,
+ 0x65, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04,
+ 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06,
+ 0x06, 0x06, 0x06, 0x07, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x08, 0x08, 0x08, 0x09, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x04, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x00,
+ 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x0a, 0x00, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ 0x1a, 0x00, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
+ 0x12, 0x00, 0x00, 0x00, 0x3a, 0x0d, 0x28, 0x2e,
+ 0x00, 0x20, 0x31, 0x18, 0x10, 0x3a, 0x23, 0x14,
+ 0x3f, 0x2b, 0x17, 0x3f, 0x30, 0x22, 0x3f, 0x34,
+ 0x21, 0x3f, 0x00, 0x00, 0x36, 0x00, 0x00, 0x28,
+ 0x00, 0x00, 0x11, 0x2f, 0x3f, 0x11, 0x24, 0x3f,
+ 0x11, 0x16, 0x3f, 0x1d, 0x11, 0x1f, 0x28, 0x2f,
+ 0x33, 0x35, 0x13, 0x10, 0x0c, 0x28, 0x21, 0x19,
+ 0x00, 0x92, 0x66, 0x94, 0x66, 0x96, 0x66, 0x98,
+ 0x66, 0x9a, 0x66, 0x9c, 0x66, 0x9e, 0x66, 0xa0,
+ 0x66, 0xa2, 0x66, 0xa4, 0x66, 0xa6, 0x66, 0xb1,
+ 0x66, 0xbc, 0x66, 0xbe, 0x66, 0xc9, 0x66, 0xcb,
+ 0x66, 0xd6, 0x66, 0xd8, 0x66, 0xe3, 0x66, 0xe5,
+ 0x66, 0xf0, 0x66, 0xf2, 0x66, 0xf4, 0x66, 0xf6,
+ 0x66, 0xf8, 0x66, 0xfa, 0x66, 0x20, 0x67, 0x22,
+ 0x67, 0x24, 0x67, 0x26, 0x67, 0x28, 0x67, 0x2a,
+ 0x67, 0x2c, 0x67, 0x2e, 0x67, 0x30, 0x67, 0x32,
+ 0x67, 0x34, 0x67, 0x36, 0x67, 0x38, 0x67, 0x3a,
+ 0x67, 0x3c, 0x67, 0x3e, 0x67, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x5c, 0x00, 0x50, 0x00, 0x97,
+ 0x00, 0x0f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x01, 0xab, 0x00, 0x09, 0xff, 0xff, 0xff,
+ 0xff, 0x1f, 0x00, 0xb7, 0x00, 0x55, 0x00, 0xc4,
+ 0x00, 0x0c, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+ 0x00, 0x00, 0xd2, 0x00, 0xc7, 0x00, 0x08, 0xff,
+ 0xff, 0xff, 0xff, 0x3a, 0x00, 0x9e, 0x00, 0x3f,
+ 0x01, 0xc7, 0x00, 0x0a, 0xff, 0xff, 0xff, 0xff,
+ 0x82, 0x00, 0xa0, 0x00, 0x3f, 0x01, 0xa9, 0x00,
+ 0x0a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
+ 0x00, 0x86, 0x00, 0xc7, 0x00, 0x12, 0x00, 0x00,
+ 0x00, 0x00, 0xaf, 0x00, 0xae, 0x00, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0xdb, 0x00, 0xa9, 0x00, 0x0e,
+ 0x00, 0x00, 0x00, 0x00, 0x3f, 0x01, 0xc7, 0x00,
+ 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x9a, 0x67, 0x9b, 0x67, 0xf0, 0x67, 0x29,
+ 0x68, 0x70, 0x68, 0xc5, 0x68, 0xfe, 0x68, 0x37,
+ 0x69, 0x8c, 0x69, 0xc5, 0x69, 0x1a, 0x6a, 0x6f,
+ 0x6a, 0xc4, 0x6a, 0xfd, 0x6a, 0x6e, 0x6b, 0xdf,
+ 0x6b, 0x18, 0x6c, 0x19, 0x6c, 0x6e, 0x6c, 0xa7,
+ 0x6c, 0xee, 0x6c, 0x35, 0x6d, 0x7c, 0x6d, 0xb5,
+ 0x6d, 0xee, 0x6d, 0x19, 0x6e, 0x36, 0x6e, 0xd1,
+ 0x6e, 0xfc, 0x6e, 0x27, 0x6f, 0x6e, 0x6f, 0x8b,
+ 0x6f, 0xd2, 0x6f, 0x0b, 0x70, 0x6e, 0x70, 0x99,
+ 0x70, 0xb6, 0x70, 0xb7, 0x70, 0xf0, 0x70, 0xf1,
+ 0x70, 0xf2, 0x70, 0xf3, 0x70, 0x00, 0x06, 0x01,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0xd2, 0x00, 0xb1,
+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xe4, 0x00, 0x9b, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xfc, 0x00, 0x8e, 0x00, 0x00, 0x03, 0x00,
+ 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x3f,
+ 0x01, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0xc0, 0x00, 0xa2, 0x00, 0xc7,
+ 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x00, 0xff,
+ 0x00, 0x9c, 0x00, 0x3f, 0x01, 0xc7, 0x00, 0x04,
+ 0x00, 0x00, 0x01, 0x04, 0x01, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0xcb, 0x00, 0xbf, 0x00, 0x00, 0x03,
+ 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xe8, 0x00, 0x99, 0x00, 0x00, 0x03, 0x02, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x01,
+ 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0xe5, 0x00, 0xb9, 0x00, 0x3f, 0x01, 0xc7, 0x00,
+ 0x04, 0x00, 0x00, 0x01, 0x05, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xde, 0x00, 0xaf, 0x00, 0x00,
+ 0x03, 0x02, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x7b, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+ 0x01, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01,
+ 0x00, 0x00, 0x00, 0xc0, 0x00, 0x3f, 0x01, 0xc7,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0xf4,
+ 0x00, 0x93, 0x00, 0x3f, 0x01, 0xb0, 0x00, 0x04,
+ 0x00, 0x04, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0xf9, 0x00, 0x9c, 0x00, 0x00, 0x03,
+ 0x00, 0x00, 0x01, 0x00, 0xf9, 0x00, 0x00, 0x00,
+ 0x08, 0x01, 0x9b, 0x00, 0x00, 0x03, 0x00, 0x03,
+ 0x01, 0x00, 0x08, 0x01, 0x00, 0x00, 0x3f, 0x01,
+ 0x7c, 0x00, 0x00, 0x03, 0x00, 0x03, 0x01, 0x03,
+ 0x46, 0x00, 0x00, 0x00, 0x6c, 0x00, 0xa4, 0x00,
+ 0x00, 0x03, 0x00, 0x03, 0x02, 0x01, 0x00, 0x00,
+ 0xb5, 0x00, 0x6b, 0x00, 0xc7, 0x00, 0x02, 0x01,
+ 0x00, 0x00, 0x03, 0x00, 0x87, 0x00, 0xb7, 0x00,
+ 0x3f, 0x01, 0xc7, 0x00, 0x04, 0x00, 0x00, 0x01,
+ 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x01, 0xac,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x8f, 0x00, 0xbc, 0x00, 0x00,
+ 0x03, 0x02, 0x00, 0x01, 0x00, 0x33, 0x01, 0x00,
+ 0x00, 0x3f, 0x01, 0xc7, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0xc7, 0x00, 0x00, 0x03, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x01,
+ 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0xfa, 0x00, 0x00, 0x00, 0x3f, 0x01, 0xc7, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x53, 0x00,
+ 0xaf, 0x00, 0xe6, 0x00, 0xbe, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x01, 0x00, 0xce, 0x00, 0xb3,
+ 0x00, 0x3f, 0x01, 0xc1, 0x00, 0x04, 0x00, 0x04,
+ 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x3f,
+ 0x01, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0xb6, 0x00, 0x5e, 0x00, 0xc1,
+ 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0xc7, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x01, 0x00,
+ 0x00, 0x3f, 0x01, 0xc7, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0xff, 0x00, 0x00, 0x00, 0x3f,
+ 0x01, 0xc1, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04,
+ 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x00,
+ 0xb2, 0x00, 0x00, 0x03, 0x02, 0x00, 0x01, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x3f, 0x01, 0xac, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xf1, 0x00,
+ 0x00, 0x00, 0x3f, 0x01, 0xbc, 0x00, 0x00, 0x00,
+ 0x04, 0x03, 0x01, 0x00, 0x16, 0x01, 0x00, 0x00,
+ 0x3f, 0x01, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59,
+ 0x00, 0x8a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01,
+ 0x00, 0x59, 0x00, 0x00, 0x00, 0x3f, 0x01, 0x94,
+ 0x00, 0x00, 0x00, 0x04, 0x03, 0x01, 0x00, 0xec,
+ 0x00, 0x00, 0x00, 0x3f, 0x01, 0xa2, 0x00, 0x00,
+ 0x00, 0x04, 0x03, 0x02, 0x00, 0x00, 0x00, 0x94,
+ 0x00, 0x3e, 0x00, 0xc7, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x71,
+ 0x00, 0xc7, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0xbd, 0x00, 0x3f, 0x01, 0xc7,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x00,
+ 0x00, 0x00, 0x91, 0x00, 0x1a, 0x00, 0xa3, 0x00,
+ 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0xb3, 0x00, 0xa4, 0x00, 0xc7, 0x00, 0x02, 0x01,
+ 0x00, 0x00, 0x02, 0x00, 0xa5, 0x00, 0xbd, 0x00,
+ 0xc8, 0x00, 0xc7, 0x00, 0x02, 0x01, 0x00, 0x00,
+ 0x03, 0x00, 0xaf, 0x00, 0x83, 0x00, 0x3f, 0x01,
+ 0x97, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00,
+ 0xc3, 0x00, 0x98, 0x00, 0x3f, 0x01, 0xb3, 0x00,
+ 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x42, 0x00,
+ 0x00, 0x00, 0x7c, 0x00, 0x99, 0x00, 0x00, 0x03,
+ 0x00, 0x03, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0xfc, 0x00, 0xa8, 0x00, 0x00, 0x03, 0x02,
+ 0x00, 0x01, 0x03, 0x00, 0x00, 0xa9, 0x00, 0x30,
+ 0x00, 0xb8, 0x00, 0x00, 0x03, 0x02, 0x00, 0x01,
+ 0x00, 0xfd, 0x00, 0x00, 0x00, 0x1f, 0x01, 0xac,
+ 0x00, 0x00, 0x03, 0x02, 0x03, 0x01, 0x00, 0x20,
+ 0x01, 0x00, 0x00, 0x2c, 0x01, 0xa2, 0x00, 0x00,
+ 0x03, 0x02, 0x03, 0x01, 0x00, 0x2d, 0x01, 0x00,
+ 0x00, 0x3f, 0x01, 0x87, 0x00, 0x00, 0x03, 0x02,
+ 0x03, 0x02, 0x01, 0x00, 0x00, 0xc2, 0x00, 0x3f,
+ 0x01, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0x01, 0x01, 0x00, 0x00, 0xba, 0x00, 0x4b, 0x00,
+ 0xc7, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x01,
+ 0xe6, 0x00, 0xba, 0x00, 0x3f, 0x01, 0xc7, 0x00,
+ 0x04, 0x00, 0x04, 0x01, 0x02, 0x00, 0x3e, 0x00,
+ 0x00, 0x00, 0x70, 0x00, 0xaf, 0x00, 0x00, 0x00,
+ 0x04, 0x03, 0x02, 0x00, 0x70, 0x00, 0x00, 0x00,
+ 0x3f, 0x01, 0xb2, 0x00, 0x00, 0x00, 0x04, 0x03,
+ 0x08, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x3f,
+ 0x01, 0x6e, 0x00, 0x00, 0x03, 0x04, 0x03, 0x01,
+ 0x00, 0x7a, 0x00, 0x6f, 0x00, 0x3f, 0x01, 0x89,
+ 0x00, 0x04, 0x00, 0x04, 0x03, 0x01, 0x00, 0xfc,
+ 0x00, 0x8d, 0x00, 0x3f, 0x01, 0xb8, 0x00, 0x04,
+ 0x00, 0x04, 0x03, 0x01, 0x00, 0x1c, 0x01, 0xb9,
+ 0x00, 0x3f, 0x01, 0xc7, 0x00, 0x04, 0x00, 0x04,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x8a,
+ 0x00, 0xb2, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0xb3, 0x00, 0x23, 0x00, 0xc7,
+ 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x24,
+ 0x00, 0xb3, 0x00, 0x6d, 0x00, 0xbe, 0x00, 0x02,
+ 0x00, 0x02, 0x00, 0x03, 0x00, 0x77, 0x00, 0xbc,
+ 0x00, 0xe8, 0x00, 0xc7, 0x00, 0x00, 0x01, 0x00,
+ 0x01, 0x08, 0x03, 0x01, 0xde, 0x00, 0xb4, 0x00,
+ 0x2c, 0x01, 0xc7, 0x00, 0x04, 0x00, 0x00, 0x01,
+ 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x00,
+ 0xa7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03,
+ 0x6f, 0x00, 0x00, 0x00, 0xef, 0x00, 0xb1, 0x00,
+ 0x00, 0x03, 0x00, 0x03, 0x01, 0x03, 0xf0, 0x00,
+ 0x00, 0x00, 0x22, 0x01, 0xa5, 0x00, 0x00, 0x03,
+ 0x00, 0x00, 0x01, 0x03, 0x23, 0x01, 0x00, 0x00,
+ 0x3f, 0x01, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x02, 0x01, 0x00, 0x00, 0xb8, 0x00, 0x8b, 0x00,
+ 0xc7, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x01,
+ 0xa3, 0x00, 0xb8, 0x00, 0xdd, 0x00, 0xc7, 0x00,
+ 0x04, 0x00, 0x00, 0x01, 0x03, 0x01, 0x2d, 0x01,
+ 0xaf, 0x00, 0x3f, 0x01, 0xc7, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x3f, 0x01, 0x50, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b,
+ 0x00, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x14, 0x01, 0x00, 0x00, 0x3f, 0x01, 0xc7,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x65, 0x00, 0x3f, 0x01, 0xc7, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x00, 0x61,
+ 0x00, 0x00, 0x00, 0x3f, 0x01, 0xa3, 0x00, 0x00,
+ 0x00, 0x04, 0x03, 0x01, 0x00, 0x34, 0x00, 0x85,
+ 0x00, 0x63, 0x00, 0x97, 0x00, 0x04, 0x00, 0x04,
+ 0x00, 0x01, 0x00, 0xab, 0x00, 0xa4, 0x00, 0x3f,
+ 0x01, 0xb6, 0x00, 0x00, 0x00, 0x04, 0x03, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x72,
+ 0x00, 0x00, 0x03, 0x02, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x72, 0x00, 0x19, 0x00, 0xaa, 0x00, 0x02,
+ 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0xaa,
+ 0x00, 0x45, 0x00, 0xc7, 0x00, 0x02, 0x01, 0x00,
+ 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0xa3, 0x00,
+ 0x2c, 0x00, 0xc7, 0x00, 0x02, 0x01, 0x00, 0x00,
+ 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x01,
+ 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04,
+ 0x0f, 0x01, 0xa3, 0x00, 0x3f, 0x01, 0xbd, 0x00,
+ 0x04, 0x00, 0x04, 0x03, 0x01, 0x00, 0xe2, 0x00,
+ 0x00, 0x00, 0x3f, 0x01, 0xaa, 0x00, 0x00, 0x00,
+ 0x04, 0x03, 0x05, 0x01, 0x03, 0xb0, 0x00, 0xa4,
+ 0x00, 0x3f, 0x01, 0xbc, 0x00, 0x04, 0x00, 0x04,
+ 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0e,
+ 0x00, 0x82, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01,
+ 0x03, 0x0f, 0x00, 0x00, 0x00, 0x88, 0x00, 0xb4,
+ 0x00, 0x00, 0x03, 0x00, 0x03, 0x01, 0x03, 0x89,
+ 0x00, 0x00, 0x00, 0x3f, 0x01, 0xa3, 0x00, 0x00,
+ 0x00, 0x04, 0x00, 0x02, 0x01, 0x00, 0x00, 0xc4,
+ 0x00, 0x93, 0x00, 0xc7, 0x00, 0x02, 0x01, 0x00,
+ 0x00, 0x05, 0x01, 0x00, 0xdc, 0x00, 0x00, 0x00,
+ 0x3f, 0x01, 0xc7, 0x00, 0x00, 0x03, 0x00, 0x03,
+ 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00,
+ 0xae, 0x00, 0x00, 0x03, 0x02, 0x00, 0x01, 0x03,
+ 0x51, 0x00, 0x00, 0x00, 0x78, 0x00, 0xab, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x79, 0x00,
+ 0x00, 0x00, 0x3f, 0x01, 0xb1, 0x00, 0x00, 0x00,
+ 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0xc0, 0x00,
+ 0xa9, 0x00, 0xc7, 0x00, 0x02, 0x01, 0x00, 0x00,
+ 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+ 0x01, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0xaa, 0x00, 0x29, 0x00, 0xbf,
+ 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x01, 0x00,
+ 0x00, 0xbf, 0x00, 0x9e, 0x00, 0xc7, 0x00, 0x02,
+ 0x01, 0x00, 0x00, 0x01, 0x01, 0xc5, 0x00, 0xaf,
+ 0x00, 0x3f, 0x01, 0xc7, 0x00, 0x04, 0x00, 0x00,
+ 0x01, 0x01, 0x04, 0x00, 0x01, 0xa8, 0x00, 0x3f,
+ 0x01, 0xae, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04,
+ 0x01, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x52, 0x00,
+ 0xba, 0x00, 0x00, 0x03, 0x02, 0x00, 0x01, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x3f, 0x01, 0xa9, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xe0, 0x00,
+ 0xaa, 0x00, 0x3f, 0x01, 0xb2, 0x00, 0x00, 0x00,
+ 0x04, 0x03, 0x01, 0x00, 0x12, 0x01, 0xb3, 0x00,
+ 0x3f, 0x01, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
+ 0x00, 0xc7, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01,
+ 0x03, 0x47, 0x00, 0x00, 0x00, 0x12, 0x01, 0xa6,
+ 0x00, 0x00, 0x03, 0x00, 0x03, 0x01, 0x03, 0x63,
+ 0x00, 0x00, 0x00, 0xd3, 0x00, 0xaa, 0x00, 0x00,
+ 0x03, 0x00, 0x03, 0x01, 0x00, 0x12, 0x01, 0x00,
+ 0x00, 0x3f, 0x01, 0xc7, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x96, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x03, 0x79, 0x00, 0x00, 0x00, 0x3f, 0x01,
+ 0x90, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01,
+ 0x79, 0x00, 0xa4, 0x00, 0x3f, 0x01, 0xc7, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x69, 0x00, 0xc7, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x03, 0x6a, 0x00, 0x00,
+ 0x00, 0x3f, 0x01, 0xa5, 0x00, 0x00, 0x03, 0x02,
+ 0x03, 0x0b, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x3f, 0x01, 0x83, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x01, 0x03, 0x00, 0x00, 0x84, 0x00, 0xda, 0x00,
+ 0x9e, 0x00, 0x02, 0x03, 0x02, 0x00, 0x01, 0x03,
+ 0x00, 0x00, 0x9f, 0x00, 0xc2, 0x00, 0xa9, 0x00,
+ 0x00, 0x03, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
+ 0xaa, 0x00, 0xa4, 0x00, 0xaf, 0x00, 0x00, 0x03,
+ 0x02, 0x00, 0x01, 0x03, 0x00, 0x00, 0xb0, 0x00,
+ 0x7f, 0x00, 0xbb, 0x00, 0x00, 0x03, 0x02, 0x00,
+ 0x01, 0x03, 0x00, 0x00, 0xbc, 0x00, 0x5e, 0x00,
+ 0xc3, 0x00, 0x00, 0x03, 0x02, 0x00, 0x01, 0x02,
+ 0x00, 0x00, 0xc4, 0x00, 0x4b, 0x00, 0xc7, 0x00,
+ 0x00, 0x03, 0x02, 0x00, 0x01, 0x03, 0xef, 0x00,
+ 0x84, 0x00, 0x3f, 0x01, 0xa4, 0x00, 0x04, 0x00,
+ 0x00, 0x01, 0x01, 0x03, 0xdb, 0x00, 0xa5, 0x00,
+ 0x3f, 0x01, 0xb4, 0x00, 0x04, 0x00, 0x00, 0x01,
+ 0x01, 0x03, 0xc2, 0x00, 0xb5, 0x00, 0x3f, 0x01,
+ 0xbe, 0x00, 0x04, 0x00, 0x00, 0x01, 0x01, 0x04,
+ 0xa2, 0x00, 0xbf, 0x00, 0x3f, 0x01, 0xc7, 0x00,
+ 0x04, 0x00, 0x00, 0x01, 0x03, 0x01, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x93, 0x00, 0x8c, 0x00, 0x00,
+ 0x03, 0x00, 0x03, 0x01, 0x03, 0x94, 0x00, 0x00,
+ 0x00, 0x3f, 0x01, 0x94, 0x00, 0x00, 0x00, 0x04,
+ 0x03, 0x01, 0x00, 0xe9, 0x00, 0x95, 0x00, 0x3f,
+ 0x01, 0xc7, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03,
+ 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x01,
+ 0xa5, 0x00, 0x00, 0x03, 0x00, 0x03, 0x01, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0xc7, 0x00,
+ 0x02, 0x00, 0x02, 0x00, 0x01, 0x03, 0x30, 0x00,
+ 0x00, 0x00, 0x4f, 0x00, 0xab, 0x00, 0x00, 0x03,
+ 0x00, 0x03, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x3f, 0x01, 0x95, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x3f,
+ 0x01, 0x9a, 0x00, 0x00, 0x00, 0x04, 0x03, 0x01,
+ 0x04, 0x22, 0x01, 0x00, 0x00, 0x3f, 0x01, 0xc7,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x75,
+ 0x00, 0x9c, 0x00, 0xe9, 0x00, 0xbf, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x11, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x3f, 0x01, 0xa5, 0x00, 0x00, 0x03, 0x00, 0x03,
+ 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x37, 0x00,
+ 0xb0, 0x00, 0x02, 0x03, 0x02, 0x00, 0x05, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x00, 0xc7,
+ 0x00, 0x00, 0x03, 0x02, 0x00, 0x01, 0x03, 0x28,
+ 0x00, 0x00, 0x00, 0x8e, 0x00, 0xa9, 0x00, 0x00,
+ 0x03, 0x02, 0x03, 0x01, 0x03, 0x8e, 0x00, 0x00,
+ 0x00, 0x07, 0x01, 0xa1, 0x00, 0x00, 0x03, 0x00,
+ 0x03, 0x01, 0x00, 0x08, 0x01, 0x00, 0x00, 0x3f,
+ 0x01, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0xdf, 0x00, 0xb7, 0x00, 0x3f, 0x01, 0xc7,
+ 0x00, 0x04, 0x00, 0x04, 0x01, 0x03, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xaf, 0x00,
+ 0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x50, 0x00, 0xa7, 0x00, 0x00, 0x03,
+ 0x02, 0x00, 0x01, 0x03, 0x50, 0x00, 0x00, 0x00,
+ 0x3f, 0x01, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x01, 0x03, 0x97, 0x00, 0x00, 0x00, 0xb4, 0x00,
+ 0xa2, 0x00, 0x00, 0x03, 0x00, 0x03, 0x07, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x80,
+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x03, 0x45,
+ 0x00, 0x00, 0x00, 0x78, 0x00, 0x86, 0x00, 0x00,
+ 0x03, 0x00, 0x03, 0x01, 0x03, 0x78, 0x00, 0x00,
+ 0x00, 0x07, 0x01, 0xa8, 0x00, 0x00, 0x03, 0x00,
+ 0x03, 0x01, 0x03, 0x07, 0x01, 0x00, 0x00, 0x3f,
+ 0x01, 0x9e, 0x00, 0x00, 0x03, 0x00, 0x03, 0x02,
+ 0x00, 0x00, 0x00, 0xb4, 0x00, 0x4d, 0x00, 0xc7,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0c,
+ 0x01, 0xbe, 0x00, 0x3f, 0x01, 0xc7, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0a, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x01, 0x03, 0x64, 0x00, 0x00, 0x00,
+ 0x3f, 0x01, 0xa8, 0x00, 0x00, 0x03, 0x00, 0x03,
+ 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x63, 0x00,
+ 0xb7, 0x00, 0x00, 0x03, 0x02, 0x00, 0x02, 0x00,
+ 0xb6, 0x00, 0xb2, 0x00, 0x3f, 0x01, 0xc7, 0x00,
+ 0x00, 0x00, 0x03, 0x00, 0x02, 0x01, 0x00, 0x7d,
+ 0x00, 0x00, 0x00, 0x3f, 0x01, 0xc7, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x3f, 0x01, 0xbe, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x28, 0x00, 0xc7, 0x00, 0x00, 0x03, 0x00,
+ 0x00, 0x01, 0x03, 0x29, 0x00, 0x00, 0x00, 0x5f,
+ 0x00, 0xa2, 0x00, 0x00, 0x03, 0x00, 0x03, 0x01,
+ 0x03, 0x5f, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x9b,
+ 0x00, 0x00, 0x03, 0x00, 0x03, 0x01, 0x00, 0xc8,
+ 0x00, 0x00, 0x00, 0x3f, 0x01, 0xc7, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x48,
+ 0x71, 0x4c, 0x71, 0x50, 0x71, 0x54, 0x71, 0x58,
+ 0x71, 0x5c, 0x71, 0x60, 0x71, 0x64, 0x71, 0x68,
+ 0x71, 0x6c, 0x71, 0x70, 0x71, 0x84, 0x71, 0x88,
+ 0x71, 0x8c, 0x71, 0x9c, 0x71, 0xa0, 0x71, 0xa4,
+ 0x71, 0xa8, 0x71, 0xd0, 0x71, 0xd4, 0x71, 0xee,
+ 0x71, 0xf2, 0x71, 0xf6, 0x71, 0xfa, 0x71, 0xfe,
+ 0x71, 0x02, 0x72, 0x06, 0x72, 0x0a, 0x72, 0x18,
+ 0x72, 0x1c, 0x72, 0x20, 0x72, 0x24, 0x72, 0x28,
+ 0x72, 0x2c, 0x72, 0x30, 0x72, 0x34, 0x72, 0x38,
+ 0x72, 0x3c, 0x72, 0x40, 0x72, 0x44, 0x72, 0x48,
+ 0x72, 0x4c, 0x72, 0xc7, 0x00, 0xff, 0xff, 0xc7,
+ 0x00, 0xff, 0xff, 0xc7, 0x00, 0xff, 0xff, 0xc7,
+ 0x00, 0xff, 0xff, 0xc7, 0x00, 0xff, 0xff, 0xc7,
+ 0x00, 0xff, 0xff, 0xc7, 0x00, 0xff, 0xff, 0xc7,
+ 0x00, 0xff, 0xff, 0xc7, 0x00, 0xff, 0xff, 0xc7,
+ 0x00, 0xff, 0xff, 0x67, 0x2d, 0x6a, 0x28, 0x70,
+ 0x23, 0x79, 0x1e, 0x7f, 0x19, 0x82, 0x14, 0x87,
+ 0x0f, 0x8c, 0x0a, 0xc7, 0x00, 0xff, 0xff, 0xc7,
+ 0x00, 0xff, 0xff, 0xc7, 0x00, 0xff, 0xff, 0x6e,
+ 0x17, 0x73, 0x15, 0x78, 0x13, 0x7d, 0x11, 0x82,
+ 0x0f, 0x85, 0x0c, 0xc7, 0x00, 0xff, 0xff, 0xc7,
+ 0x00, 0xff, 0xff, 0xc7, 0x00, 0xff, 0xff, 0xc7,
+ 0x00, 0xff, 0xff, 0x7a, 0x32, 0x7c, 0x30, 0x7e,
+ 0x2e, 0x80, 0x2c, 0x82, 0x2a, 0x84, 0x28, 0x86,
+ 0x24, 0x88, 0x20, 0x8a, 0x1d, 0x8c, 0x1a, 0x8e,
+ 0x17, 0x90, 0x14, 0x92, 0x11, 0x94, 0x0e, 0x96,
+ 0x0b, 0x98, 0x08, 0x9a, 0x05, 0x9c, 0x03, 0xc7,
+ 0x00, 0xff, 0xff, 0xc7, 0x00, 0xff, 0xff, 0x83,
+ 0x12, 0x85, 0x10, 0x87, 0x0e, 0x89, 0x0c, 0x8b,
+ 0x0b, 0x8d, 0x0a, 0x8f, 0x09, 0x91, 0x08, 0x93,
+ 0x06, 0x95, 0x04, 0x97, 0x02, 0xc7, 0x00, 0xff,
+ 0xff, 0xc7, 0x00, 0xff, 0xff, 0xc7, 0x00, 0xff,
+ 0xff, 0xc7, 0x00, 0xff, 0xff, 0xc7, 0x00, 0xff,
+ 0xff, 0xc7, 0x00, 0xff, 0xff, 0xc7, 0x00, 0xff,
+ 0xff, 0xc7, 0x00, 0xff, 0xff, 0x8e, 0x0c, 0x90,
+ 0x0a, 0x92, 0x08, 0x94, 0x06, 0x96, 0x04, 0xc7,
+ 0x00, 0xff, 0xff, 0xc7, 0x00, 0xff, 0xff, 0xc7,
+ 0x00, 0xff, 0xff, 0xc7, 0x00, 0xff, 0xff, 0xc7,
+ 0x00, 0xff, 0xff, 0xc7, 0x00, 0xff, 0xff, 0xc7,
+ 0x00, 0xff, 0xff, 0xc7, 0x00, 0xff, 0xff, 0xc7,
+ 0x00, 0xff, 0xff, 0xc7, 0x00, 0xff, 0xff, 0xc7,
+ 0x00, 0xff, 0xff, 0xc7, 0x00, 0xff, 0xff, 0xc7,
+ 0x00, 0xff, 0xff, 0xc7, 0x00, 0xff, 0xff, 0xc7,
+ 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xa8,
+ 0x72, 0xaa, 0x72, 0xc7, 0x73, 0x34, 0x75, 0xca,
+ 0x76, 0xda, 0x77, 0xbe, 0x79, 0x52, 0x7c, 0xe7,
+ 0x7e, 0x3e, 0x80, 0x1a, 0x81, 0x2c, 0x84, 0xd9,
+ 0x85, 0x20, 0x87, 0x06, 0x88, 0xd9, 0x89, 0x6d,
+ 0x8a, 0xca, 0x8b, 0xec, 0x8c, 0x19, 0x90, 0x6f,
+ 0x93, 0x2c, 0x95, 0x9c, 0x97, 0x08, 0x9b, 0x22,
+ 0x9d, 0x00, 0x9f, 0x10, 0xa0, 0xc0, 0xa3, 0x82,
+ 0xa4, 0xde, 0xa5, 0xc1, 0xa8, 0x5c, 0xaa, 0x12,
+ 0xac, 0x46, 0xaf, 0x5c, 0xb0, 0xa5, 0xb3, 0xfa,
+ 0xb3, 0xfc, 0xb3, 0xeb, 0xb4, 0xed, 0xb4, 0xef,
+ 0xb4, 0xf1, 0xb4, 0x00, 0x00, 0xb6, 0x72, 0xcf,
+ 0x72, 0xe8, 0x72, 0x38, 0x73, 0x7f, 0x73, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0xa6, 0x00, 0x38, 0x00,
+ 0xc7, 0x00, 0x38, 0x00, 0xb4, 0x00, 0x00, 0x00,
+ 0xb4, 0x00, 0x04, 0x01, 0x70, 0x61, 0x74, 0x68,
+ 0x00, 0x01, 0x02, 0xb6, 0x00, 0xb5, 0x00, 0x10,
+ 0x01, 0xc7, 0x00, 0xd9, 0x00, 0xc1, 0x00, 0xdd,
+ 0x00, 0xc7, 0x00, 0x03, 0x01, 0x70, 0x61, 0x74,
+ 0x68, 0x00, 0x01, 0x03, 0x20, 0x01, 0x4c, 0x00,
+ 0x2f, 0x01, 0x59, 0x00, 0x10, 0x01, 0x64, 0x00,
+ 0x10, 0x01, 0x64, 0x00, 0x01, 0x01, 0x6d, 0x79,
+ 0x73, 0x74, 0x65, 0x72, 0x69, 0x6f, 0x75, 0x73,
+ 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x00,
+ 0x42, 0x6f, 0x79, 0x2c, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x63, 0x6f, 0x75, 0x6c, 0x64, 0x20,
+ 0x62, 0x65, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20,
+ 0x6b, 0x69, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65,
+ 0x21, 0x00, 0x00, 0x04, 0xf1, 0x00, 0x0e, 0x00,
+ 0x3f, 0x01, 0x5f, 0x00, 0x10, 0x01, 0x64, 0x00,
+ 0x10, 0x01, 0x64, 0x00, 0x01, 0x01, 0x66, 0x65,
+ 0x6e, 0x63, 0x65, 0x00, 0x54, 0x68, 0x69, 0x73,
+ 0x20, 0x69, 0x73, 0x20, 0x6d, 0x61, 0x64, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x62, 0x61, 0x72, 0x62,
+ 0x65, 0x64, 0x20, 0x77, 0x69, 0x72, 0x65, 0x2c,
+ 0x00, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x27,
+ 0x73, 0x20, 0x72, 0x75, 0x73, 0x74, 0x79, 0x2e,
+ 0x00, 0x00, 0x05, 0x40, 0x00, 0x5a, 0x00, 0xb9,
+ 0x00, 0xa6, 0x00, 0x7c, 0x00, 0xb7, 0x00, 0x7c,
+ 0x00, 0xb7, 0x00, 0x01, 0x01, 0x74, 0x65, 0x6e,
+ 0x74, 0x00, 0x54, 0x68, 0x65, 0x20, 0x63, 0x61,
+ 0x6d, 0x6f, 0x75, 0x66, 0x6c, 0x61, 0x67, 0x65,
+ 0x20, 0x69, 0x73, 0x6e, 0x27, 0x74, 0x20, 0x71,
+ 0x75, 0x69, 0x74, 0x65, 0x20, 0x73, 0x74, 0x61,
+ 0x74, 0x65, 0x2d, 0x6f, 0x66, 0x2d, 0x74, 0x68,
+ 0x65, 0x2d, 0x61, 0x72, 0x74, 0x2e, 0x2e, 0x2e,
+ 0x00, 0x00, 0xd5, 0x73, 0xf7, 0x73, 0x10, 0x74,
+ 0x29, 0x74, 0x5c, 0x74, 0xd0, 0x74, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xf0, 0x00, 0xa3, 0x00, 0xf0, 0x00, 0xa3,
+ 0x00, 0x04, 0x01, 0x62, 0x69, 0x72, 0x64, 0x00,
+ 0x42, 0x69, 0x67, 0x20, 0x62, 0x6f, 0x79, 0x2e,
+ 0x00, 0x00, 0x02, 0x16, 0x01, 0x55, 0x00, 0x3f,
+ 0x01, 0x7a, 0x00, 0x22, 0x01, 0x76, 0x00, 0x3f,
+ 0x01, 0x68, 0x00, 0x02, 0x01, 0x70, 0x61, 0x74,
+ 0x68, 0x00, 0x01, 0x03, 0x50, 0x00, 0xbd, 0x00,
+ 0xe6, 0x00, 0xc7, 0x00, 0xda, 0x00, 0xbf, 0x00,
+ 0xd6, 0x00, 0xc7, 0x00, 0x03, 0x01, 0x70, 0x61,
+ 0x74, 0x68, 0x00, 0x01, 0x04, 0xc6, 0x00, 0x23,
+ 0x00, 0xdc, 0x00, 0x96, 0x00, 0xd1, 0x00, 0x9a,
+ 0x00, 0xd1, 0x00, 0x9a, 0x00, 0x01, 0x01, 0x70,
+ 0x6f, 0x73, 0x74, 0x00, 0x54, 0x68, 0x61, 0x74,
+ 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x73, 0x20, 0x65,
+ 0x61, 0x73, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x63,
+ 0x6c, 0x69, 0x6d, 0x62, 0x2e, 0x00, 0x00, 0x05,
+ 0x38, 0x00, 0x65, 0x00, 0xac, 0x00, 0xbc, 0x00,
+ 0x73, 0x00, 0xc2, 0x00, 0x73, 0x00, 0xc2, 0x00,
+ 0x01, 0x01, 0x6d, 0x75, 0x64, 0x20, 0x70, 0x6f,
+ 0x6f, 0x6c, 0x00, 0x48, 0x65, 0x61, 0x76, 0x65,
+ 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x57, 0x6f,
+ 0x6f, 0x64, 0x73, 0x74, 0x6f, 0x63, 0x6b, 0x20,
+ 0x66, 0x61, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6c,
+ 0x6c, 0x69, 0x67, 0x61, 0x74, 0x6f, 0x72, 0x73,
+ 0x00, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x6f,
+ 0x73, 0x65, 0x20, 0x74, 0x6f, 0x75, 0x67, 0x68,
+ 0x20, 0x77, 0x6f, 0x6d, 0x65, 0x6e, 0x20, 0x66,
+ 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x20,
+ 0x6f, 0x6e, 0x20, 0x6c, 0x61, 0x74, 0x65, 0x20,
+ 0x54, 0x56, 0x00, 0x73, 0x68, 0x6f, 0x77, 0x73,
+ 0x2e, 0x00, 0x00, 0x06, 0xb8, 0x00, 0x90, 0x00,
+ 0xe4, 0x00, 0xa0, 0x00, 0xf0, 0x00, 0xa3, 0x00,
+ 0xdc, 0x00, 0xa1, 0x00, 0x04, 0x00, 0x62, 0x69,
+ 0x72, 0x64, 0x00, 0x49, 0x74, 0x20, 0x74, 0x6f,
+ 0x6f, 0x6b, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20,
+ 0x64, 0x72, 0x75, 0x67, 0x73, 0x20, 0x74, 0x68,
+ 0x65, 0x6e, 0x20, 0x66, 0x65, 0x6c, 0x6c, 0x20,
+ 0x35, 0x20, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73,
+ 0x2e, 0x00, 0x57, 0x68, 0x6f, 0x20, 0x77, 0x6f,
+ 0x75, 0x6c, 0x64, 0x6e, 0x27, 0x74, 0x20, 0x74,
+ 0x61, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x6e, 0x61,
+ 0x70, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x3f, 0x00, 0x00, 0x44,
+ 0x75, 0x7d, 0x75, 0xd0, 0x75, 0x0a, 0x76, 0x5a,
+ 0x76, 0x73, 0x76, 0x8c, 0x76, 0x00, 0x00, 0x01,
+ 0x04, 0x00, 0x77, 0x00, 0x14, 0x00, 0x8d, 0x00,
+ 0xca, 0x00, 0xb3, 0x00, 0xca, 0x00, 0xb3, 0x00,
+ 0x04, 0x01, 0x73, 0x68, 0x6f, 0x76, 0x65, 0x6c,
+ 0x00, 0x49, 0x74, 0x27, 0x73, 0x20, 0x61, 0x20,
+ 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x20, 0x6d, 0x69,
+ 0x6c, 0x69, 0x74, 0x61, 0x72, 0x79, 0x20, 0x73,
+ 0x68, 0x6f, 0x76, 0x65, 0x6c, 0x2e, 0x00, 0x00,
+ 0x02, 0x7c, 0x00, 0xaa, 0x00, 0xcf, 0x00, 0xc0,
+ 0x00, 0xca, 0x00, 0xb3, 0x00, 0xca, 0x00, 0xb3,
+ 0x00, 0x04, 0x01, 0x73, 0x6f, 0x6c, 0x69, 0x64,
+ 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x00,
+ 0x49, 0x27, 0x76, 0x65, 0x20, 0x67, 0x6f, 0x74,
+ 0x20, 0x61, 0x20, 0x66, 0x65, 0x65, 0x6c, 0x69,
+ 0x6e, 0x67, 0x20, 0x49, 0x27, 0x6d, 0x20, 0x67,
+ 0x6f, 0x6e, 0x6e, 0x61, 0x20, 0x6e, 0x65, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x00, 0x73,
+ 0x6f, 0x6d, 0x65, 0x68, 0x6f, 0x77, 0x2e, 0x2e,
+ 0x2e, 0x00, 0x00, 0x03, 0xab, 0x00, 0x63, 0x00,
+ 0xba, 0x00, 0x97, 0x00, 0xe1, 0x00, 0x9f, 0x00,
+ 0xe1, 0x00, 0x9f, 0x00, 0x04, 0x01, 0x70, 0x6c,
+ 0x61, 0x6e, 0x74, 0x00, 0x49, 0x74, 0x20, 0x6d,
+ 0x75, 0x73, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65,
+ 0x20, 0x61, 0x20, 0x76, 0x65, 0x72, 0x79, 0x20,
+ 0x73, 0x6f, 0x66, 0x74, 0x20, 0x74, 0x6f, 0x75,
+ 0x63, 0x68, 0x2e, 0x00, 0x00, 0x04, 0x27, 0x00,
+ 0x53, 0x00, 0xaa, 0x00, 0xa1, 0x00, 0xca, 0x00,
+ 0xb3, 0x00, 0xca, 0x00, 0xb3, 0x00, 0x04, 0x01,
+ 0x62, 0x72, 0x69, 0x63, 0x6b, 0x20, 0x77, 0x61,
+ 0x6c, 0x6c, 0x00, 0x54, 0x68, 0x65, 0x20, 0x62,
+ 0x72, 0x69, 0x63, 0x6b, 0x2d, 0x6c, 0x61, 0x79,
+ 0x65, 0x72, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65,
+ 0x6e, 0x00, 0x61, 0x20, 0x50, 0x69, 0x6e, 0x6b,
+ 0x20, 0x46, 0x6c, 0x6f, 0x79, 0x64, 0x20, 0x66,
+ 0x61, 0x6e, 0x2e, 0x00, 0x00, 0x05, 0xe0, 0x00,
+ 0x7a, 0x00, 0x3f, 0x01, 0x9b, 0x00, 0x13, 0x01,
+ 0x89, 0x00, 0x3f, 0x01, 0x80, 0x00, 0x02, 0x01,
+ 0x70, 0x61, 0x74, 0x68, 0x00, 0x01, 0x06, 0xfa,
+ 0x00, 0x9c, 0x00, 0x3f, 0x01, 0xc7, 0x00, 0x18,
+ 0x01, 0xb9, 0x00, 0x3f, 0x01, 0xb9, 0x00, 0x02,
+ 0x01, 0x70, 0x61, 0x74, 0x68, 0x00, 0x01, 0x07,
+ 0xb2, 0x00, 0xa1, 0x00, 0xc0, 0x00, 0xb4, 0x00,
+ 0xcb, 0x00, 0xb6, 0x00, 0xcb, 0x00, 0xb6, 0x00,
+ 0x04, 0x00, 0x73, 0x70, 0x72, 0x69, 0x6e, 0x67,
+ 0x00, 0x49, 0x27, 0x76, 0x65, 0x20, 0x73, 0x65,
+ 0x65, 0x6e, 0x20, 0x62, 0x65, 0x74, 0x74, 0x65,
+ 0x72, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x73,
+ 0x20, 0x74, 0x6f, 0x20, 0x73, 0x69, 0x74, 0x20,
+ 0x6f, 0x6e, 0x2e, 0x00, 0x00, 0xda, 0x76, 0xf3,
+ 0x76, 0x0c, 0x77, 0x25, 0x77, 0x56, 0x77, 0x6f,
+ 0x77, 0xb1, 0x77, 0x00, 0x00, 0x01, 0x5c, 0x00,
+ 0xb4, 0x00, 0x92, 0x00, 0xc7, 0x00, 0x80, 0x00,
+ 0xb0, 0x00, 0x74, 0x00, 0xc7, 0x00, 0x03, 0x01,
+ 0x70, 0x61, 0x74, 0x68, 0x00, 0x01, 0x02, 0x00,
+ 0x00, 0x9c, 0x00, 0x2d, 0x00, 0xb6, 0x00, 0x23,
+ 0x00, 0xae, 0x00, 0x00, 0x00, 0xae, 0x00, 0x04,
+ 0x01, 0x70, 0x61, 0x74, 0x68, 0x00, 0x01, 0x03,
+ 0x23, 0x01, 0x00, 0x00, 0x3f, 0x01, 0x82, 0x00,
+ 0x2c, 0x01, 0x87, 0x00, 0x2c, 0x01, 0x87, 0x00,
+ 0x01, 0x01, 0x70, 0x61, 0x74, 0x68, 0x00, 0x01,
+ 0x04, 0x0b, 0x00, 0x47, 0x00, 0x42, 0x00, 0x9b,
+ 0x00, 0x28, 0x00, 0x9d, 0x00, 0x28, 0x00, 0x9d,
+ 0x00, 0x01, 0x01, 0x63, 0x61, 0x6e, 0x74, 0x65,
+ 0x65, 0x6e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x20,
+ 0x64, 0x6f, 0x6f, 0x72, 0x00, 0x4e, 0x69, 0x63,
+ 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x00,
+ 0x00, 0x05, 0x8c, 0x00, 0x47, 0x00, 0xbf, 0x00,
+ 0x9b, 0x00, 0xa6, 0x00, 0x9e, 0x00, 0xa6, 0x00,
+ 0x9e, 0x00, 0x01, 0x01, 0x64, 0x6f, 0x6f, 0x72,
+ 0x00, 0x01, 0x06, 0x04, 0x01, 0x35, 0x00, 0x22,
+ 0x01, 0x94, 0x00, 0x22, 0x01, 0x8f, 0x00, 0x14,
+ 0x01, 0x8f, 0x00, 0x04, 0x01, 0x6a, 0x61, 0x69,
+ 0x6c, 0x20, 0x64, 0x6f, 0x6f, 0x72, 0x00, 0x4e,
+ 0x6f, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x27,
+ 0x73, 0x20, 0x77, 0x68, 0x61, 0x74, 0x00, 0x49,
+ 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x20,
+ 0x67, 0x6f, 0x6f, 0x64, 0x00, 0x64, 0x6f, 0x6f,
+ 0x72, 0x2e, 0x00, 0x00, 0x07, 0x4b, 0x00, 0x65,
+ 0x00, 0x65, 0x00, 0xa0, 0x00, 0x6d, 0x00, 0xa1,
+ 0x00, 0x6d, 0x00, 0xa1, 0x00, 0x04, 0x01, 0x74,
+ 0x72, 0x61, 0x73, 0x68, 0x20, 0x63, 0x61, 0x6e,
+ 0x00, 0x49, 0x74, 0x20, 0x73, 0x74, 0x69, 0x6e,
+ 0x6b, 0x73, 0x2e, 0x00, 0x00, 0xf0, 0x77, 0x2c,
+ 0x78, 0x4f, 0x78, 0x96, 0x78, 0xcd, 0x78, 0x03,
+ 0x79, 0x3e, 0x79, 0x68, 0x79, 0x86, 0x79, 0xa1,
+ 0x79, 0x00, 0x00, 0x01, 0x6b, 0x00, 0x9c, 0x00,
+ 0x84, 0x00, 0xa9, 0x00, 0x91, 0x00, 0xb3, 0x00,
+ 0x91, 0x00, 0xb3, 0x00, 0x04, 0x01, 0x73, 0x70,
+ 0x72, 0x69, 0x6e, 0x67, 0x00, 0x59, 0x65, 0x61,
+ 0x68, 0x2c, 0x20, 0x49, 0x20, 0x64, 0x65, 0x66,
+ 0x69, 0x6e, 0x65, 0x74, 0x65, 0x6c, 0x79, 0x20,
+ 0x67, 0x6f, 0x74, 0x74, 0x61, 0x20, 0x73, 0x70,
+ 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x00, 0x00, 0x02,
+ 0x1f, 0x00, 0x9c, 0x00, 0x90, 0x00, 0xbb, 0x00,
+ 0x50, 0x00, 0xc0, 0x00, 0x50, 0x00, 0xc0, 0x00,
+ 0x01, 0x01, 0x62, 0x65, 0x64, 0x00, 0x4c, 0x6f,
+ 0x6f, 0x6b, 0x73, 0x20, 0x62, 0x61, 0x64, 0x2e,
+ 0x00, 0x00, 0x03, 0x1e, 0x01, 0x71, 0x00, 0x32,
+ 0x01, 0x7e, 0x00, 0x09, 0x01, 0xb4, 0x00, 0x09,
+ 0x01, 0xb4, 0x00, 0x02, 0x01, 0x63, 0x72, 0x61,
+ 0x74, 0x65, 0x73, 0x00, 0x54, 0x68, 0x65, 0x20,
+ 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x20, 0x6c, 0x6f,
+ 0x6f, 0x6b, 0x73, 0x20, 0x62, 0x65, 0x74, 0x74,
+ 0x65, 0x72, 0x00, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6f, 0x74, 0x68, 0x65,
+ 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2e, 0x00,
+ 0x00, 0x04, 0x1b, 0x01, 0x87, 0x00, 0x2d, 0x01,
+ 0x92, 0x00, 0x09, 0x01, 0xb4, 0x00, 0x09, 0x01,
+ 0xb4, 0x00, 0x02, 0x00, 0x62, 0x6f, 0x77, 0x6c,
+ 0x00, 0x49, 0x74, 0x27, 0x73, 0x20, 0x6d, 0x61,
+ 0x64, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c,
+ 0x75, 0x6d, 0x69, 0x6e, 0x69, 0x75, 0x6d, 0x2e,
+ 0x00, 0x00, 0x62, 0x6f, 0x64, 0x79, 0x00, 0xff,
+ 0x05, 0x0a, 0x01, 0xaa, 0x00, 0x20, 0x01, 0xbe,
+ 0x00, 0x0a, 0x01, 0xbd, 0x00, 0x0a, 0x01, 0xbd,
+ 0x00, 0x02, 0x00, 0x6c, 0x69, 0x76, 0x65, 0x20,
+ 0x63, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x54, 0x68,
+ 0x65, 0x20, 0x77, 0x69, 0x72, 0x65, 0x73, 0x20,
+ 0x61, 0x72, 0x65, 0x20, 0x65, 0x78, 0x70, 0x6f,
+ 0x73, 0x65, 0x64, 0x21, 0x00, 0x00, 0x06, 0x9b,
+ 0x00, 0x5a, 0x00, 0xa4, 0x00, 0x6b, 0x00, 0x9f,
+ 0x00, 0xc2, 0x00, 0x9f, 0x00, 0xc2, 0x00, 0x01,
+ 0x01, 0x62, 0x75, 0x6c, 0x62, 0x00, 0x49, 0x74,
+ 0x27, 0x73, 0x20, 0x6e, 0x61, 0x6b, 0x65, 0x64,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x27,
+ 0x73, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2e, 0x00,
+ 0x00, 0x07, 0x15, 0x01, 0x62, 0x00, 0x35, 0x01,
+ 0xbd, 0x00, 0x09, 0x01, 0xb4, 0x00, 0x09, 0x01,
+ 0xb4, 0x00, 0x02, 0x01, 0x64, 0x6f, 0x6f, 0x72,
+ 0x00, 0x48, 0x65, 0x61, 0x76, 0x79, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64,
+ 0x2e, 0x00, 0x00, 0x08, 0xfa, 0x00, 0x93, 0x00,
+ 0x0e, 0x01, 0xad, 0x00, 0xf2, 0x00, 0xad, 0x00,
+ 0xf2, 0x00, 0xad, 0x00, 0x02, 0x01, 0x74, 0x72,
+ 0x61, 0x73, 0x68, 0x20, 0x63, 0x61, 0x6e, 0x00,
+ 0x01, 0x09, 0x38, 0x01, 0x8a, 0x00, 0x3f, 0x01,
+ 0x91, 0x00, 0x32, 0x01, 0xc4, 0x00, 0x32, 0x01,
+ 0xc4, 0x00, 0x02, 0x01, 0x73, 0x77, 0x69, 0x74,
+ 0x63, 0x68, 0x00, 0x01, 0x0a, 0x38, 0x00, 0x7a,
+ 0x00, 0xd0, 0x00, 0x9a, 0x00, 0x99, 0x00, 0xb2,
+ 0x00, 0x99, 0x00, 0xb2, 0x00, 0x01, 0x01, 0x67,
+ 0x72, 0x61, 0x66, 0x66, 0x69, 0x74, 0x69, 0x00,
+ 0x01, 0xd8, 0x79, 0x08, 0x7a, 0x21, 0x7a, 0x61,
+ 0x7a, 0x82, 0x7a, 0xbb, 0x7a, 0xf2, 0x7a, 0x1a,
+ 0x7b, 0x94, 0x7b, 0xd1, 0x7b, 0xed, 0x7b, 0x17,
+ 0x7c, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0xc3, 0x00,
+ 0x82, 0x00, 0xc3, 0x00, 0x01, 0x01, 0x63, 0x61,
+ 0x70, 0x74, 0x61, 0x69, 0x6e, 0x00, 0x48, 0x65,
+ 0x27, 0x73, 0x20, 0x73, 0x69, 0x74, 0x74, 0x69,
+ 0x6e, 0x67, 0x20, 0x74, 0x69, 0x67, 0x68, 0x74,
+ 0x2e, 0x00, 0x00, 0x02, 0x00, 0x00, 0x50, 0x00,
+ 0x23, 0x00, 0xbc, 0x00, 0x32, 0x00, 0xb8, 0x00,
+ 0x13, 0x00, 0xb8, 0x00, 0x04, 0x01, 0x64, 0x6f,
+ 0x6f, 0x72, 0x00, 0x01, 0x03, 0x2c, 0x00, 0x61,
+ 0x00, 0x4e, 0x00, 0xa4, 0x00, 0x40, 0x00, 0xa6,
+ 0x00, 0x40, 0x00, 0xa6, 0x00, 0x01, 0x01, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x00, 0x49, 0x74,
+ 0x27, 0x73, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65,
+ 0x64, 0x2e, 0x20, 0x4e, 0x6f, 0x74, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x00, 0x49, 0x27, 0x6d, 0x20,
+ 0x73, 0x75, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65,
+ 0x64, 0x2e, 0x00, 0x00, 0x04, 0x6b, 0x00, 0x51,
+ 0x00, 0xcd, 0x00, 0x8c, 0x00, 0x9e, 0x00, 0xa8,
+ 0x00, 0x9e, 0x00, 0xa8, 0x00, 0x01, 0x01, 0x6d,
+ 0x61, 0x70, 0x00, 0x50, 0x69, 0x63, 0x61, 0x73,
+ 0x73, 0x6f, 0x3f, 0x00, 0x00, 0x05, 0x8c, 0x00,
+ 0x94, 0x00, 0xd6, 0x00, 0x9e, 0x00, 0xa4, 0x00,
+ 0xc6, 0x00, 0xa4, 0x00, 0xc6, 0x00, 0x01, 0x01,
+ 0x64, 0x65, 0x73, 0x6b, 0x00, 0x54, 0x68, 0x61,
+ 0x74, 0x27, 0x73, 0x20, 0x6a, 0x75, 0x73, 0x74,
+ 0x20, 0x61, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x20,
+ 0x6f, 0x66, 0x20, 0x6f, 0x6c, 0x64, 0x20, 0x6a,
+ 0x75, 0x6e, 0x6b, 0x2e, 0x00, 0x00, 0x06, 0xee,
+ 0x00, 0x83, 0x00, 0x3f, 0x01, 0xc7, 0x00, 0xf1,
+ 0x00, 0xb5, 0x00, 0xf1, 0x00, 0xb5, 0x00, 0x02,
+ 0x01, 0x62, 0x65, 0x64, 0x00, 0x54, 0x68, 0x61,
+ 0x74, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x6e, 0x27,
+ 0x74, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x20, 0x63,
+ 0x6f, 0x6d, 0x66, 0x6f, 0x72, 0x74, 0x61, 0x62,
+ 0x6c, 0x65, 0x2e, 0x00, 0x00, 0x07, 0xbf, 0x00,
+ 0xa2, 0x00, 0xd9, 0x00, 0xb9, 0x00, 0xcc, 0x00,
+ 0xc2, 0x00, 0xcc, 0x00, 0xc2, 0x00, 0x01, 0x01,
+ 0x64, 0x72, 0x61, 0x77, 0x65, 0x72, 0x00, 0x49,
+ 0x74, 0x27, 0x73, 0x20, 0x63, 0x6c, 0x6f, 0x73,
+ 0x65, 0x64, 0x21, 0x00, 0x00, 0x08, 0xd5, 0x00,
+ 0x5d, 0x00, 0xe8, 0x00, 0x8a, 0x00, 0xf1, 0x00,
+ 0xb5, 0x00, 0xf1, 0x00, 0xb5, 0x00, 0x01, 0x01,
+ 0x73, 0x61, 0x62, 0x72, 0x65, 0x73, 0x00, 0x4d,
+ 0x79, 0x20, 0x67, 0x72, 0x61, 0x6e, 0x64, 0x70,
+ 0x61, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6f, 0x6e,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x6f,
+ 0x73, 0x65, 0x20, 0x6f, 0x6e, 0x63, 0x65, 0x2e,
+ 0x00, 0x49, 0x20, 0x65, 0x78, 0x63, 0x68, 0x61,
+ 0x6e, 0x67, 0x65, 0x64, 0x20, 0x69, 0x74, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x6a, 0x6f,
+ 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x2e, 0x00,
+ 0x47, 0x72, 0x61, 0x6e, 0x64, 0x70, 0x61, 0x20,
+ 0x64, 0x69, 0x64, 0x6e, 0x27, 0x74, 0x20, 0x6c,
+ 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x69, 0x64, 0x65, 0x61, 0x2e, 0x00, 0x00, 0x09,
+ 0xef, 0x00, 0x5e, 0x00, 0x15, 0x01, 0x7a, 0x00,
+ 0xf1, 0x00, 0xb5, 0x00, 0xf1, 0x00, 0xb5, 0x00,
+ 0x01, 0x01, 0x67, 0x75, 0x6e, 0x73, 0x00, 0x57,
+ 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x70, 0x69,
+ 0x74, 0x79, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x61, 0x72, 0x65, 0x20, 0x6f, 0x6e, 0x6c, 0x79,
+ 0x00, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2e,
+ 0x2e, 0x2e, 0x00, 0x00, 0x0a, 0x2d, 0x00, 0x27,
+ 0x00, 0x53, 0x00, 0x56, 0x00, 0x32, 0x00, 0xb5,
+ 0x00, 0x32, 0x00, 0xb5, 0x00, 0x01, 0x01, 0x70,
+ 0x69, 0x63, 0x74, 0x75, 0x72, 0x65, 0x00, 0x01,
+ 0x0b, 0xde, 0x00, 0x2b, 0x00, 0x1d, 0x01, 0x53,
+ 0x00, 0xf1, 0x00, 0xb5, 0x00, 0xf1, 0x00, 0xb5,
+ 0x00, 0x01, 0x01, 0x70, 0x69, 0x63, 0x74, 0x75,
+ 0x72, 0x65, 0x00, 0x4e, 0x69, 0x63, 0x65, 0x20,
+ 0x63, 0x68, 0x6f, 0x70, 0x70, 0x65, 0x72, 0x2e,
+ 0x00, 0x00, 0x0c, 0x7b, 0x00, 0xac, 0x00, 0x89,
+ 0x00, 0xbb, 0x00, 0x81, 0x00, 0xbf, 0x00, 0x81,
+ 0x00, 0xbf, 0x00, 0x01, 0x00, 0x20, 0x53, 0x77,
+ 0x69, 0x73, 0x73, 0x20, 0x41, 0x72, 0x6d, 0x79,
+ 0x20, 0x6b, 0x6e, 0x69, 0x66, 0x65, 0x00, 0x54,
+ 0x68, 0x61, 0x74, 0x27, 0x73, 0x20, 0x6d, 0x6f,
+ 0x72, 0x65, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20,
+ 0x69, 0x74, 0x2e, 0x00, 0x00, 0x66, 0x7c, 0xa8,
+ 0x7c, 0xe0, 0x7c, 0xf9, 0x7c, 0x34, 0x7d, 0x9b,
+ 0x7d, 0xf7, 0x7d, 0x3a, 0x7e, 0xba, 0x7e, 0x00,
+ 0x00, 0x01, 0xbb, 0x00, 0x63, 0x00, 0xc4, 0x00,
+ 0x6b, 0x00, 0xc0, 0x00, 0x98, 0x00, 0xc0, 0x00,
+ 0x98, 0x00, 0x01, 0x00, 0x6d, 0x75, 0x67, 0x00,
+ 0x54, 0x68, 0x61, 0x74, 0x27, 0x73, 0x20, 0x73,
+ 0x75, 0x72, 0x70, 0x72, 0x69, 0x73, 0x69, 0x6e,
+ 0x67, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x27, 0x73, 0x20, 0x74,
+ 0x65, 0x61, 0x00, 0x69, 0x6e, 0x20, 0x69, 0x74,
+ 0x2e, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x98, 0x00,
+ 0xb1, 0x00, 0x98, 0x00, 0x01, 0x01, 0x62, 0x61,
+ 0x72, 0x6d, 0x61, 0x6e, 0x00, 0x57, 0x68, 0x61,
+ 0x74, 0x20, 0x61, 0x20, 0x68, 0x61, 0x72, 0x64,
+ 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67,
+ 0x20, 0x63, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x6e,
+ 0x2e, 0x00, 0x00, 0x03, 0x5e, 0x00, 0xb6, 0x00,
+ 0xce, 0x00, 0xc7, 0x00, 0x9e, 0x00, 0xb8, 0x00,
+ 0x9b, 0x00, 0xc7, 0x00, 0x03, 0x01, 0x65, 0x78,
+ 0x69, 0x74, 0x00, 0x01, 0x04, 0x10, 0x00, 0x34,
+ 0x00, 0x26, 0x00, 0x92, 0x00, 0x28, 0x00, 0x98,
+ 0x00, 0x28, 0x00, 0x98, 0x00, 0x01, 0x01, 0x64,
+ 0x6f, 0x6f, 0x72, 0x00, 0x54, 0x68, 0x69, 0x73,
+ 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x6c, 0x65,
+ 0x61, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20,
+ 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x00, 0x00, 0x05,
+ 0x34, 0x00, 0x2b, 0x00, 0x59, 0x00, 0x48, 0x00,
+ 0x4d, 0x00, 0x98, 0x00, 0x4d, 0x00, 0x98, 0x00,
+ 0x01, 0x01, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x00,
+ 0x54, 0x68, 0x65, 0x20, 0x72, 0x61, 0x64, 0x69,
+ 0x6f, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x73, 0x20,
+ 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x72,
+ 0x61, 0x64, 0x69, 0x6f, 0x2c, 0x20, 0x62, 0x75,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x65,
+ 0x72, 0x69, 0x61, 0x6c, 0x00, 0x69, 0x73, 0x20,
+ 0x6d, 0x61, 0x64, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x6b, 0x69, 0x6e,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x61, 0x6e,
+ 0x67, 0x65, 0x72, 0x2e, 0x00, 0x00, 0x06, 0x0a,
+ 0x01, 0x9f, 0x00, 0x17, 0x01, 0xa6, 0x00, 0x04,
+ 0x01, 0xc2, 0x00, 0x04, 0x01, 0xc2, 0x00, 0x02,
+ 0x01, 0x63, 0x72, 0x75, 0x6d, 0x62, 0x73, 0x00,
+ 0x49, 0x74, 0x27, 0x73, 0x20, 0x64, 0x69, 0x73,
+ 0x67, 0x75, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e,
+ 0x20, 0x50, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x20,
+ 0x72, 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x73,
+ 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x00, 0x63, 0x6c,
+ 0x65, 0x61, 0x6e, 0x20, 0x75, 0x70, 0x20, 0x61,
+ 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65,
+ 0x6d, 0x73, 0x65, 0x6c, 0x76, 0x65, 0x73, 0x2e,
+ 0x00, 0x00, 0x07, 0x62, 0x00, 0x23, 0x00, 0x75,
+ 0x00, 0x35, 0x00, 0x6e, 0x00, 0x98, 0x00, 0x6e,
+ 0x00, 0x98, 0x00, 0x01, 0x01, 0x63, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x00, 0x49, 0x74, 0x20, 0x6c, 0x6f,
+ 0x6f, 0x6b, 0x73, 0x20, 0x6c, 0x69, 0x6b, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x27, 0x73,
+ 0x20, 0x61, 0x20, 0x70, 0x72, 0x6f, 0x62, 0x6c,
+ 0x65, 0x6d, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x69, 0x74, 0x2e, 0x00, 0x00, 0x08, 0x7e, 0x00,
+ 0x22, 0x00, 0x00, 0x01, 0x69, 0x00, 0xc8, 0x00,
+ 0x98, 0x00, 0xc8, 0x00, 0x98, 0x00, 0x01, 0x01,
+ 0x73, 0x68, 0x65, 0x6c, 0x76, 0x65, 0x73, 0x00,
+ 0x49, 0x20, 0x77, 0x6f, 0x6e, 0x64, 0x65, 0x72,
+ 0x20, 0x77, 0x68, 0x79, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x27, 0x73, 0x20, 0x73, 0x75, 0x63,
+ 0x68, 0x20, 0x61, 0x20, 0x6c, 0x61, 0x72, 0x67,
+ 0x65, 0x20, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65,
+ 0x00, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x63, 0x6f,
+ 0x68, 0x6f, 0x6c, 0x20, 0x61, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x72, 0x61, 0x69, 0x6e,
+ 0x69, 0x6e, 0x67, 0x20, 0x63, 0x61, 0x6d, 0x70,
+ 0x2e, 0x00, 0x54, 0x6f, 0x20, 0x6b, 0x65, 0x65,
+ 0x70, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72,
+ 0x6f, 0x6f, 0x70, 0x73, 0x20, 0x68, 0x61, 0x70,
+ 0x70, 0x79, 0x3f, 0x00, 0x00, 0x09, 0x41, 0x00,
+ 0x59, 0x00, 0x5b, 0x00, 0x69, 0x00, 0x4d, 0x00,
+ 0x98, 0x00, 0x4d, 0x00, 0x98, 0x00, 0x01, 0x01,
+ 0x63, 0x61, 0x73, 0x68, 0x20, 0x72, 0x65, 0x67,
+ 0x69, 0x73, 0x74, 0x65, 0x72, 0x00, 0x49, 0x20,
+ 0x6c, 0x6f, 0x76, 0x65, 0x20, 0x69, 0x74, 0x2e,
+ 0x00, 0x00, 0xf7, 0x7e, 0x29, 0x7f, 0x42, 0x7f,
+ 0x8b, 0x7f, 0xc4, 0x7f, 0xfc, 0x7f, 0x1d, 0x80,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x32, 0x00, 0xb4, 0x00, 0x32,
+ 0x00, 0xb4, 0x00, 0x01, 0x01, 0x62, 0x6c, 0x69,
+ 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x6f,
+ 0x6c, 0x65, 0x00, 0x54, 0x68, 0x61, 0x74, 0x27,
+ 0x73, 0x20, 0x77, 0x65, 0x69, 0x72, 0x64, 0x2e,
+ 0x2e, 0x2e, 0x00, 0x00, 0x02, 0x0c, 0x01, 0x55,
+ 0x00, 0x29, 0x01, 0xaa, 0x00, 0xf0, 0x00, 0xb6,
+ 0x00, 0xf0, 0x00, 0xb6, 0x00, 0x02, 0x01, 0x64,
+ 0x6f, 0x6f, 0x72, 0x00, 0x01, 0x03, 0x04, 0x00,
+ 0x6c, 0x00, 0x5b, 0x00, 0xb2, 0x00, 0x32, 0x00,
+ 0xb4, 0x00, 0x32, 0x00, 0xb4, 0x00, 0x01, 0x01,
+ 0x62, 0x61, 0x72, 0x72, 0x65, 0x6c, 0x73, 0x00,
+ 0x49, 0x74, 0x27, 0x73, 0x20, 0x67, 0x6f, 0x6f,
+ 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6b, 0x6e, 0x6f,
+ 0x77, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x61, 0x72,
+ 0x6d, 0x79, 0x20, 0x69, 0x73, 0x20, 0x77, 0x65,
+ 0x6c, 0x6c, 0x20, 0x65, 0x71, 0x75, 0x69, 0x70,
+ 0x70, 0x65, 0x64, 0x2e, 0x00, 0x00, 0x04, 0x5a,
+ 0x00, 0x5f, 0x00, 0x78, 0x00, 0xa8, 0x00, 0x70,
+ 0x00, 0xad, 0x00, 0x70, 0x00, 0xad, 0x00, 0x01,
+ 0x01, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x00,
+ 0x49, 0x74, 0x27, 0x73, 0x20, 0x61, 0x20, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x20, 0x6b, 0x69,
+ 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x65, 0x72, 0x2e, 0x00, 0x00, 0x05,
+ 0x96, 0x00, 0x6b, 0x00, 0xd6, 0x00, 0xa4, 0x00,
+ 0xb7, 0x00, 0xb2, 0x00, 0xb7, 0x00, 0xb2, 0x00,
+ 0x01, 0x01, 0x6c, 0x6f, 0x74, 0x73, 0x20, 0x6f,
+ 0x66, 0x20, 0x64, 0x72, 0x61, 0x77, 0x65, 0x72,
+ 0x73, 0x00, 0x49, 0x20, 0x68, 0x61, 0x74, 0x65,
+ 0x20, 0x62, 0x75, 0x72, 0x65, 0x61, 0x75, 0x63,
+ 0x72, 0x61, 0x63, 0x79, 0x2e, 0x00, 0x00, 0x06,
+ 0x7e, 0x00, 0x8f, 0x00, 0x97, 0x00, 0xaa, 0x00,
+ 0x8d, 0x00, 0xb1, 0x00, 0x8d, 0x00, 0xb1, 0x00,
+ 0x01, 0x01, 0x62, 0x6f, 0x78, 0x65, 0x73, 0x00,
+ 0x27, 0x50, 0x65, 0x70, 0x61, 0x27, 0x00, 0x00,
+ 0x07, 0xd7, 0x00, 0x81, 0x00, 0xea, 0x00, 0xaa,
+ 0x00, 0xe0, 0x00, 0xb6, 0x00, 0xe0, 0x00, 0xb6,
+ 0x00, 0x01, 0x01, 0x62, 0x6f, 0x78, 0x65, 0x73,
+ 0x00, 0x27, 0x53, 0x61, 0x6c, 0x74, 0x27, 0x00,
+ 0x00, 0x48, 0x80, 0x87, 0x80, 0xd1, 0x80, 0x01,
+ 0x81, 0x00, 0x00, 0x01, 0x7e, 0x00, 0x5f, 0x00,
+ 0x86, 0x00, 0x69, 0x00, 0x8b, 0x00, 0x9c, 0x00,
+ 0x84, 0x00, 0x95, 0x00, 0x01, 0x00, 0x67, 0x72,
+ 0x65, 0x6e, 0x61, 0x64, 0x65, 0x00, 0x57, 0x6f,
+ 0x77, 0x21, 0x20, 0x49, 0x20, 0x61, 0x6c, 0x77,
+ 0x61, 0x79, 0x73, 0x20, 0x77, 0x61, 0x6e, 0x74,
+ 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x2e,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x8b, 0x00, 0x9c, 0x00, 0x8b,
+ 0x00, 0x9c, 0x00, 0x01, 0x01, 0x67, 0x75, 0x61,
+ 0x72, 0x64, 0x00, 0x49, 0x20, 0x64, 0x6f, 0x6e,
+ 0x27, 0x74, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x6b,
+ 0x20, 0x68, 0x65, 0x27, 0x73, 0x20, 0x6d, 0x61,
+ 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x69,
+ 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f,
+ 0x6e, 0x2e, 0x00, 0x00, 0x03, 0x00, 0x00, 0x6f,
+ 0x00, 0x54, 0x00, 0xa2, 0x00, 0x53, 0x00, 0x95,
+ 0x00, 0x53, 0x00, 0x95, 0x00, 0x04, 0x01, 0x77,
+ 0x61, 0x79, 0x20, 0x6f, 0x75, 0x74, 0x00, 0x48,
+ 0x6f, 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x77, 0x65,
+ 0x65, 0x74, 0x20, 0x68, 0x6f, 0x6d, 0x65, 0x2e,
+ 0x2e, 0x2e, 0x00, 0x00, 0x04, 0x10, 0x01, 0x95,
+ 0x00, 0x3f, 0x01, 0xc7, 0x00, 0x0d, 0x01, 0xaf,
+ 0x00, 0x3f, 0x01, 0xb7, 0x00, 0x02, 0x01, 0x70,
+ 0x61, 0x74, 0x68, 0x00, 0x01, 0x3a, 0x81, 0x79,
+ 0x81, 0xa3, 0x81, 0xc0, 0x81, 0xdd, 0x81, 0x11,
+ 0x82, 0x3d, 0x82, 0x7f, 0x82, 0xa4, 0x82, 0xcc,
+ 0x82, 0x1a, 0x83, 0x3c, 0x83, 0x64, 0x83, 0xb8,
+ 0x83, 0xea, 0x83, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x00,
+ 0xa3, 0x00, 0x8a, 0x00, 0xa3, 0x00, 0x02, 0x01,
+ 0x67, 0x75, 0x61, 0x72, 0x64, 0x00, 0x48, 0x65,
+ 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x73, 0x20, 0x6c,
+ 0x69, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x70, 0x65,
+ 0x61, 0x73, 0x61, 0x6e, 0x74, 0x20, 0x69, 0x6e,
+ 0x00, 0x64, 0x69, 0x73, 0x67, 0x75, 0x69, 0x73,
+ 0x65, 0x2e, 0x00, 0x00, 0x02, 0x70, 0x00, 0xa0,
+ 0x00, 0x7b, 0x00, 0xa8, 0x00, 0x68, 0x00, 0xab,
+ 0x00, 0x68, 0x00, 0xab, 0x00, 0x02, 0x00, 0x62,
+ 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x00, 0x49, 0x74,
+ 0x27, 0x73, 0x20, 0x77, 0x68, 0x69, 0x73, 0x6b,
+ 0x79, 0x21, 0x2e, 0x2e, 0x00, 0x00, 0x03, 0xd2,
+ 0x00, 0x77, 0x00, 0xf6, 0x00, 0x98, 0x00, 0x8a,
+ 0x00, 0xa3, 0x00, 0x8a, 0x00, 0xa3, 0x00, 0x02,
+ 0x01, 0x67, 0x61, 0x72, 0x67, 0x6f, 0x79, 0x6c,
+ 0x65, 0x00, 0x01, 0x04, 0x09, 0x01, 0x80, 0x00,
+ 0x2f, 0x01, 0xad, 0x00, 0x8a, 0x00, 0xa3, 0x00,
+ 0x8a, 0x00, 0xa3, 0x00, 0x02, 0x01, 0x67, 0x61,
+ 0x72, 0x67, 0x6f, 0x79, 0x6c, 0x65, 0x00, 0x01,
+ 0x05, 0x12, 0x01, 0x39, 0x00, 0x23, 0x01, 0x48,
+ 0x00, 0x8a, 0x00, 0xa3, 0x00, 0x8a, 0x00, 0xa3,
+ 0x00, 0x02, 0x01, 0x73, 0x63, 0x75, 0x6c, 0x70,
+ 0x74, 0x75, 0x72, 0x65, 0x00, 0x52, 0x65, 0x61,
+ 0x6c, 0x6c, 0x79, 0x20, 0x73, 0x6f, 0x70, 0x68,
+ 0x69, 0x73, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65,
+ 0x64, 0x21, 0x00, 0x00, 0x06, 0xfc, 0x00, 0x33,
+ 0x00, 0x32, 0x01, 0xa1, 0x00, 0x8a, 0x00, 0xa3,
+ 0x00, 0x8a, 0x00, 0xa3, 0x00, 0x02, 0x01, 0x64,
+ 0x6f, 0x6f, 0x72, 0x00, 0x53, 0x6f, 0x6c, 0x69,
+ 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61,
+ 0x73, 0x73, 0x69, 0x76, 0x65, 0x2e, 0x00, 0x00,
+ 0x07, 0xe5, 0x00, 0x00, 0x00, 0x3f, 0x01, 0x98,
+ 0x00, 0x8a, 0x00, 0xa3, 0x00, 0x8a, 0x00, 0xa3,
+ 0x00, 0x02, 0x01, 0x6d, 0x61, 0x6e, 0x73, 0x69,
+ 0x6f, 0x6e, 0x20, 0x77, 0x61, 0x6c, 0x6c, 0x00,
+ 0x49, 0x74, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20,
+ 0x62, 0x65, 0x20, 0x33, 0x20, 0x6b, 0x69, 0x6c,
+ 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20,
+ 0x74, 0x68, 0x69, 0x63, 0x6b, 0x2e, 0x2e, 0x2e,
+ 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xb5, 0x00, 0xb0, 0x00, 0xb5,
+ 0x00, 0xb0, 0x00, 0x01, 0x00, 0x4a, 0x6f, 0x68,
+ 0x6e, 0x20, 0x4e, 0x6f, 0x74, 0x79, 0x00, 0x46,
+ 0x61, 0x74, 0x73, 0x6f, 0x2e, 0x00, 0x00, 0x09,
+ 0x9c, 0x00, 0xae, 0x00, 0x3f, 0x01, 0xc7, 0x00,
+ 0x8a, 0x00, 0xa3, 0x00, 0x3f, 0x01, 0xc6, 0x00,
+ 0x02, 0x01, 0x70, 0x61, 0x74, 0x68, 0x20, 0x61,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x6d, 0x61,
+ 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x01, 0x0a,
+ 0x00, 0x00, 0x73, 0x00, 0x46, 0x00, 0x98, 0x00,
+ 0x3c, 0x00, 0xab, 0x00, 0x00, 0x00, 0x7c, 0x00,
+ 0x01, 0x01, 0x70, 0x61, 0x74, 0x68, 0x20, 0x74,
+ 0x6f, 0x20, 0x6d, 0x65, 0x61, 0x64, 0x6f, 0x77,
+ 0x00, 0x49, 0x74, 0x20, 0x6c, 0x65, 0x61, 0x64,
+ 0x73, 0x20, 0x69, 0x6e, 0x73, 0x69, 0x64, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x72,
+ 0x6b, 0x20, 0x61, 0x6e, 0x64, 0x00, 0x73, 0x63,
+ 0x61, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x65,
+ 0x73, 0x74, 0x2e, 0x00, 0x00, 0x0b, 0x00, 0x00,
+ 0xa1, 0x00, 0x39, 0x00, 0xbe, 0x00, 0x3c, 0x00,
+ 0xab, 0x00, 0x00, 0x00, 0xab, 0x00, 0x04, 0x01,
+ 0x70, 0x61, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20,
+ 0x73, 0x68, 0x6f, 0x72, 0x65, 0x00, 0x01, 0x0c,
+ 0x8c, 0x00, 0x68, 0x00, 0xe4, 0x00, 0x98, 0x00,
+ 0x8a, 0x00, 0xa3, 0x00, 0xe4, 0x00, 0x6d, 0x00,
+ 0x02, 0x01, 0x70, 0x61, 0x74, 0x68, 0x20, 0x61,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x6d, 0x61,
+ 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x01, 0x0d,
+ 0xbf, 0x00, 0xa6, 0x00, 0xc8, 0x00, 0xae, 0x00,
+ 0x8a, 0x00, 0xa3, 0x00, 0xb5, 0x00, 0xb0, 0x00,
+ 0x02, 0x01, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65,
+ 0x72, 0x00, 0x49, 0x74, 0x27, 0x73, 0x20, 0x61,
+ 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x70, 0x68,
+ 0x61, 0x6e, 0x65, 0x20, 0x77, 0x72, 0x61, 0x70,
+ 0x70, 0x65, 0x72, 0x20, 0x66, 0x72, 0x6f, 0x6d,
+ 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x63, 0x61,
+ 0x6e, 0x64, 0x79, 0x00, 0x6f, 0x72, 0x20, 0x73,
+ 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x69, 0x6e, 0x67,
+ 0x2e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00,
+ 0xe4, 0x00, 0x98, 0x00, 0x3c, 0x00, 0xab, 0x00,
+ 0x3c, 0x00, 0xab, 0x00, 0x01, 0x01, 0x66, 0x6f,
+ 0x72, 0x65, 0x73, 0x74, 0x00, 0x49, 0x74, 0x20,
+ 0x67, 0x69, 0x76, 0x65, 0x73, 0x20, 0x6d, 0x65,
+ 0x20, 0x74, 0x68, 0x72, 0x69, 0x6c, 0x6c, 0x73,
+ 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x0f, 0x78, 0x00,
+ 0x9a, 0x00, 0x85, 0x00, 0xa0, 0x00, 0x70, 0x00,
+ 0xa3, 0x00, 0x70, 0x00, 0xa3, 0x00, 0x02, 0x00,
+ 0x62, 0x61, 0x6e, 0x6b, 0x6e, 0x6f, 0x74, 0x65,
+ 0x00, 0x49, 0x27, 0x6d, 0x20, 0x72, 0x65, 0x61,
+ 0x6c, 0x6c, 0x79, 0x20, 0x70, 0x72, 0x6f, 0x75,
+ 0x64, 0x20, 0x49, 0x20, 0x64, 0x69, 0x64, 0x6e,
+ 0x27, 0x74, 0x20, 0x54, 0x41, 0x4b, 0x45, 0x20,
+ 0x54, 0x48, 0x41, 0x54, 0x2e, 0x00, 0x00, 0x40,
+ 0x84, 0x56, 0x84, 0x87, 0x84, 0xb6, 0x84, 0xf2,
+ 0x84, 0x29, 0x85, 0x66, 0x85, 0x8e, 0x85, 0xb6,
+ 0x85, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x04, 0x01, 0x74, 0x00, 0x13, 0x01,
+ 0x8a, 0x00, 0x02, 0x01, 0xbd, 0x00, 0x02, 0x01,
+ 0xbd, 0x00, 0x01, 0x01, 0x68, 0x6f, 0x6c, 0x6c,
+ 0x6f, 0x77, 0x00, 0x49, 0x74, 0x27, 0x73, 0x20,
+ 0x65, 0x6d, 0x70, 0x74, 0x79, 0x20, 0x72, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x6e, 0x6f, 0x77, 0x2e,
+ 0x00, 0x00, 0x03, 0xd0, 0x00, 0x6e, 0x00, 0xf8,
+ 0x00, 0x7e, 0x00, 0xcb, 0x00, 0xab, 0x00, 0xcb,
+ 0x00, 0xab, 0x00, 0x02, 0x01, 0x62, 0x72, 0x61,
+ 0x6e, 0x63, 0x68, 0x00, 0x49, 0x74, 0x20, 0x63,
+ 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20,
+ 0x75, 0x73, 0x65, 0x66, 0x75, 0x6c, 0x2e, 0x00,
+ 0x00, 0x04, 0xe4, 0x00, 0x3c, 0x00, 0x2d, 0x01,
+ 0xaa, 0x00, 0x02, 0x01, 0xbd, 0x00, 0xfc, 0x00,
+ 0xab, 0x00, 0x01, 0x01, 0x74, 0x72, 0x65, 0x65,
+ 0x00, 0x49, 0x74, 0x27, 0x73, 0x20, 0x68, 0x69,
+ 0x67, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61,
+ 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x61,
+ 0x6c, 0x6c, 0x21, 0x00, 0x00, 0x05, 0x0c, 0x00,
+ 0x8a, 0x00, 0x33, 0x00, 0xad, 0x00, 0x31, 0x00,
+ 0xac, 0x00, 0x31, 0x00, 0xac, 0x00, 0x04, 0x01,
+ 0x77, 0x69, 0x6c, 0x64, 0x20, 0x70, 0x6c, 0x61,
+ 0x6e, 0x74, 0x00, 0x49, 0x74, 0x27, 0x73, 0x20,
+ 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x77, 0x69, 0x6c,
+ 0x64, 0x20, 0x70, 0x6f, 0x74, 0x61, 0x74, 0x6f,
+ 0x65, 0x2e, 0x00, 0x00, 0x06, 0x00, 0x00, 0x22,
+ 0x00, 0x04, 0x01, 0xa0, 0x00, 0xa6, 0x00, 0xbd,
+ 0x00, 0xa6, 0x00, 0xbd, 0x00, 0x01, 0x01, 0x77,
+ 0x61, 0x6c, 0x6c, 0x00, 0x49, 0x74, 0x27, 0x73,
+ 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x73, 0x6f,
+ 0x6d, 0x65, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20,
+ 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x2e, 0x00,
+ 0x00, 0x07, 0x25, 0x01, 0x5c, 0x00, 0x3f, 0x01,
+ 0xaa, 0x00, 0x2a, 0x01, 0xaf, 0x00, 0x3f, 0x01,
+ 0x98, 0x00, 0x01, 0x01, 0x70, 0x61, 0x74, 0x68,
+ 0x20, 0x61, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20,
+ 0x6d, 0x61, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00,
+ 0x01, 0x08, 0x00, 0x00, 0xae, 0x00, 0x3c, 0x00,
+ 0xc7, 0x00, 0x1e, 0x00, 0xbd, 0x00, 0x00, 0x00,
+ 0xbd, 0x00, 0x04, 0x01, 0x70, 0x61, 0x74, 0x68,
+ 0x20, 0x61, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20,
+ 0x6d, 0x61, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00,
+ 0x01, 0x09, 0xd0, 0x00, 0x9c, 0x00, 0xec, 0x00,
+ 0xa8, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x00, 0x00, 0x62, 0x72, 0x61, 0x6e,
+ 0x63, 0x68, 0x00, 0x47, 0x6f, 0x74, 0x63, 0x68,
+ 0x61, 0x2e, 0x00, 0x00, 0xe9, 0x85, 0x0d, 0x86,
+ 0x42, 0x86, 0x6a, 0x86, 0xa7, 0x86, 0xcf, 0x86,
+ 0x07, 0x87, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x31, 0x00, 0x9d, 0x00, 0x12, 0x00, 0xad,
+ 0x00, 0x12, 0x00, 0xad, 0x00, 0x01, 0x01, 0x74,
+ 0x72, 0x65, 0x65, 0x00, 0x49, 0x74, 0x27, 0x73,
+ 0x20, 0x68, 0x69, 0x67, 0x68, 0x2e, 0x00, 0x00,
+ 0x02, 0xf6, 0x00, 0x7c, 0x00, 0x35, 0x01, 0xa6,
+ 0x00, 0x05, 0x01, 0xb7, 0x00, 0x05, 0x01, 0xb7,
+ 0x00, 0x01, 0x01, 0x77, 0x69, 0x6c, 0x64, 0x20,
+ 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x00, 0x4f, 0x72,
+ 0x64, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x20, 0x67,
+ 0x72, 0x65, 0x65, 0x6e, 0x20, 0x73, 0x74, 0x75,
+ 0x66, 0x66, 0x2e, 0x00, 0x00, 0x03, 0x00, 0x00,
+ 0x9e, 0x00, 0x2f, 0x00, 0xba, 0x00, 0x12, 0x00,
+ 0xad, 0x00, 0x00, 0x00, 0xac, 0x00, 0x04, 0x01,
+ 0x70, 0x61, 0x74, 0x68, 0x20, 0x61, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x6e, 0x73,
+ 0x69, 0x6f, 0x6e, 0x00, 0x01, 0x04, 0x00, 0x00,
+ 0x20, 0x00, 0x3f, 0x01, 0xa6, 0x00, 0xc5, 0x00,
+ 0xb7, 0x00, 0xc5, 0x00, 0xb7, 0x00, 0x01, 0x01,
+ 0x77, 0x61, 0x6c, 0x6c, 0x00, 0x49, 0x74, 0x27,
+ 0x73, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65,
+ 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x73,
+ 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x69, 0x6e, 0x67,
+ 0x20, 0x73, 0x6d, 0x6f, 0x6f, 0x74, 0x68, 0x2e,
+ 0x00, 0x00, 0x05, 0x06, 0x01, 0xa6, 0x00, 0x3f,
+ 0x01, 0xc7, 0x00, 0x05, 0x01, 0xb7, 0x00, 0x3f,
+ 0x01, 0xb5, 0x00, 0x02, 0x01, 0x70, 0x61, 0x74,
+ 0x68, 0x20, 0x61, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x20, 0x6d, 0x61, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
+ 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x67, 0x00, 0xc0, 0x00, 0x67,
+ 0x00, 0xc0, 0x00, 0x04, 0x01, 0x68, 0x65, 0x64,
+ 0x67, 0x65, 0x68, 0x6f, 0x67, 0x00, 0x49, 0x73,
+ 0x20, 0x68, 0x61, 0x73, 0x20, 0x61, 0x20, 0x63,
+ 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x6e, 0x20, 0x69,
+ 0x74, 0x73, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x2e,
+ 0x00, 0x00, 0x07, 0xdb, 0x00, 0xba, 0x00, 0xeb,
+ 0x00, 0xc3, 0x00, 0xd7, 0x00, 0xc3, 0x00, 0xd7,
+ 0x00, 0xc3, 0x00, 0x02, 0x01, 0x72, 0x6f, 0x63,
+ 0x6b, 0x00, 0x01, 0x2c, 0x87, 0x59, 0x87, 0x7f,
+ 0x87, 0xac, 0x87, 0xe2, 0x87, 0x00, 0x00, 0x01,
+ 0xb2, 0x00, 0x24, 0x00, 0xbe, 0x00, 0x36, 0x00,
+ 0xbc, 0x00, 0x96, 0x00, 0xbc, 0x00, 0x96, 0x00,
+ 0x01, 0x01, 0x62, 0x65, 0x65, 0x73, 0x20, 0x6e,
+ 0x65, 0x73, 0x74, 0x00, 0x48, 0x6f, 0x6e, 0x65,
+ 0x79, 0x20, 0x62, 0x61, 0x6c, 0x6c, 0x6f, 0x6f,
+ 0x6e, 0x2e, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x96,
+ 0x00, 0xbc, 0x00, 0x96, 0x00, 0x01, 0x01, 0x62,
+ 0x65, 0x65, 0x73, 0x00, 0x49, 0x20, 0x48, 0x41,
+ 0x54, 0x45, 0x20, 0x54, 0x48, 0x45, 0x4d, 0x21,
+ 0x00, 0x00, 0x03, 0x1c, 0x00, 0x5d, 0x00, 0x72,
+ 0x00, 0xc1, 0x00, 0x3f, 0x00, 0xc3, 0x00, 0x3f,
+ 0x00, 0xc3, 0x00, 0x01, 0x01, 0x62, 0x75, 0x73,
+ 0x68, 0x00, 0x4e, 0x69, 0x63, 0x65, 0x20, 0x70,
+ 0x6c, 0x61, 0x63, 0x65, 0x20, 0x74, 0x6f, 0x20,
+ 0x68, 0x69, 0x64, 0x65, 0x2e, 0x00, 0x00, 0x04,
+ 0xa6, 0x00, 0x76, 0x00, 0xe6, 0x00, 0x8d, 0x00,
+ 0xbc, 0x00, 0x96, 0x00, 0xbc, 0x00, 0x96, 0x00,
+ 0x01, 0x01, 0x76, 0x61, 0x6c, 0x76, 0x65, 0x00,
+ 0x49, 0x74, 0x27, 0x73, 0x20, 0x72, 0x75, 0x73,
+ 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68,
+ 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x20, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x2e, 0x00, 0x00, 0x05, 0xd6, 0x00,
+ 0xb4, 0x00, 0x3f, 0x01, 0xc7, 0x00, 0xdb, 0x00,
+ 0xb7, 0x00, 0x0e, 0x01, 0xc7, 0x00, 0x02, 0x01,
+ 0x70, 0x61, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20,
+ 0x6d, 0x61, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00,
+ 0x01, 0x18, 0x88, 0x6f, 0x88, 0xad, 0x88, 0xf4,
+ 0x88, 0x40, 0x89, 0x6e, 0x89, 0x92, 0x89, 0xb6,
+ 0x89, 0x00, 0x00, 0x01, 0x90, 0x00, 0x0f, 0x00,
+ 0xa3, 0x00, 0x1d, 0x00, 0x9d, 0x00, 0xb4, 0x00,
+ 0x9d, 0x00, 0xb4, 0x00, 0x01, 0x01, 0x66, 0x6c,
+ 0x6f, 0x77, 0x65, 0x72, 0x00, 0x49, 0x74, 0x27,
+ 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f,
+ 0x73, 0x74, 0x20, 0x62, 0x65, 0x61, 0x75, 0x74,
+ 0x69, 0x66, 0x75, 0x6c, 0x20, 0x66, 0x6c, 0x6f,
+ 0x77, 0x65, 0x72, 0x20, 0x49, 0x27, 0x76, 0x65,
+ 0x20, 0x73, 0x65, 0x65, 0x6e, 0x00, 0x69, 0x6e,
+ 0x20, 0x6d, 0x79, 0x20, 0x65, 0x6e, 0x74, 0x69,
+ 0x72, 0x65, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x21,
+ 0x00, 0x00, 0x02, 0x69, 0x00, 0x00, 0x00, 0xcf,
+ 0x00, 0x27, 0x00, 0x9d, 0x00, 0xb4, 0x00, 0x9d,
+ 0x00, 0xb4, 0x00, 0x01, 0x01, 0x69, 0x73, 0x6c,
+ 0x65, 0x00, 0x4e, 0x65, 0x61, 0x74, 0x20, 0x70,
+ 0x6c, 0x61, 0x63, 0x65, 0x20, 0x74, 0x6f, 0x20,
+ 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x65, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c,
+ 0x20, 0x6c, 0x69, 0x66, 0x65, 0x2e, 0x00, 0x00,
+ 0x03, 0x3c, 0x00, 0x88, 0x00, 0x7b, 0x00, 0xa7,
+ 0x00, 0x6b, 0x00, 0xa9, 0x00, 0x6b, 0x00, 0xa9,
+ 0x00, 0x04, 0x01, 0x62, 0x6f, 0x61, 0x74, 0x00,
+ 0x49, 0x20, 0x63, 0x61, 0x6e, 0x27, 0x74, 0x20,
+ 0x62, 0x65, 0x6c, 0x69, 0x65, 0x76, 0x65, 0x20,
+ 0x69, 0x74, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x61, 0x74,
+ 0x20, 0x68, 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x20,
+ 0x68, 0x6f, 0x6c, 0x65, 0x2e, 0x00, 0x00, 0x04,
+ 0xec, 0x00, 0xa4, 0x00, 0x20, 0x01, 0xc3, 0x00,
+ 0xec, 0x00, 0xb3, 0x00, 0xec, 0x00, 0xb3, 0x00,
+ 0x03, 0x01, 0x77, 0x65, 0x6c, 0x6c, 0x00, 0x49,
+ 0x20, 0x72, 0x65, 0x66, 0x75, 0x73, 0x65, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x65, 0x6c, 0x6c, 0x20,
+ 0x63, 0x68, 0x65, 0x61, 0x70, 0x20, 0x6a, 0x6f,
+ 0x6b, 0x65, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x00, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72,
+ 0x64, 0x20, 0x22, 0x77, 0x65, 0x6c, 0x6c, 0x22,
+ 0x2e, 0x00, 0x00, 0x05, 0xdd, 0x00, 0x96, 0x00,
+ 0xe8, 0x00, 0xa2, 0x00, 0xc8, 0x00, 0xb3, 0x00,
+ 0xc8, 0x00, 0xb3, 0x00, 0x02, 0x01, 0x68, 0x61,
+ 0x6e, 0x64, 0x6c, 0x65, 0x00, 0x49, 0x20, 0x63,
+ 0x61, 0x6e, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c,
+ 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x00,
+ 0x00, 0x06, 0x88, 0x00, 0xb7, 0x00, 0xa5, 0x00,
+ 0xc7, 0x00, 0x9d, 0x00, 0xb4, 0x00, 0x99, 0x00,
+ 0xc7, 0x00, 0x03, 0x01, 0x70, 0x61, 0x74, 0x68,
+ 0x20, 0x74, 0x6f, 0x20, 0x76, 0x69, 0x6c, 0x6c,
+ 0x61, 0x67, 0x65, 0x00, 0x01, 0x07, 0x25, 0x01,
+ 0x96, 0x00, 0x3f, 0x01, 0xb6, 0x00, 0x06, 0x01,
+ 0xb0, 0x00, 0x3f, 0x01, 0xa2, 0x00, 0x02, 0x01,
+ 0x70, 0x61, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20,
+ 0x6d, 0x61, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x00,
+ 0x01, 0x08, 0x00, 0x00, 0x96, 0x00, 0x20, 0x00,
+ 0xb5, 0x00, 0x1e, 0x00, 0xac, 0x00, 0x00, 0x00,
+ 0xac, 0x00, 0x04, 0x01, 0x70, 0x61, 0x74, 0x68,
+ 0x20, 0x74, 0x6f, 0x20, 0x66, 0x6f, 0x72, 0x65,
+ 0x73, 0x74, 0x00, 0x01, 0xe1, 0x89, 0x0c, 0x8a,
+ 0x3c, 0x8a, 0x00, 0x00, 0x01, 0x7d, 0x00, 0x3b,
+ 0x00, 0x8c, 0x00, 0x59, 0x00, 0x7b, 0x00, 0x5e,
+ 0x00, 0x7b, 0x00, 0x5e, 0x00, 0x02, 0x01, 0x66,
+ 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x00, 0x49, 0x74,
+ 0x27, 0x73, 0x20, 0x62, 0x65, 0x61, 0x75, 0x74,
+ 0x69, 0x66, 0x75, 0x6c, 0x21, 0x00, 0x00, 0x02,
+ 0x8d, 0x00, 0x3b, 0x00, 0x9e, 0x00, 0x57, 0x00,
+ 0xa0, 0x00, 0x5a, 0x00, 0xa0, 0x00, 0x5a, 0x00,
+ 0x04, 0x01, 0x66, 0x6c, 0x6f, 0x77, 0x65, 0x72,
+ 0x00, 0x49, 0x74, 0x20, 0x73, 0x6d, 0x65, 0x6c,
+ 0x6c, 0x73, 0x20, 0x76, 0x65, 0x72, 0x79, 0x20,
+ 0x6e, 0x69, 0x63, 0x65, 0x21, 0x00, 0x00, 0x03,
+ 0xd2, 0x00, 0x4c, 0x00, 0x38, 0x01, 0x7b, 0x00,
+ 0xec, 0x00, 0x5f, 0x00, 0xec, 0x00, 0x5f, 0x00,
+ 0x03, 0x01, 0x62, 0x6f, 0x61, 0x74, 0x00, 0x4e,
+ 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x6e,
+ 0x65, 0x77, 0x2e, 0x20, 0x4c, 0x69, 0x74, 0x65,
+ 0x72, 0x61, 0x6c, 0x6c, 0x79, 0x2e, 0x00, 0x00,
+ 0x87, 0x8a, 0xa1, 0x8a, 0xbb, 0x8a, 0xd2, 0x8a,
+ 0xe9, 0x8a, 0x05, 0x8b, 0x3c, 0x8b, 0x1f, 0x8b,
+ 0x59, 0x8b, 0x76, 0x8b, 0x93, 0x8b, 0xae, 0x8b,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x01, 0x66, 0x69, 0x73,
+ 0x68, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x66,
+ 0x69, 0x73, 0x68, 0x00, 0x00, 0x00, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x3f, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x3f, 0x00, 0x00, 0x00, 0x05, 0x21, 0x00, 0xb1,
+ 0x00, 0x2b, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x61,
+ 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x00, 0x00, 0x00,
+ 0x06, 0x29, 0x00, 0x90, 0x00, 0x99, 0x00, 0xba,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x01, 0x62, 0x6f, 0x61, 0x74, 0x00,
+ 0x00, 0x00, 0x08, 0x0f, 0x00, 0x90, 0x00, 0x2d,
+ 0x00, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x01, 0x73, 0x65, 0x61,
+ 0x77, 0x65, 0x65, 0x64, 0x00, 0x00, 0x00, 0x07,
+ 0x00, 0x00, 0x56, 0x00, 0x22, 0x00, 0x97, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x01, 0x73, 0x65, 0x61, 0x77, 0x65, 0x65,
+ 0x64, 0x00, 0x00, 0x00, 0x09, 0xce, 0x00, 0xa3,
+ 0x00, 0xfc, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x73,
+ 0x65, 0x61, 0x77, 0x65, 0x65, 0x64, 0x00, 0x00,
+ 0x00, 0x0a, 0xde, 0x00, 0x3c, 0x00, 0x08, 0x01,
+ 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x01, 0x73, 0x65, 0x61, 0x77,
+ 0x65, 0x65, 0x64, 0x00, 0x00, 0x00, 0x0b, 0x98,
+ 0x00, 0x96, 0x00, 0xbb, 0x00, 0xb5, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x01, 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x00, 0x00,
+ 0x00, 0x0c, 0x68, 0x00, 0x7a, 0x00, 0xe0, 0x00,
+ 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x01, 0x73, 0x74, 0x6f, 0x6e,
+ 0x65, 0x73, 0x00, 0x00, 0x00, 0xda, 0x8b, 0x01,
+ 0x8c, 0x39, 0x8c, 0x63, 0x8c, 0x90, 0x8c, 0xb2,
+ 0x8c, 0xd2, 0x8c, 0x00, 0x00, 0x01, 0xbd, 0x00,
+ 0xaf, 0x00, 0x3f, 0x01, 0xc7, 0x00, 0xc9, 0x00,
+ 0xc0, 0x00, 0xec, 0x00, 0xc7, 0x00, 0x02, 0x01,
+ 0x70, 0x61, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20,
+ 0x6c, 0x61, 0x6b, 0x65, 0x20, 0x73, 0x68, 0x6f,
+ 0x72, 0x65, 0x00, 0x01, 0x02, 0x37, 0x00, 0x50,
+ 0x00, 0x50, 0x00, 0x69, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x04, 0x01, 0x64,
+ 0x6f, 0x6f, 0x72, 0x00, 0x54, 0x68, 0x65, 0x72,
+ 0x65, 0x27, 0x73, 0x20, 0x6e, 0x6f, 0x20, 0x6e,
+ 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x00, 0x64, 0x6f, 0x6f, 0x72, 0x2e,
+ 0x2e, 0x2e, 0x00, 0x00, 0x03, 0x67, 0x00, 0x46,
+ 0x00, 0x85, 0x00, 0x5d, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x01, 0x77,
+ 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x00, 0x49,
+ 0x20, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x20,
+ 0x44, 0x4f, 0x53, 0x2e, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc9,
+ 0x00, 0xc0, 0x00, 0xc9, 0x00, 0xc0, 0x00, 0x01,
+ 0x01, 0x73, 0x71, 0x75, 0x69, 0x72, 0x72, 0x65,
+ 0x6c, 0x00, 0x49, 0x74, 0x27, 0x73, 0x20, 0x76,
+ 0x65, 0x72, 0x79, 0x20, 0x66, 0x61, 0x73, 0x74,
+ 0x2e, 0x00, 0x00, 0x05, 0x92, 0x00, 0x35, 0x00,
+ 0x99, 0x00, 0x3c, 0x00, 0xc9, 0x00, 0xc0, 0x00,
+ 0xc9, 0x00, 0xc0, 0x00, 0x01, 0x01, 0x6e, 0x75,
+ 0x74, 0x00, 0x49, 0x74, 0x27, 0x73, 0x20, 0x62,
+ 0x69, 0x67, 0x2e, 0x00, 0x00, 0x06, 0x8c, 0x00,
+ 0xbb, 0x00, 0x92, 0x00, 0xc1, 0x00, 0x9c, 0x00,
+ 0xc2, 0x00, 0x9c, 0x00, 0xc2, 0x00, 0x04, 0x00,
+ 0x6e, 0x75, 0x74, 0x00, 0x47, 0x6f, 0x74, 0x63,
+ 0x68, 0x61, 0x2e, 0x00, 0x00, 0x07, 0x48, 0x00,
+ 0xb4, 0x00, 0xaa, 0x00, 0xc7, 0x00, 0xa2, 0x00,
+ 0xc2, 0x00, 0xa2, 0x00, 0xc2, 0x00, 0x04, 0x01,
+ 0x67, 0x72, 0x61, 0x73, 0x73, 0x00, 0x01, 0x0c,
+ 0x8d, 0x28, 0x8d, 0x6f, 0x8d, 0xcb, 0x8d, 0xe8,
+ 0x8d, 0x22, 0x8e, 0x3f, 0x8e, 0x5e, 0x8e, 0x99,
+ 0x8e, 0xd7, 0x8e, 0x12, 0x8f, 0x2c, 0x8f, 0x54,
+ 0x8f, 0x71, 0x8f, 0xcc, 0x8f, 0x00, 0x00, 0x01,
+ 0x90, 0x00, 0xbd, 0x00, 0x3f, 0x01, 0xc7, 0x00,
+ 0xdf, 0x00, 0xc1, 0x00, 0xdf, 0x00, 0xc7, 0x00,
+ 0x03, 0x01, 0x77, 0x61, 0x79, 0x20, 0x6f, 0x75,
+ 0x74, 0x00, 0x01, 0x02, 0xcc, 0x00, 0x75, 0x00,
+ 0xe0, 0x00, 0x83, 0x00, 0xd8, 0x00, 0xa7, 0x00,
+ 0xd8, 0x00, 0xa7, 0x00, 0x01, 0x01, 0x68, 0x6f,
+ 0x72, 0x6e, 0x00, 0x49, 0x74, 0x20, 0x6d, 0x75,
+ 0x73, 0x74, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20,
+ 0x61, 0x20, 0x62, 0x69, 0x67, 0x20, 0x69, 0x6d,
+ 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
+ 0x20, 0x6f, 0x6e, 0x00, 0x74, 0x68, 0x65, 0x20,
+ 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x2e,
+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x47, 0x00, 0x1c,
+ 0x00, 0x94, 0x00, 0x51, 0x00, 0xa7, 0x00, 0x51,
+ 0x00, 0xa7, 0x00, 0x04, 0x01, 0x77, 0x69, 0x6e,
+ 0x64, 0x6f, 0x77, 0x00, 0x49, 0x27, 0x6d, 0x20,
+ 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x72, 0x65,
+ 0x20, 0x69, 0x66, 0x20, 0x69, 0x74, 0x20, 0x73,
+ 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x6e, 0x27, 0x74,
+ 0x20, 0x62, 0x65, 0x20, 0x6f, 0x6e, 0x00, 0x74,
+ 0x68, 0x65, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x73, 0x69, 0x64, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x6c,
+ 0x6c, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x04, 0x2e,
+ 0x00, 0x86, 0x00, 0x72, 0x00, 0x98, 0x00, 0x4e,
+ 0x00, 0xa4, 0x00, 0x4e, 0x00, 0xa4, 0x00, 0x01,
+ 0x01, 0x63, 0x75, 0x70, 0x62, 0x6f, 0x61, 0x72,
+ 0x64, 0x00, 0x01, 0x05, 0x81, 0x00, 0x67, 0x00,
+ 0x9a, 0x00, 0x70, 0x00, 0x8b, 0x00, 0xa5, 0x00,
+ 0x8b, 0x00, 0xa5, 0x00, 0x01, 0x01, 0x68, 0x65,
+ 0x61, 0x72, 0x74, 0x2d, 0x73, 0x68, 0x61, 0x70,
+ 0x65, 0x64, 0x20, 0x68, 0x6f, 0x6c, 0x65, 0x00,
+ 0x57, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x6c,
+ 0x6f, 0x76, 0x65, 0x6c, 0x79, 0x20, 0x68, 0x6f,
+ 0x6c, 0x65, 0x2e, 0x00, 0x00, 0x06, 0x7d, 0x00,
+ 0x8c, 0x00, 0x9e, 0x00, 0x9b, 0x00, 0x8f, 0x00,
+ 0xa4, 0x00, 0x8f, 0x00, 0xa4, 0x00, 0x01, 0x01,
+ 0x63, 0x75, 0x70, 0x62, 0x6f, 0x61, 0x72, 0x64,
+ 0x00, 0x01, 0x07, 0x89, 0x00, 0x06, 0x00, 0xb6,
+ 0x00, 0x29, 0x00, 0xa2, 0x00, 0xbb, 0x00, 0xa2,
+ 0x00, 0xbb, 0x00, 0x01, 0x01, 0x63, 0x68, 0x61,
+ 0x6e, 0x64, 0x65, 0x6c, 0x69, 0x65, 0x72, 0x00,
+ 0x01, 0x08, 0x13, 0x01, 0x5e, 0x00, 0x3f, 0x01,
+ 0x81, 0x00, 0xd8, 0x00, 0xa7, 0x00, 0xd8, 0x00,
+ 0xa7, 0x00, 0x02, 0x01, 0x70, 0x69, 0x63, 0x74,
+ 0x75, 0x72, 0x65, 0x00, 0x49, 0x74, 0x20, 0x6c,
+ 0x6f, 0x6f, 0x6b, 0x73, 0x20, 0x61, 0x6c, 0x6d,
+ 0x6f, 0x73, 0x74, 0x20, 0x6c, 0x69, 0x6b, 0x65,
+ 0x20, 0x61, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f,
+ 0x77, 0x2e, 0x00, 0x00, 0x09, 0x11, 0x01, 0x8c,
+ 0x00, 0x25, 0x01, 0xb7, 0x00, 0x0e, 0x01, 0xb6,
+ 0x00, 0x0e, 0x01, 0xb6, 0x00, 0x02, 0x01, 0x66,
+ 0x69, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65,
+ 0x00, 0x54, 0x68, 0x65, 0x72, 0x65, 0x27, 0x73,
+ 0x20, 0x61, 0x20, 0x6c, 0x6f, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x73, 0x6f, 0x6f, 0x74, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x2e,
+ 0x00, 0x00, 0x0a, 0xb9, 0x00, 0x60, 0x00, 0xe8,
+ 0x00, 0x83, 0x00, 0xd8, 0x00, 0xa7, 0x00, 0xd8,
+ 0x00, 0xa7, 0x00, 0x01, 0x01, 0x67, 0x75, 0x6e,
+ 0x73, 0x00, 0x54, 0x68, 0x65, 0x79, 0x20, 0x61,
+ 0x72, 0x65, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20,
+ 0x70, 0x6c, 0x61, 0x73, 0x74, 0x69, 0x63, 0x20,
+ 0x69, 0x6d, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x2e, 0x00, 0x00, 0x0b, 0x37, 0x00,
+ 0xa5, 0x00, 0x8c, 0x00, 0xc7, 0x00, 0x51, 0x00,
+ 0xa7, 0x00, 0x51, 0x00, 0xa7, 0x00, 0x03, 0x01,
+ 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x01, 0x0c,
+ 0x68, 0x00, 0x71, 0x00, 0x6f, 0x00, 0x77, 0x00,
+ 0x6d, 0x00, 0xa4, 0x00, 0x6d, 0x00, 0xa4, 0x00,
+ 0x01, 0x01, 0x72, 0x6f, 0x74, 0x74, 0x65, 0x6e,
+ 0x20, 0x63, 0x68, 0x65, 0x65, 0x73, 0x65, 0x00,
+ 0x50, 0x66, 0x75, 0x69, 0x21, 0x00, 0x00, 0x0d,
+ 0xa9, 0x00, 0x2f, 0x00, 0x3f, 0x01, 0x5d, 0x00,
+ 0xd8, 0x00, 0xa7, 0x00, 0xd8, 0x00, 0xa7, 0x00,
+ 0x01, 0x01, 0x74, 0x72, 0x6f, 0x70, 0x68, 0x69,
+ 0x65, 0x73, 0x00, 0x01, 0x0e, 0xa2, 0x00, 0x8b,
+ 0x00, 0xb6, 0x00, 0xa9, 0x00, 0xc1, 0x00, 0xa4,
+ 0x00, 0xc1, 0x00, 0xa4, 0x00, 0x04, 0x01, 0x63,
+ 0x68, 0x61, 0x69, 0x6e, 0x73, 0x61, 0x77, 0x00,
+ 0x49, 0x20, 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x20,
+ 0x6b, 0x6e, 0x6f, 0x77, 0x20, 0x77, 0x68, 0x79,
+ 0x20, 0x62, 0x75, 0x74, 0x20, 0x69, 0x74, 0x20,
+ 0x72, 0x65, 0x6d, 0x69, 0x6e, 0x64, 0x73, 0x20,
+ 0x6f, 0x66, 0x00, 0x73, 0x6f, 0x6d, 0x65, 0x20,
+ 0x54, 0x65, 0x78, 0x61, 0x73, 0x20, 0x67, 0x75,
+ 0x79, 0x20, 0x49, 0x20, 0x6d, 0x65, 0x74, 0x20,
+ 0x6f, 0x6e, 0x63, 0x65, 0x2e, 0x00, 0x00, 0x0f,
+ 0x2d, 0x00, 0x6c, 0x00, 0x72, 0x00, 0x84, 0x00,
+ 0x51, 0x00, 0xa7, 0x00, 0x51, 0x00, 0xa7, 0x00,
+ 0x01, 0x01, 0x70, 0x6f, 0x72, 0x63, 0x65, 0x6c,
+ 0x61, 0x69, 0x6e, 0x00, 0x49, 0x27, 0x6d, 0x20,
+ 0x61, 0x66, 0x72, 0x61, 0x69, 0x64, 0x20, 0x65,
+ 0x76, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x62,
+ 0x72, 0x65, 0x61, 0x74, 0x68, 0x20, 0x61, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x73, 0x65, 0x00, 0x74, 0x68, 0x69, 0x6e, 0x67,
+ 0x73, 0x2e, 0x00, 0x00, 0x3b, 0x90, 0x67, 0x90,
+ 0xaf, 0x90, 0x01, 0x91, 0x55, 0x91, 0x6e, 0x91,
+ 0xc0, 0x91, 0xdb, 0x91, 0xf6, 0x91, 0x17, 0x92,
+ 0x38, 0x92, 0x51, 0x92, 0x73, 0x92, 0xf8, 0x92,
+ 0x20, 0x93, 0x52, 0x93, 0x00, 0x00, 0x01, 0x1d,
+ 0x01, 0x87, 0x00, 0x3b, 0x01, 0xaa, 0x00, 0x16,
+ 0x01, 0xbd, 0x00, 0x16, 0x01, 0xbd, 0x00, 0x02,
+ 0x01, 0x63, 0x61, 0x72, 0x20, 0x64, 0x6f, 0x6f,
+ 0x72, 0x00, 0x49, 0x74, 0x27, 0x73, 0x20, 0x75,
+ 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x2e,
+ 0x00, 0x00, 0x02, 0xbf, 0x00, 0x88, 0x00, 0xe6,
+ 0x00, 0x9c, 0x00, 0xa8, 0x00, 0xb3, 0x00, 0xa8,
+ 0x00, 0xb3, 0x00, 0x02, 0x01, 0x74, 0x72, 0x75,
+ 0x6e, 0x6b, 0x00, 0x54, 0x68, 0x65, 0x72, 0x65,
+ 0x27, 0x73, 0x20, 0x61, 0x6c, 0x77, 0x61, 0x79,
+ 0x73, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x74, 0x68,
+ 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65, 0x66,
+ 0x75, 0x6c, 0x00, 0x69, 0x6e, 0x20, 0x61, 0x20,
+ 0x74, 0x72, 0x75, 0x6e, 0x6b, 0x2e, 0x2e, 0x2e,
+ 0x00, 0x00, 0x03, 0x50, 0x00, 0x47, 0x00, 0x64,
+ 0x00, 0x51, 0x00, 0x51, 0x00, 0xb5, 0x00, 0x51,
+ 0x00, 0xb5, 0x00, 0x01, 0x01, 0x62, 0x61, 0x73,
+ 0x6b, 0x65, 0x74, 0x00, 0x49, 0x74, 0x20, 0x67,
+ 0x69, 0x76, 0x65, 0x73, 0x20, 0x6d, 0x65, 0x20,
+ 0x61, 0x6d, 0x62, 0x69, 0x76, 0x61, 0x6c, 0x65,
+ 0x6e, 0x74, 0x20, 0x66, 0x65, 0x65, 0x6c, 0x69,
+ 0x6e, 0x67, 0x73, 0x3a, 0x00, 0x72, 0x65, 0x6d,
+ 0x69, 0x6e, 0x64, 0x73, 0x20, 0x6d, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x73, 0x63, 0x68, 0x6f, 0x6f,
+ 0x6c, 0x2e, 0x00, 0x00, 0x04, 0x65, 0x00, 0x3c,
+ 0x00, 0x69, 0x00, 0xa0, 0x00, 0x65, 0x00, 0xb5,
+ 0x00, 0x65, 0x00, 0xb5, 0x00, 0x01, 0x01, 0x70,
+ 0x6f, 0x6c, 0x65, 0x00, 0x41, 0x62, 0x6f, 0x75,
+ 0x74, 0x20, 0x34, 0x20, 0x6d, 0x65, 0x74, 0x65,
+ 0x72, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6d,
+ 0x65, 0x74, 0x61, 0x6c, 0x20, 0x70, 0x6f, 0x6c,
+ 0x65, 0x00, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61,
+ 0x20, 0x62, 0x61, 0x73, 0x6b, 0x65, 0x74, 0x20,
+ 0x73, 0x63, 0x72, 0x65, 0x77, 0x65, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x69, 0x74, 0x2e, 0x00, 0x00,
+ 0x05, 0x90, 0x00, 0x5a, 0x00, 0xb7, 0x00, 0x9f,
+ 0x00, 0xa1, 0x00, 0xa5, 0x00, 0xa1, 0x00, 0xa5,
+ 0x00, 0x01, 0x01, 0x64, 0x6f, 0x6f, 0x72, 0x00,
+ 0x01, 0x06, 0xbe, 0x00, 0x71, 0x00, 0xc5, 0x00,
+ 0x7c, 0x00, 0xa1, 0x00, 0xa5, 0x00, 0xa1, 0x00,
+ 0xa5, 0x00, 0x02, 0x01, 0x64, 0x6f, 0x6f, 0x72,
+ 0x2d, 0x62, 0x65, 0x6c, 0x6c, 0x00, 0x4f, 0x6e,
+ 0x65, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x75, 0x73,
+ 0x65, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20,
+ 0x73, 0x63, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65,
+ 0x00, 0x62, 0x65, 0x68, 0x69, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x6f, 0x6f, 0x72,
+ 0x2e, 0x00, 0x00, 0x07, 0xd0, 0x00, 0x4b, 0x00,
+ 0xfd, 0x00, 0x7e, 0x00, 0xa9, 0x00, 0xae, 0x00,
+ 0xa9, 0x00, 0xae, 0x00, 0x02, 0x01, 0x77, 0x69,
+ 0x6e, 0x64, 0x6f, 0x77, 0x00, 0x01, 0x08, 0x10,
+ 0x01, 0x4b, 0x00, 0x3d, 0x01, 0x7d, 0x00, 0xa9,
+ 0x00, 0xae, 0x00, 0xa9, 0x00, 0xae, 0x00, 0x02,
+ 0x01, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x00,
+ 0x01, 0x09, 0x4b, 0x00, 0x02, 0x00, 0x58, 0x00,
+ 0x1b, 0x00, 0x51, 0x00, 0xb5, 0x00, 0x51, 0x00,
+ 0xb5, 0x00, 0x01, 0x01, 0x61, 0x74, 0x74, 0x69,
+ 0x63, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77,
+ 0x00, 0x01, 0x0a, 0x00, 0x00, 0xaa, 0x00, 0x21,
+ 0x00, 0xc7, 0x00, 0x30, 0x00, 0xbb, 0x00, 0x00,
+ 0x00, 0xbb, 0x00, 0x04, 0x01, 0x70, 0x61, 0x74,
+ 0x68, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x61, 0x6b,
+ 0x65, 0x00, 0x01, 0x0b, 0x17, 0x01, 0xaa, 0x00,
+ 0x3f, 0x01, 0xc7, 0x00, 0x21, 0x01, 0xbe, 0x00,
+ 0x3f, 0x01, 0xbe, 0x00, 0x02, 0x01, 0x70, 0x61,
+ 0x74, 0x68, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x74,
+ 0x00, 0x1c, 0x00, 0xa9, 0x00, 0x30, 0x00, 0xbb,
+ 0x00, 0x05, 0x00, 0x83, 0x00, 0x01, 0x01, 0x70,
+ 0x61, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x66,
+ 0x69, 0x65, 0x6c, 0x64, 0x00, 0x01, 0x0d, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x00, 0xbb, 0x00, 0x40, 0x00, 0xbb, 0x00, 0x01,
+ 0x01, 0x62, 0x6f, 0x79, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0x65, 0x27, 0x73, 0x20,
+ 0x74, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x68,
+ 0x61, 0x72, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x73,
+ 0x63, 0x6f, 0x72, 0x65, 0x2c, 0x00, 0x62, 0x75,
+ 0x74, 0x20, 0x68, 0x65, 0x27, 0x73, 0x20, 0x74,
+ 0x6f, 0x6f, 0x20, 0x77, 0x65, 0x61, 0x6b, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x72, 0x6f, 0x77,
+ 0x00, 0x74, 0x68, 0x65, 0x20, 0x62, 0x61, 0x6c,
+ 0x6c, 0x20, 0x68, 0x69, 0x67, 0x68, 0x20, 0x65,
+ 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x21, 0x00, 0x00,
+ 0x53, 0x6f, 0x6e, 0x6e, 0x79, 0x20, 0x6f, 0x72,
+ 0x20, 0x77, 0x68, 0x61, 0x74, 0x65, 0x76, 0x65,
+ 0x72, 0x00, 0xff, 0x0e, 0x1d, 0x01, 0x91, 0x00,
+ 0x23, 0x01, 0x9b, 0x00, 0x16, 0x01, 0xbd, 0x00,
+ 0x16, 0x01, 0xbd, 0x00, 0x02, 0x00, 0x63, 0x6f,
+ 0x6d, 0x62, 0x00, 0x53, 0x74, 0x72, 0x61, 0x6e,
+ 0x67, 0x65, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67,
+ 0x2e, 0x00, 0x00, 0x0f, 0x1e, 0x01, 0xa5, 0x00,
+ 0x24, 0x01, 0xa9, 0x00, 0x16, 0x01, 0xbd, 0x00,
+ 0x16, 0x01, 0xbd, 0x00, 0x02, 0x00, 0x6c, 0x65,
+ 0x76, 0x65, 0x72, 0x00, 0x49, 0x20, 0x77, 0x6f,
+ 0x6e, 0x64, 0x65, 0x72, 0x20, 0x77, 0x68, 0x61,
+ 0x74, 0x00, 0x69, 0x74, 0x27, 0x73, 0x20, 0x66,
+ 0x6f, 0x72, 0x3f, 0x00, 0x00, 0x10, 0x26, 0x01,
+ 0x85, 0x00, 0x3b, 0x01, 0xac, 0x00, 0x16, 0x01,
+ 0xbd, 0x00, 0x16, 0x01, 0xbd, 0x00, 0x02, 0x00,
+ 0x63, 0x61, 0x72, 0x20, 0x64, 0x6f, 0x6f, 0x72,
+ 0x00, 0x01, 0x89, 0x93, 0xa2, 0x93, 0xc3, 0x93,
+ 0xdc, 0x93, 0x27, 0x94, 0x42, 0x94, 0x5d, 0x94,
+ 0x78, 0x94, 0xa6, 0x94, 0xda, 0x94, 0xfa, 0x94,
+ 0x13, 0x95, 0x00, 0x00, 0x01, 0x00, 0x00, 0xac,
+ 0x00, 0x2b, 0x00, 0xc3, 0x00, 0x30, 0x00, 0xbe,
+ 0x00, 0x00, 0x00, 0xbb, 0x00, 0x04, 0x01, 0x70,
+ 0x61, 0x74, 0x68, 0x00, 0x01, 0x02, 0xb0, 0x00,
+ 0xb6, 0x00, 0xdd, 0x00, 0xc7, 0x00, 0xc4, 0x00,
+ 0xc2, 0x00, 0xce, 0x00, 0xc7, 0x00, 0x03, 0x01,
+ 0x70, 0x61, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20,
+ 0x63, 0x61, 0x76, 0x65, 0x00, 0x01, 0x03, 0x50,
+ 0x00, 0x68, 0x00, 0x79, 0x00, 0xa9, 0x00, 0x64,
+ 0x00, 0xb0, 0x00, 0x64, 0x00, 0xb0, 0x00, 0x01,
+ 0x01, 0x64, 0x6f, 0x6f, 0x72, 0x00, 0x01, 0x04,
+ 0x00, 0x00, 0x82, 0x00, 0x3f, 0x00, 0xab, 0x00,
+ 0x30, 0x00, 0xbe, 0x00, 0x30, 0x00, 0xbe, 0x00,
+ 0x04, 0x01, 0x6c, 0x61, 0x75, 0x6e, 0x64, 0x72,
+ 0x79, 0x00, 0x54, 0x68, 0x65, 0x20, 0x61, 0x69,
+ 0x72, 0x20, 0x69, 0x73, 0x20, 0x74, 0x6f, 0x6f,
+ 0x20, 0x64, 0x61, 0x6d, 0x70, 0x20, 0x74, 0x6f,
+ 0x20, 0x64, 0x72, 0x79, 0x00, 0x74, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x65, 0x74, 0x20, 0x6c, 0x61,
+ 0x75, 0x6e, 0x64, 0x72, 0x79, 0x2e, 0x2e, 0x2e,
+ 0x00, 0x00, 0x05, 0x8d, 0x00, 0x58, 0x00, 0xba,
+ 0x00, 0x90, 0x00, 0x9f, 0x00, 0xbd, 0x00, 0x9f,
+ 0x00, 0xbd, 0x00, 0x01, 0x01, 0x77, 0x69, 0x6e,
+ 0x64, 0x6f, 0x77, 0x00, 0x01, 0x06, 0xce, 0x00,
+ 0x58, 0x00, 0xfb, 0x00, 0x90, 0x00, 0x9f, 0x00,
+ 0xbd, 0x00, 0x9f, 0x00, 0xbd, 0x00, 0x02, 0x01,
+ 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x00, 0x01,
+ 0x07, 0x15, 0x01, 0x55, 0x00, 0x36, 0x01, 0x82,
+ 0x00, 0xc4, 0x00, 0xc2, 0x00, 0xc4, 0x00, 0xc2,
+ 0x00, 0x02, 0x01, 0x77, 0x69, 0x6e, 0x64, 0x6f,
+ 0x77, 0x00, 0x01, 0x08, 0x1a, 0x01, 0x9c, 0x00,
+ 0x38, 0x01, 0xab, 0x00, 0x29, 0x01, 0xb5, 0x00,
+ 0x29, 0x01, 0xb2, 0x00, 0x01, 0x00, 0x68, 0x6f,
+ 0x6c, 0x65, 0x00, 0x41, 0x20, 0x77, 0x61, 0x79,
+ 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x65, 0x6c, 0x6c, 0x61, 0x72, 0x2e, 0x00,
+ 0x00, 0x09, 0x0b, 0x01, 0x83, 0x00, 0x3f, 0x01,
+ 0xb0, 0x00, 0xc4, 0x00, 0xc2, 0x00, 0xc4, 0x00,
+ 0xc2, 0x00, 0x02, 0x01, 0x76, 0x61, 0x6c, 0x76,
+ 0x65, 0x00, 0x49, 0x74, 0x27, 0x73, 0x20, 0x61,
+ 0x20, 0x68, 0x65, 0x61, 0x76, 0x79, 0x20, 0x6d,
+ 0x65, 0x74, 0x61, 0x6c, 0x20, 0x74, 0x68, 0x69,
+ 0x6e, 0x67, 0x2e, 0x00, 0x00, 0x0a, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x00,
+ 0xc2, 0x00, 0xc4, 0x00, 0xc2, 0x00, 0x02, 0x01,
+ 0x64, 0x6f, 0x67, 0x00, 0x53, 0x6e, 0x6f, 0x6f,
+ 0x70, 0x79, 0x2e, 0x00, 0x00, 0x0b, 0x7c, 0x00,
+ 0x84, 0x00, 0x81, 0x00, 0x8e, 0x00, 0x64, 0x00,
+ 0xb0, 0x00, 0x64, 0x00, 0xb0, 0x00, 0x02, 0x01,
+ 0x62, 0x65, 0x6c, 0x6c, 0x00, 0x01, 0x0c, 0x00,
+ 0x00, 0x82, 0x00, 0x3f, 0x00, 0xa1, 0x00, 0x3f,
+ 0x00, 0xbb, 0x00, 0x3f, 0x00, 0xbb, 0x00, 0x01,
+ 0x01, 0x72, 0x6f, 0x70, 0x65, 0x00, 0x01, 0x48,
+ 0x95, 0x86, 0x95, 0xa3, 0x95, 0xd2, 0x95, 0xfe,
+ 0x95, 0x2e, 0x96, 0x48, 0x96, 0x88, 0x96, 0xae,
+ 0x96, 0x0f, 0x97, 0x36, 0x97, 0x4f, 0x97, 0x6e,
+ 0x97, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xe6, 0x00, 0xac, 0x00,
+ 0xe6, 0x00, 0xac, 0x00, 0x03, 0x01, 0x6f, 0x6c,
+ 0x64, 0x20, 0x6d, 0x61, 0x6e, 0x00, 0x48, 0x65,
+ 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x73, 0x20, 0x6c,
+ 0x69, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x72, 0x65,
+ 0x74, 0x69, 0x72, 0x65, 0x64, 0x00, 0x73, 0x65,
+ 0x61, 0x20, 0x77, 0x6f, 0x6c, 0x66, 0x2e, 0x00,
+ 0x00, 0x02, 0x60, 0x00, 0x5e, 0x00, 0x7a, 0x00,
+ 0x7f, 0x00, 0x6d, 0x00, 0xa9, 0x00, 0x6d, 0x00,
+ 0xa9, 0x00, 0x01, 0x01, 0x63, 0x75, 0x70, 0x62,
+ 0x6f, 0x61, 0x72, 0x64, 0x00, 0x01, 0x03, 0x63,
+ 0x00, 0x83, 0x00, 0xb2, 0x00, 0x97, 0x00, 0xa3,
+ 0x00, 0xab, 0x00, 0xa3, 0x00, 0xab, 0x00, 0x01,
+ 0x01, 0x64, 0x72, 0x61, 0x77, 0x65, 0x72, 0x73,
+ 0x00, 0x42, 0x6f, 0x79, 0x21, 0x20, 0x4c, 0x6f,
+ 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x6d, 0x21, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0xb7, 0x00, 0x8e, 0x00, 0xc7, 0x00, 0x63, 0x00,
+ 0xb4, 0x00, 0x63, 0x00, 0xb4, 0x00, 0x03, 0x01,
+ 0x62, 0x65, 0x64, 0x00, 0x48, 0x6f, 0x6d, 0x65,
+ 0x2c, 0x20, 0x73, 0x77, 0x65, 0x65, 0x74, 0x20,
+ 0x68, 0x6f, 0x6d, 0x65, 0x2e, 0x2e, 0x2e, 0x00,
+ 0x00, 0x05, 0x13, 0x01, 0x51, 0x00, 0x28, 0x01,
+ 0x92, 0x00, 0xf4, 0x00, 0xac, 0x00, 0xf4, 0x00,
+ 0xac, 0x00, 0x02, 0x01, 0x77, 0x69, 0x6e, 0x64,
+ 0x6f, 0x77, 0x00, 0x41, 0x20, 0x76, 0x69, 0x65,
+ 0x77, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x00,
+ 0x00, 0x06, 0xc8, 0x00, 0x87, 0x00, 0xf4, 0x00,
+ 0x9b, 0x00, 0xd2, 0x00, 0xac, 0x00, 0xd2, 0x00,
+ 0xac, 0x00, 0x01, 0x01, 0x74, 0x61, 0x62, 0x6c,
+ 0x65, 0x00, 0x01, 0x07, 0xc0, 0x00, 0x68, 0x00,
+ 0xec, 0x00, 0x7f, 0x00, 0xd2, 0x00, 0xac, 0x00,
+ 0xd2, 0x00, 0xac, 0x00, 0x01, 0x01, 0x73, 0x68,
+ 0x6f, 0x74, 0x67, 0x75, 0x6e, 0x00, 0x47, 0x65,
+ 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x6d, 0x75,
+ 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f,
+ 0x72, 0x00, 0x64, 0x69, 0x6e, 0x6f, 0x73, 0x61,
+ 0x75, 0x72, 0x75, 0x73, 0x65, 0x73, 0x21, 0x2e,
+ 0x2e, 0x00, 0x00, 0x08, 0xbd, 0x00, 0x38, 0x00,
+ 0xe6, 0x00, 0x65, 0x00, 0xd2, 0x00, 0xac, 0x00,
+ 0xd2, 0x00, 0xac, 0x00, 0x01, 0x01, 0x70, 0x69,
+ 0x63, 0x74, 0x75, 0x72, 0x65, 0x00, 0x43, 0x68,
+ 0x61, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0x2e, 0x00,
+ 0x00, 0x09, 0x87, 0x00, 0x47, 0x00, 0xb8, 0x00,
+ 0x6a, 0x00, 0x96, 0x00, 0xac, 0x00, 0x96, 0x00,
+ 0xac, 0x00, 0x01, 0x01, 0x66, 0x61, 0x6d, 0x69,
+ 0x6c, 0x79, 0x20, 0x70, 0x69, 0x63, 0x74, 0x75,
+ 0x72, 0x65, 0x73, 0x00, 0x49, 0x20, 0x77, 0x6f,
+ 0x75, 0x6c, 0x64, 0x6e, 0x27, 0x74, 0x20, 0x6c,
+ 0x69, 0x6b, 0x65, 0x20, 0x68, 0x61, 0x76, 0x69,
+ 0x6e, 0x67, 0x20, 0x6d, 0x79, 0x20, 0x61, 0x6e,
+ 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, 0x20,
+ 0x68, 0x61, 0x6e, 0x67, 0x69, 0x6e, 0x67, 0x00,
+ 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x72, 0x6f,
+ 0x70, 0x68, 0x69, 0x65, 0x73, 0x2e, 0x2e, 0x2e,
+ 0x00, 0x00, 0x0a, 0x37, 0x00, 0x56, 0x00, 0x57,
+ 0x00, 0x89, 0x00, 0x46, 0x00, 0xac, 0x00, 0x46,
+ 0x00, 0xac, 0x00, 0x01, 0x01, 0x66, 0x6c, 0x6f,
+ 0x77, 0x65, 0x72, 0x00, 0x49, 0x74, 0x27, 0x73,
+ 0x20, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x2e, 0x00,
+ 0x00, 0x0b, 0x0d, 0x00, 0x60, 0x00, 0x2c, 0x00,
+ 0xac, 0x00, 0x3d, 0x00, 0xaf, 0x00, 0x3d, 0x00,
+ 0xaf, 0x00, 0x04, 0x01, 0x64, 0x6f, 0x6f, 0x72,
+ 0x00, 0x01, 0x0c, 0x94, 0x00, 0x04, 0x00, 0xb6,
+ 0x00, 0x37, 0x00, 0xa3, 0x00, 0xab, 0x00, 0xa3,
+ 0x00, 0xab, 0x00, 0x01, 0x01, 0x63, 0x68, 0x61,
+ 0x6e, 0x64, 0x65, 0x6c, 0x69, 0x65, 0x72, 0x00,
+ 0x01, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xb7, 0x00, 0xaa, 0x00, 0xb7, 0x00,
+ 0xaa, 0x00, 0x01, 0x01, 0x66, 0x61, 0x6e, 0x00,
+ 0x49, 0x74, 0x27, 0x73, 0x20, 0x62, 0x61, 0x74,
+ 0x74, 0x65, 0x72, 0x79, 0x20, 0x70, 0x6f, 0x77,
+ 0x65, 0x72, 0x65, 0x64, 0x2e, 0x00, 0x00, 0xbe,
+ 0x97, 0xfb, 0x97, 0x26, 0x98, 0x42, 0x98, 0x5d,
+ 0x98, 0x78, 0x98, 0x97, 0x98, 0xcb, 0x98, 0xe1,
+ 0x98, 0x23, 0x99, 0x51, 0x99, 0x97, 0x99, 0xdb,
+ 0x99, 0x3f, 0x9a, 0x7d, 0x9a, 0xe2, 0x9a, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x5d, 0x00, 0xba, 0x00, 0x5d, 0x00,
+ 0xba, 0x00, 0x04, 0x01, 0x6f, 0x6c, 0x64, 0x20,
+ 0x6c, 0x61, 0x64, 0x79, 0x00, 0x53, 0x68, 0x65,
+ 0x20, 0x6b, 0x6e, 0x69, 0x74, 0x73, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x74,
+ 0x65, 0x61, 0x6d, 0x2e, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+ 0x01, 0x67, 0x69, 0x72, 0x6c, 0x00, 0x53, 0x68,
+ 0x65, 0x27, 0x73, 0x20, 0x63, 0x6f, 0x6f, 0x6c,
+ 0x2e, 0x00, 0x00, 0x41, 0x6e, 0x6e, 0x65, 0x00,
+ 0xff, 0x03, 0x00, 0x00, 0xbc, 0x00, 0x6b, 0x00,
+ 0xc7, 0x00, 0x5e, 0x00, 0xbe, 0x00, 0x4c, 0x00,
+ 0xc7, 0x00, 0x03, 0x01, 0x77, 0x61, 0x79, 0x20,
+ 0x6f, 0x75, 0x74, 0x00, 0x01, 0x04, 0x02, 0x00,
+ 0x48, 0x00, 0x30, 0x00, 0x84, 0x00, 0x5d, 0x00,
+ 0xba, 0x00, 0x5d, 0x00, 0xba, 0x00, 0x01, 0x01,
+ 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x00, 0x01,
+ 0x05, 0x84, 0x00, 0x48, 0x00, 0xb0, 0x00, 0x84,
+ 0x00, 0x9b, 0x00, 0xac, 0x00, 0x9b, 0x00, 0xac,
+ 0x00, 0x01, 0x01, 0x77, 0x69, 0x6e, 0x64, 0x6f,
+ 0x77, 0x00, 0x01, 0x06, 0x4b, 0x00, 0x0a, 0x00,
+ 0x78, 0x00, 0x38, 0x00, 0x5d, 0x00, 0xba, 0x00,
+ 0x5d, 0x00, 0xba, 0x00, 0x01, 0x01, 0x63, 0x68,
+ 0x61, 0x6e, 0x64, 0x65, 0x6c, 0x69, 0x65, 0x72,
+ 0x00, 0x01, 0x07, 0x4d, 0x00, 0x61, 0x00, 0x6f,
+ 0x00, 0xa5, 0x00, 0x5d, 0x00, 0xab, 0x00, 0x5d,
+ 0x00, 0xab, 0x00, 0x01, 0x01, 0x63, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x00, 0x52, 0x65, 0x61, 0x6c, 0x6c,
+ 0x79, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20,
+ 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x70, 0x69,
+ 0x65, 0x63, 0x65, 0x2e, 0x00, 0x00, 0x08, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x09, 0x86, 0x00, 0x9f,
+ 0x00, 0x97, 0x00, 0xad, 0x00, 0x9e, 0x00, 0xc6,
+ 0x00, 0x9e, 0x00, 0xc6, 0x00, 0x03, 0x01, 0x69,
+ 0x6d, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x73, 0x00,
+ 0x54, 0x68, 0x65, 0x20, 0x61, 0x70, 0x70, 0x6c,
+ 0x65, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x73, 0x20,
+ 0x61, 0x6c, 0x6d, 0x6f, 0x73, 0x74, 0x00, 0x72,
+ 0x65, 0x61, 0x6c, 0x21, 0x00, 0x00, 0x0a, 0xac,
+ 0x00, 0x9f, 0x00, 0xb6, 0x00, 0xae, 0x00, 0x9e,
+ 0x00, 0xc6, 0x00, 0x9e, 0x00, 0xc6, 0x00, 0x03,
+ 0x01, 0x6a, 0x75, 0x67, 0x00, 0x49, 0x74, 0x20,
+ 0x68, 0x6f, 0x6c, 0x64, 0x73, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x77, 0x65, 0x72,
+ 0x73, 0x2e, 0x00, 0x00, 0x0b, 0xa1, 0x00, 0x89,
+ 0x00, 0xc2, 0x00, 0x9e, 0x00, 0x9e, 0x00, 0xc6,
+ 0x00, 0x9e, 0x00, 0xc6, 0x00, 0x03, 0x01, 0x66,
+ 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x73, 0x00, 0x49,
+ 0x20, 0x68, 0x6f, 0x70, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20,
+ 0x6e, 0x6f, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d,
+ 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x00, 0x61, 0x64,
+ 0x6d, 0x69, 0x72, 0x65, 0x72, 0x2e, 0x2e, 0x2e,
+ 0x00, 0x00, 0x0c, 0x3c, 0x00, 0xa1, 0x00, 0x4c,
+ 0x00, 0xa8, 0x00, 0x5d, 0x00, 0xba, 0x00, 0x4e,
+ 0x00, 0xbc, 0x00, 0x04, 0x01, 0x66, 0x65, 0x61,
+ 0x74, 0x68, 0x65, 0x72, 0x20, 0x64, 0x75, 0x73,
+ 0x74, 0x65, 0x72, 0x00, 0x49, 0x74, 0x20, 0x6d,
+ 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x75, 0x73, 0x74, 0x20, 0x70, 0x72, 0x6f, 0x62,
+ 0x6c, 0x65, 0x6d, 0x2e, 0x00, 0x00, 0x0d, 0x7d,
+ 0x00, 0xa7, 0x00, 0xc2, 0x00, 0xc7, 0x00, 0x9e,
+ 0x00, 0xc6, 0x00, 0x9e, 0x00, 0xc6, 0x00, 0x03,
+ 0x01, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x49,
+ 0x74, 0x27, 0x73, 0x20, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x49,
+ 0x20, 0x64, 0x6f, 0x75, 0x62, 0x74, 0x20, 0x69,
+ 0x74, 0x20, 0x68, 0x61, 0x73, 0x20, 0x61, 0x6e,
+ 0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74,
+ 0x6f, 0x20, 0x64, 0x6f, 0x00, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65,
+ 0x64, 0x69, 0x65, 0x76, 0x61, 0x6c, 0x20, 0x6c,
+ 0x65, 0x67, 0x65, 0x6e, 0x64, 0x2e, 0x2e, 0x2e,
+ 0x00, 0x00, 0x0e, 0xf1, 0x00, 0x60, 0x00, 0x1a,
+ 0x01, 0x94, 0x00, 0x02, 0x01, 0xb8, 0x00, 0x02,
+ 0x01, 0xb8, 0x00, 0x01, 0x01, 0x6d, 0x69, 0x72,
+ 0x72, 0x6f, 0x72, 0x00, 0x49, 0x20, 0x63, 0x61,
+ 0x6e, 0x20, 0x73, 0x65, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x67, 0x69, 0x72, 0x6c, 0x27, 0x73,
+ 0x00, 0x66, 0x61, 0x63, 0x65, 0x20, 0x69, 0x6e,
+ 0x20, 0x69, 0x74, 0x2e, 0x2e, 0x2e, 0x00, 0x00,
+ 0x0f, 0x1d, 0x01, 0x3e, 0x00, 0x3f, 0x01, 0x68,
+ 0x00, 0x02, 0x01, 0xb8, 0x00, 0x02, 0x01, 0xb8,
+ 0x00, 0x02, 0x01, 0x70, 0x69, 0x63, 0x74, 0x75,
+ 0x72, 0x65, 0x00, 0x49, 0x74, 0x27, 0x73, 0x20,
+ 0x6e, 0x69, 0x63, 0x65, 0x20, 0x74, 0x6f, 0x20,
+ 0x6c, 0x69, 0x76, 0x65, 0x20, 0x69, 0x6e, 0x20,
+ 0x61, 0x20, 0x76, 0x69, 0x6c, 0x6c, 0x61, 0x67,
+ 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x76, 0x69, 0x6c, 0x6c, 0x61,
+ 0x67, 0x65, 0x00, 0x6c, 0x61, 0x6e, 0x64, 0x73,
+ 0x63, 0x61, 0x70, 0x65, 0x73, 0x20, 0x6f, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x6c,
+ 0x6c, 0x73, 0x2e, 0x00, 0x00, 0x10, 0x18, 0x01,
+ 0xa1, 0x00, 0x3f, 0x01, 0xc7, 0x00, 0xf5, 0x00,
+ 0xc6, 0x00, 0xf5, 0x00, 0xc6, 0x00, 0x02, 0x01,
+ 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x00, 0x49, 0x6d,
+ 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x76, 0x65,
+ 0x2e, 0x00, 0x00, 0x1c, 0x9b, 0x3f, 0x9b, 0x77,
+ 0x9b, 0x9b, 0x9b, 0xd1, 0x9b, 0x2d, 0x9c, 0x47,
+ 0x9c, 0xa4, 0x9c, 0xf4, 0x9c, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x5e, 0x00, 0xaa, 0x00, 0x5e, 0x00, 0xaa, 0x00,
+ 0x04, 0x01, 0x73, 0x70, 0x69, 0x64, 0x65, 0x72,
+ 0x00, 0x49, 0x74, 0x27, 0x73, 0x2e, 0x2e, 0x2e,
+ 0x00, 0x00, 0x02, 0x38, 0x00, 0x86, 0x00, 0x4e,
+ 0x00, 0xa9, 0x00, 0x5e, 0x00, 0xaa, 0x00, 0x4e,
+ 0x00, 0xaa, 0x00, 0x04, 0x01, 0x73, 0x68, 0x6f,
+ 0x76, 0x65, 0x6c, 0x00, 0x49, 0x20, 0x63, 0x6f,
+ 0x75, 0x6c, 0x64, 0x20, 0x70, 0x6c, 0x61, 0x79,
+ 0x20, 0x64, 0x69, 0x67, 0x67, 0x65, 0x72, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x69, 0x74, 0x2e,
+ 0x00, 0x00, 0x03, 0xd5, 0x00, 0x15, 0x00, 0xf8,
+ 0x00, 0xa5, 0x00, 0xe6, 0x00, 0xaa, 0x00, 0xe6,
+ 0x00, 0xaa, 0x00, 0x01, 0x01, 0x6c, 0x61, 0x64,
+ 0x64, 0x65, 0x72, 0x00, 0x57, 0x61, 0x79, 0x20,
+ 0x6f, 0x75, 0x74, 0x2e, 0x00, 0x00, 0x04, 0xf7,
+ 0x00, 0x70, 0x00, 0xfe, 0x00, 0x7a, 0x00, 0x05,
+ 0x01, 0xa8, 0x00, 0x05, 0x01, 0xa8, 0x00, 0x01,
+ 0x00, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x00,
+ 0x49, 0x74, 0x27, 0x73, 0x20, 0x6c, 0x69, 0x74,
+ 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x62, 0x75, 0x74,
+ 0x20, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x66, 0x75,
+ 0x6c, 0x2e, 0x00, 0x00, 0x05, 0x05, 0x00, 0x5a,
+ 0x00, 0x1e, 0x00, 0x77, 0x00, 0x53, 0x00, 0xb4,
+ 0x00, 0x53, 0x00, 0xb4, 0x00, 0x04, 0x01, 0x61,
+ 0x78, 0x65, 0x00, 0x49, 0x20, 0x68, 0x6f, 0x70,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20,
+ 0x73, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x6c, 0x6c, 0x20, 0x68, 0x61, 0x76, 0x65, 0x00,
+ 0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x6f, 0x20, 0x64, 0x6f, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20,
+ 0x61, 0x78, 0x65, 0x2e, 0x2e, 0x2e, 0x00, 0x00,
+ 0x06, 0x1c, 0x01, 0x38, 0x00, 0x28, 0x01, 0x62,
+ 0x00, 0xf5, 0x00, 0xb2, 0x00, 0xf5, 0x00, 0xb2,
+ 0x00, 0x02, 0x01, 0x63, 0x68, 0x61, 0x69, 0x6e,
+ 0x00, 0x01, 0x07, 0x2e, 0x01, 0x50, 0x00, 0x36,
+ 0x01, 0x62, 0x00, 0xf5, 0x00, 0xb2, 0x00, 0xf5,
+ 0x00, 0xb2, 0x00, 0x02, 0x01, 0x74, 0x6f, 0x6e,
+ 0x67, 0x73, 0x00, 0x47, 0x65, 0x65, 0x2c, 0x20,
+ 0x74, 0x68, 0x69, 0x73, 0x20, 0x70, 0x6c, 0x61,
+ 0x63, 0x65, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x73,
+ 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x6c, 0x69,
+ 0x6b, 0x65, 0x20, 0x61, 0x00, 0x74, 0x6f, 0x72,
+ 0x74, 0x75, 0x72, 0x65, 0x20, 0x63, 0x68, 0x61,
+ 0x6d, 0x62, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61,
+ 0x6e, 0x20, 0x61, 0x20, 0x63, 0x65, 0x6c, 0x6c,
+ 0x61, 0x72, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x08,
+ 0x6b, 0x00, 0x59, 0x00, 0xcc, 0x00, 0xa9, 0x00,
+ 0x99, 0x00, 0xb0, 0x00, 0x99, 0x00, 0xb0, 0x00,
+ 0x01, 0x01, 0x73, 0x68, 0x65, 0x6c, 0x76, 0x65,
+ 0x73, 0x00, 0x4c, 0x6f, 0x74, 0x73, 0x20, 0x6f,
+ 0x66, 0x20, 0x6a, 0x61, 0x72, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x73, 0x74, 0x75, 0x66, 0x66,
+ 0x2e, 0x20, 0x4e, 0x6f, 0x74, 0x68, 0x69, 0x6e,
+ 0x67, 0x00, 0x72, 0x65, 0x61, 0x6c, 0x6c, 0x79,
+ 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73,
+ 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x00, 0x00, 0x09,
+ 0x17, 0x01, 0x8c, 0x00, 0x3f, 0x01, 0xc2, 0x00,
+ 0xf5, 0x00, 0xb2, 0x00, 0xf5, 0x00, 0xb2, 0x00,
+ 0x02, 0x01, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
+ 0x6e, 0x65, 0x72, 0x73, 0x00, 0x54, 0x68, 0x65,
+ 0x79, 0x27, 0x72, 0x65, 0x20, 0x65, 0x6d, 0x70,
+ 0x74, 0x79, 0x2e, 0x00, 0x00, 0x32, 0x9d, 0x90,
+ 0x9d, 0x07, 0x9e, 0x29, 0x9e, 0x42, 0x9e, 0x9e,
+ 0x9e, 0xcf, 0x9e, 0x00, 0x00, 0x01, 0xe1, 0x00,
+ 0x8b, 0x00, 0xf6, 0x00, 0x91, 0x00, 0x0c, 0x01,
+ 0x91, 0x00, 0x0c, 0x01, 0x91, 0x00, 0x04, 0x00,
+ 0x62, 0x6f, 0x6e, 0x65, 0x00, 0x44, 0x75, 0x65,
+ 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x61, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x72, 0x6f, 0x63, 0x6b, 0x20,
+ 0x49, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x6b, 0x00,
+ 0x69, 0x74, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20,
+ 0x62, 0x65, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20,
+ 0x64, 0x69, 0x6e, 0x6f, 0x73, 0x61, 0x75, 0x72,
+ 0x20, 0x62, 0x6f, 0x6e, 0x65, 0x2e, 0x2e, 0x2e,
+ 0x2e, 0x00, 0x00, 0x02, 0x90, 0x00, 0x49, 0x00,
+ 0xcb, 0x00, 0x9e, 0x00, 0xea, 0x00, 0x98, 0x00,
+ 0xea, 0x00, 0x98, 0x00, 0x04, 0x01, 0x62, 0x75,
+ 0x73, 0x68, 0x00, 0x49, 0x74, 0x20, 0x62, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x61, 0x79, 0x20, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x76, 0x65,
+ 0x2e, 0x00, 0x4d, 0x61, 0x79, 0x62, 0x65, 0x20,
+ 0x73, 0x6f, 0x6d, 0x65, 0x6f, 0x6e, 0x65, 0x20,
+ 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x20,
+ 0x69, 0x74, 0x20, 0x68, 0x65, 0x72, 0x65, 0x20,
+ 0x74, 0x6f, 0x00, 0x6b, 0x65, 0x65, 0x70, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x76, 0x65,
+ 0x20, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73,
+ 0x20, 0x73, 0x61, 0x66, 0x65, 0x2e, 0x2e, 0x2e,
+ 0x00, 0x00, 0x03, 0x79, 0x00, 0x34, 0x00, 0xae,
+ 0x00, 0x9e, 0x00, 0xea, 0x00, 0x98, 0x00, 0xea,
+ 0x00, 0x98, 0x00, 0x04, 0x01, 0x63, 0x61, 0x76,
+ 0x65, 0x20, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6e,
+ 0x63, 0x65, 0x00, 0x01, 0x04, 0x15, 0x01, 0x7a,
+ 0x00, 0x3f, 0x01, 0xa9, 0x00, 0x14, 0x01, 0x93,
+ 0x00, 0x3f, 0x01, 0x93, 0x00, 0x02, 0x01, 0x70,
+ 0x61, 0x74, 0x68, 0x00, 0x01, 0x05, 0xdd, 0x00,
+ 0x7a, 0x00, 0xfe, 0x00, 0x94, 0x00, 0xed, 0x00,
+ 0x98, 0x00, 0xed, 0x00, 0x98, 0x00, 0x01, 0x01,
+ 0x72, 0x6f, 0x63, 0x6b, 0x00, 0x49, 0x74, 0x20,
+ 0x6d, 0x75, 0x73, 0x74, 0x20, 0x68, 0x61, 0x76,
+ 0x65, 0x20, 0x66, 0x61, 0x6c, 0x6c, 0x65, 0x6e,
+ 0x20, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61, 0x67,
+ 0x65, 0x73, 0x20, 0x61, 0x67, 0x6f, 0x2e, 0x00,
+ 0x49, 0x20, 0x77, 0x6f, 0x6e, 0x64, 0x65, 0x72,
+ 0x20, 0x69, 0x66, 0x20, 0x61, 0x6e, 0x79, 0x62,
+ 0x6f, 0x64, 0x79, 0x20, 0x67, 0x6f, 0x74, 0x20,
+ 0x68, 0x75, 0x72, 0x74, 0x2e, 0x2e, 0x2e, 0x00,
+ 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xed, 0x00, 0x98, 0x00, 0xed, 0x00,
+ 0x98, 0x00, 0x01, 0x01, 0x62, 0x75, 0x74, 0x74,
+ 0x65, 0x72, 0x66, 0x6c, 0x79, 0x00, 0x49, 0x73,
+ 0x6e, 0x27, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x6c, 0x79, 0x3f,
+ 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xed, 0x00, 0x98, 0x00, 0xed,
+ 0x00, 0x98, 0x00, 0x01, 0x01, 0x62, 0x75, 0x74,
+ 0x74, 0x65, 0x72, 0x66, 0x6c, 0x79, 0x00, 0x49,
+ 0x73, 0x6e, 0x27, 0x74, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x6c, 0x79,
+ 0x3f, 0x00, 0x00, 0x0e, 0x9f, 0x29, 0x9f, 0x4e,
+ 0x9f, 0x6a, 0x9f, 0xbd, 0x9f, 0xea, 0x9f, 0x00,
+ 0x00, 0x01, 0x03, 0x01, 0xa4, 0x00, 0x1d, 0x01,
+ 0xb6, 0x00, 0xf8, 0x00, 0xa9, 0x00, 0xf8, 0x00,
+ 0xa9, 0x00, 0x03, 0x01, 0x6c, 0x69, 0x7a, 0x61,
+ 0x72, 0x64, 0x00, 0x01, 0x02, 0x3f, 0x00, 0x8a,
+ 0x00, 0x5c, 0x00, 0xbc, 0x00, 0x6e, 0x00, 0xaa,
+ 0x00, 0x6e, 0x00, 0xaa, 0x00, 0x03, 0x00, 0x3f,
+ 0x3f, 0x3f, 0x00, 0x57, 0x68, 0x61, 0x74, 0x20,
+ 0x49, 0x53, 0x20, 0x49, 0x54, 0x3f, 0x21, 0x00,
+ 0x00, 0x03, 0x11, 0x01, 0x70, 0x00, 0x3f, 0x01,
+ 0xc7, 0x00, 0xf8, 0x00, 0xa9, 0x00, 0x3f, 0x01,
+ 0xa9, 0x00, 0x02, 0x01, 0x77, 0x61, 0x79, 0x20,
+ 0x6f, 0x75, 0x74, 0x00, 0x01, 0x04, 0x97, 0x00,
+ 0x54, 0x00, 0xad, 0x00, 0x5d, 0x00, 0x9f, 0x00,
+ 0xaa, 0x00, 0x9f, 0x00, 0xaa, 0x00, 0x01, 0x01,
+ 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x00,
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x73,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+ 0x20, 0x69, 0x73, 0x20, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x62, 0x75,
+ 0x74, 0x20, 0x49, 0x20, 0x63, 0x61, 0x6e, 0x20,
+ 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x00, 0x72, 0x65,
+ 0x61, 0x64, 0x20, 0x69, 0x74, 0x2e, 0x00, 0x00,
+ 0x05, 0x9a, 0x00, 0x5e, 0x00, 0xa6, 0x00, 0x67,
+ 0x00, 0x9f, 0x00, 0xaa, 0x00, 0x9f, 0x00, 0xaa,
+ 0x00, 0x01, 0x01, 0x68, 0x6f, 0x6c, 0x65, 0x00,
+ 0x49, 0x74, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x73,
+ 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x64, 0x65,
+ 0x65, 0x70, 0x2e, 0x00, 0x00, 0x06, 0xf9, 0x00,
+ 0x9d, 0x00, 0xff, 0x00, 0xa3, 0x00, 0xee, 0x00,
+ 0xa8, 0x00, 0xee, 0x00, 0xa8, 0x00, 0x02, 0x00,
+ 0x6e, 0x75, 0x67, 0x67, 0x65, 0x74, 0x00, 0x50,
+ 0x75, 0x72, 0x65, 0x20, 0x67, 0x6f, 0x6c, 0x64,
+ 0x21, 0x00, 0x00, 0x32, 0xa0, 0x5e, 0xa0, 0x8d,
+ 0xa0, 0xb9, 0xa0, 0xe6, 0xa0, 0x1c, 0xa1, 0x51,
+ 0xa1, 0xb1, 0xa1, 0xe3, 0xa1, 0x07, 0xa2, 0x64,
+ 0xa2, 0xad, 0xa2, 0xe6, 0xa2, 0x21, 0xa3, 0x5f,
+ 0xa3, 0x7d, 0xa3, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00,
+ 0xc3, 0x00, 0x96, 0x00, 0xc3, 0x00, 0x02, 0x01,
+ 0x68, 0x65, 0x6e, 0x00, 0x41, 0x20, 0x6c, 0x69,
+ 0x74, 0x74, 0x6c, 0x65, 0x20, 0x73, 0x74, 0x72,
+ 0x61, 0x6e, 0x67, 0x65, 0x2e, 0x2e, 0x2e, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xe0, 0x00, 0x87, 0x00, 0xe0, 0x00,
+ 0x87, 0x00, 0x01, 0x01, 0x63, 0x72, 0x6f, 0x77,
+ 0x00, 0x45, 0x78, 0x74, 0x72, 0x65, 0x6d, 0x65,
+ 0x6c, 0x79, 0x20, 0x75, 0x6e, 0x66, 0x72, 0x69,
+ 0x65, 0x6e, 0x64, 0x6c, 0x79, 0x2e, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xe0, 0x00, 0x87, 0x00, 0xe0, 0x00, 0x87,
+ 0x00, 0x01, 0x01, 0x63, 0x72, 0x6f, 0x77, 0x00,
+ 0x4c, 0x6f, 0x6f, 0x6b, 0x73, 0x20, 0x64, 0x61,
+ 0x6e, 0x67, 0x65, 0x72, 0x6f, 0x75, 0x73, 0x2e,
+ 0x2e, 0x2e, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x00, 0x8e,
+ 0x00, 0xec, 0x00, 0x8e, 0x00, 0x04, 0x01, 0x6d,
+ 0x6f, 0x75, 0x73, 0x65, 0x00, 0x49, 0x74, 0x27,
+ 0x73, 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6e,
+ 0x65, 0x72, 0x76, 0x6f, 0x75, 0x73, 0x2e, 0x00,
+ 0x00, 0x05, 0xdb, 0x00, 0x41, 0x00, 0xe9, 0x00,
+ 0x47, 0x00, 0xe0, 0x00, 0x87, 0x00, 0xe0, 0x00,
+ 0x87, 0x00, 0x01, 0x01, 0x64, 0x69, 0x76, 0x65,
+ 0x20, 0x6d, 0x61, 0x73, 0x6b, 0x00, 0x59, 0x65,
+ 0x61, 0x68, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x61,
+ 0x6d, 0x61, 0x7a, 0x65, 0x73, 0x20, 0x6d, 0x65,
+ 0x20, 0x74, 0x6f, 0x6f, 0x2e, 0x00, 0x00, 0x06,
+ 0xc9, 0x00, 0x72, 0x00, 0xf1, 0x00, 0x80, 0x00,
+ 0xe0, 0x00, 0x87, 0x00, 0xde, 0x00, 0x8f, 0x00,
+ 0x01, 0x01, 0x66, 0x69, 0x6e, 0x73, 0x00, 0x54,
+ 0x68, 0x65, 0x79, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x66, 0x69, 0x74, 0x20, 0x6d, 0x65, 0x20,
+ 0x70, 0x65, 0x72, 0x66, 0x65, 0x63, 0x74, 0x6c,
+ 0x79, 0x2e, 0x00, 0x00, 0x07, 0xc8, 0x00, 0x3a,
+ 0x00, 0xf5, 0x00, 0x80, 0x00, 0xe0, 0x00, 0x87,
+ 0x00, 0xe0, 0x00, 0x87, 0x00, 0x01, 0x01, 0x73,
+ 0x63, 0x61, 0x72, 0x65, 0x63, 0x72, 0x6f, 0x77,
+ 0x00, 0x41, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67,
+ 0x20, 0x74, 0x6f, 0x20, 0x73, 0x63, 0x61, 0x72,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x72,
+ 0x6f, 0x77, 0x73, 0x2e, 0x00, 0x41, 0x74, 0x20,
+ 0x6c, 0x65, 0x61, 0x73, 0x74, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x27, 0x73, 0x20, 0x77, 0x68, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x00, 0x74, 0x68,
+ 0x65, 0x6f, 0x72, 0x79, 0x20, 0x73, 0x61, 0x79,
+ 0x73, 0x2e, 0x00, 0x00, 0x08, 0x7a, 0x00, 0xa7,
+ 0x00, 0x87, 0x00, 0xb3, 0x00, 0x90, 0x00, 0xb5,
+ 0x00, 0x90, 0x00, 0xb5, 0x00, 0x04, 0x01, 0x73,
+ 0x69, 0x63, 0x6b, 0x6c, 0x65, 0x00, 0x41, 0x20,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x64, 0x61, 0x6e,
+ 0x67, 0x65, 0x72, 0x6f, 0x75, 0x73, 0x20, 0x74,
+ 0x6f, 0x6f, 0x6c, 0x2e, 0x00, 0x00, 0x09, 0x3d,
+ 0x00, 0xb6, 0x00, 0x8d, 0x00, 0xc7, 0x00, 0x84,
+ 0x00, 0xbe, 0x00, 0x7e, 0x00, 0xc7, 0x00, 0x03,
+ 0x01, 0x70, 0x61, 0x74, 0x68, 0x20, 0x74, 0x6f,
+ 0x20, 0x76, 0x69, 0x6c, 0x6c, 0x61, 0x67, 0x65,
+ 0x00, 0x01, 0x0a, 0x7b, 0x00, 0x7a, 0x00, 0x99,
+ 0x00, 0xa8, 0x00, 0xa2, 0x00, 0xb5, 0x00, 0xa2,
+ 0x00, 0xb5, 0x00, 0x04, 0x01, 0x68, 0x61, 0x79,
+ 0x20, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x00, 0x54,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x6d, 0x75, 0x73,
+ 0x74, 0x20, 0x62, 0x65, 0x20, 0x73, 0x6f, 0x6d,
+ 0x65, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x6d,
+ 0x65, 0x74, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x73,
+ 0x69, 0x64, 0x65, 0x2c, 0x00, 0x49, 0x20, 0x63,
+ 0x61, 0x6e, 0x20, 0x73, 0x65, 0x65, 0x20, 0x69,
+ 0x74, 0x20, 0x67, 0x6c, 0x69, 0x74, 0x74, 0x65,
+ 0x72, 0x69, 0x6e, 0x67, 0x21, 0x00, 0x00, 0x0b,
+ 0x6a, 0x00, 0x94, 0x00, 0x7d, 0x00, 0xb3, 0x00,
+ 0x81, 0x00, 0xbf, 0x00, 0x81, 0x00, 0xbf, 0x00,
+ 0x04, 0x01, 0x72, 0x61, 0x6b, 0x65, 0x00, 0x49,
+ 0x74, 0x27, 0x73, 0x20, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x6f, 0x6c, 0x64, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61,
+ 0x72, 0x65, 0x6e, 0x27, 0x74, 0x00, 0x6d, 0x61,
+ 0x6e, 0x79, 0x20, 0x74, 0x65, 0x65, 0x74, 0x68,
+ 0x20, 0x6c, 0x65, 0x66, 0x74, 0x2e, 0x00, 0x00,
+ 0x0c, 0xa2, 0x00, 0x73, 0x00, 0xb6, 0x00, 0x80,
+ 0x00, 0xec, 0x00, 0x8e, 0x00, 0xec, 0x00, 0x8e,
+ 0x00, 0x04, 0x01, 0x6d, 0x6f, 0x75, 0x73, 0x65,
+ 0x20, 0x68, 0x6f, 0x6c, 0x65, 0x00, 0x48, 0x6f,
+ 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70,
+ 0x61, 0x6e, 0x74, 0x72, 0x79, 0x20, 0x69, 0x6e,
+ 0x20, 0x6f, 0x6e, 0x65, 0x2e, 0x2e, 0x2e, 0x00,
+ 0x00, 0x0d, 0xa5, 0x00, 0x5c, 0x00, 0xbf, 0x00,
+ 0x80, 0x00, 0xec, 0x00, 0x8e, 0x00, 0xec, 0x00,
+ 0x8e, 0x00, 0x04, 0x01, 0x68, 0x61, 0x79, 0x20,
+ 0x73, 0x74, 0x61, 0x63, 0x6b, 0x00, 0x54, 0x68,
+ 0x65, 0x72, 0x65, 0x27, 0x73, 0x20, 0x61, 0x20,
+ 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x20, 0x68, 0x6f,
+ 0x6c, 0x65, 0x20, 0x69, 0x6e, 0x73, 0x69, 0x64,
+ 0x65, 0x21, 0x00, 0x00, 0x0e, 0xae, 0x00, 0xbc,
+ 0x00, 0xb4, 0x00, 0xc2, 0x00, 0xa1, 0x00, 0xc3,
+ 0x00, 0xa1, 0x00, 0xc3, 0x00, 0x02, 0x00, 0x66,
+ 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x00, 0x49,
+ 0x74, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x68,
+ 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6e,
+ 0x20, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64,
+ 0x20, 0x62, 0x79, 0x20, 0x68, 0x65, 0x6e, 0x2e,
+ 0x00, 0x00, 0x0f, 0x51, 0x00, 0x89, 0x00, 0x70,
+ 0x00, 0xb6, 0x00, 0x84, 0x00, 0xbe, 0x00, 0x84,
+ 0x00, 0xbe, 0x00, 0x04, 0x01, 0x68, 0x61, 0x79,
+ 0x20, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x00, 0x01,
+ 0x10, 0x04, 0x01, 0x0d, 0x00, 0x3f, 0x01, 0x5d,
+ 0x00, 0xe8, 0x00, 0x86, 0x00, 0xe8, 0x00, 0x86,
+ 0x00, 0x02, 0x01, 0x6d, 0x61, 0x6e, 0x73, 0x69,
+ 0x6f, 0x6e, 0x00, 0x47, 0x65, 0x65, 0x2c, 0x20,
+ 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x70, 0x65, 0x6f,
+ 0x70, 0x6c, 0x65, 0x20, 0x72, 0x65, 0x61, 0x6c,
+ 0x6c, 0x79, 0x00, 0x68, 0x61, 0x76, 0x65, 0x20,
+ 0x6e, 0x6f, 0x20, 0x74, 0x61, 0x73, 0x74, 0x65,
+ 0x2e, 0x00, 0x00, 0xca, 0xa3, 0x0d, 0xa4, 0x3e,
+ 0xa4, 0x57, 0xa4, 0x00, 0x00, 0x01, 0x55, 0x00,
+ 0x35, 0x00, 0x79, 0x00, 0x56, 0x00, 0x67, 0x00,
+ 0x8f, 0x00, 0x67, 0x00, 0x8f, 0x00, 0x01, 0x01,
+ 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x00, 0x54,
+ 0x68, 0x65, 0x72, 0x65, 0x27, 0x73, 0x20, 0x61,
+ 0x20, 0x73, 0x68, 0x75, 0x74, 0x74, 0x65, 0x72,
+ 0x2c, 0x20, 0x49, 0x20, 0x63, 0x61, 0x6e, 0x27,
+ 0x74, 0x20, 0x73, 0x65, 0x65, 0x20, 0x61, 0x20,
+ 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2e, 0x00, 0x00,
+ 0x02, 0xaa, 0x00, 0x63, 0x00, 0xbd, 0x00, 0x7b,
+ 0x00, 0x8f, 0x00, 0x8f, 0x00, 0x8f, 0x00, 0x8f,
+ 0x00, 0x02, 0x01, 0x73, 0x63, 0x75, 0x6c, 0x70,
+ 0x74, 0x75, 0x72, 0x65, 0x00, 0x54, 0x68, 0x65,
+ 0x20, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x20, 0x69,
+ 0x73, 0x20, 0x73, 0x69, 0x63, 0x6b, 0x2e, 0x00,
+ 0x00, 0x03, 0xc6, 0x00, 0x53, 0x00, 0xf0, 0x00,
+ 0xa4, 0x00, 0xaa, 0x00, 0x99, 0x00, 0xd1, 0x00,
+ 0x99, 0x00, 0x02, 0x01, 0x64, 0x6f, 0x6f, 0x72,
+ 0x00, 0x01, 0x04, 0x00, 0x00, 0x8b, 0x00, 0x22,
+ 0x00, 0xc7, 0x00, 0x42, 0x00, 0xa7, 0x00, 0x42,
+ 0x00, 0xa7, 0x00, 0x04, 0x01, 0x77, 0x61, 0x79,
+ 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x73,
+ 0x69, 0x6f, 0x6e, 0x00, 0x01, 0x92, 0xa4, 0xab,
+ 0xa4, 0xc4, 0xa4, 0x09, 0xa5, 0x3d, 0xa5, 0x8e,
+ 0xa5, 0xbd, 0xa5, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x5b, 0x00, 0x1a, 0x00, 0xae, 0x00, 0x2b, 0x00,
+ 0xaa, 0x00, 0x2b, 0x00, 0xaa, 0x00, 0x04, 0x01,
+ 0x64, 0x6f, 0x6f, 0x72, 0x00, 0x01, 0x02, 0xe8,
+ 0x00, 0x5b, 0x00, 0x17, 0x01, 0xa8, 0x00, 0xff,
+ 0x00, 0xb2, 0x00, 0xff, 0x00, 0xa6, 0x00, 0x01,
+ 0x01, 0x64, 0x6f, 0x6f, 0x72, 0x00, 0x01, 0x03,
+ 0x2b, 0x00, 0x74, 0x00, 0x4f, 0x00, 0xae, 0x00,
+ 0x3e, 0x00, 0xb7, 0x00, 0x3e, 0x00, 0xb7, 0x00,
+ 0x01, 0x01, 0x66, 0x6c, 0x6f, 0x77, 0x65, 0x72,
+ 0x73, 0x00, 0x53, 0x75, 0x72, 0x70, 0x72, 0x69,
+ 0x73, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x72, 0x70,
+ 0x72, 0x69, 0x73, 0x65, 0x2c, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x61, 0x72, 0x65, 0x6e, 0x27,
+ 0x74, 0x00, 0x70, 0x6c, 0x61, 0x73, 0x74, 0x69,
+ 0x63, 0x2e, 0x00, 0x00, 0x04, 0x82, 0x00, 0x32,
+ 0x00, 0xab, 0x00, 0x69, 0x00, 0xa2, 0x00, 0xad,
+ 0x00, 0xa2, 0x00, 0xad, 0x00, 0x01, 0x01, 0x70,
+ 0x6c, 0x61, 0x6e, 0x74, 0x00, 0x48, 0x6f, 0x77,
+ 0x27, 0x73, 0x20, 0x69, 0x74, 0x20, 0x68, 0x61,
+ 0x6e, 0x67, 0x69, 0x6e, 0x27, 0x2c, 0x20, 0x52,
+ 0x6f, 0x62, 0x62, 0x69, 0x65, 0x3f, 0x00, 0x00,
+ 0x05, 0x1e, 0x00, 0x49, 0x00, 0x9d, 0x00, 0xa8,
+ 0x00, 0xa2, 0x00, 0xad, 0x00, 0xa2, 0x00, 0xad,
+ 0x00, 0x01, 0x01, 0x73, 0x74, 0x61, 0x69, 0x72,
+ 0x73, 0x00, 0x54, 0x68, 0x65, 0x79, 0x20, 0x73,
+ 0x61, 0x79, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x73, 0x74, 0x65, 0x70, 0x20, 0x6d, 0x61,
+ 0x6b, 0x65, 0x73, 0x20, 0x79, 0x6f, 0x75, 0x72,
+ 0x20, 0x6c, 0x69, 0x66, 0x65, 0x00, 0x33, 0x20,
+ 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x20,
+ 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x2e, 0x00,
+ 0x00, 0x06, 0x1f, 0x01, 0xa8, 0x00, 0x3f, 0x01,
+ 0xc7, 0x00, 0x18, 0x01, 0xbc, 0x00, 0x3f, 0x01,
+ 0xbc, 0x00, 0x02, 0x01, 0x6f, 0x74, 0x68, 0x65,
+ 0x72, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f,
+ 0x72, 0x72, 0x69, 0x64, 0x6f, 0x72, 0x00, 0x01,
+ 0x07, 0x00, 0x00, 0xc0, 0x00, 0x3f, 0x01, 0xc7,
+ 0x00, 0xa0, 0x00, 0xbc, 0x00, 0xa0, 0x00, 0xc7,
+ 0x00, 0x03, 0x01, 0x77, 0x61, 0x79, 0x20, 0x74,
+ 0x6f, 0x20, 0x70, 0x6f, 0x72, 0x63, 0x68, 0x00,
+ 0x01, 0x00, 0xa6, 0x1f, 0xa6, 0x4d, 0xa6, 0x84,
+ 0xa6, 0xd4, 0xa6, 0xee, 0xa6, 0x11, 0xa7, 0x51,
+ 0xa7, 0x72, 0xa7, 0x8b, 0xa7, 0xb3, 0xa7, 0xdb,
+ 0xa7, 0x03, 0xa8, 0x2b, 0xa8, 0x53, 0xa8, 0x7b,
+ 0xa8, 0x00, 0x00, 0x01, 0x00, 0x00, 0x78, 0x00,
+ 0x51, 0x00, 0x9c, 0x00, 0x12, 0x00, 0x9f, 0x00,
+ 0x12, 0x00, 0x9f, 0x00, 0x01, 0x01, 0x64, 0x6f,
+ 0x77, 0x6e, 0x73, 0x74, 0x61, 0x69, 0x72, 0x73,
+ 0x00, 0x01, 0x02, 0x14, 0x00, 0x3f, 0x00, 0x55,
+ 0x00, 0x6a, 0x00, 0x34, 0x00, 0xa5, 0x00, 0x34,
+ 0x00, 0xa5, 0x00, 0x01, 0x01, 0x70, 0x69, 0x63,
+ 0x74, 0x75, 0x72, 0x65, 0x00, 0x49, 0x74, 0x27,
+ 0x73, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x63,
+ 0x61, 0x73, 0x74, 0x6c, 0x65, 0x2e, 0x00, 0x00,
+ 0x03, 0x29, 0x01, 0x5f, 0x00, 0x3f, 0x01, 0xb0,
+ 0x00, 0x0f, 0x01, 0xae, 0x00, 0x0f, 0x01, 0xae,
+ 0x00, 0x02, 0x01, 0x61, 0x72, 0x6d, 0x6f, 0x75,
+ 0x72, 0x00, 0x54, 0x68, 0x65, 0x20, 0x62, 0x65,
+ 0x74, 0x61, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69,
+ 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20,
+ 0x74, 0x61, 0x6e, 0x6b, 0x2e, 0x00, 0x00, 0x04,
+ 0xcf, 0x00, 0x63, 0x00, 0xda, 0x00, 0x67, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x20,
+ 0x74, 0x61, 0x70, 0x65, 0x00, 0x57, 0x68, 0x61,
+ 0x74, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x20, 0x6f,
+ 0x66, 0x20, 0x6d, 0x6f, 0x76, 0x69, 0x65, 0x20,
+ 0x6d, 0x75, 0x73, 0x74, 0x20, 0x69, 0x74, 0x20,
+ 0x62, 0x65, 0x00, 0x68, 0x69, 0x64, 0x64, 0x65,
+ 0x6e, 0x20, 0x73, 0x6f, 0x20, 0x77, 0x65, 0x6c,
+ 0x6c, 0x3f, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x05,
+ 0xc3, 0x00, 0x54, 0x00, 0xc7, 0x00, 0x5d, 0x00,
+ 0xd0, 0x00, 0x97, 0x00, 0xd0, 0x00, 0x97, 0x00,
+ 0x01, 0x01, 0x62, 0x6f, 0x6f, 0x6b, 0x00, 0x00,
+ 0x00, 0x06, 0x6f, 0x00, 0x2f, 0x00, 0x3f, 0x01,
+ 0x6e, 0x00, 0xdd, 0x00, 0x9b, 0x00, 0xdd, 0x00,
+ 0x9b, 0x00, 0x01, 0x01, 0x62, 0x6f, 0x6f, 0x6b,
+ 0x73, 0x00, 0x4f, 0x68, 0x2c, 0x20, 0x62, 0x6f,
+ 0x79, 0x21, 0x00, 0x00, 0x07, 0xd5, 0x00, 0xab,
+ 0x00, 0xe3, 0x00, 0xbd, 0x00, 0xea, 0x00, 0xbd,
+ 0x00, 0xea, 0x00, 0xbd, 0x00, 0x04, 0x01, 0x74,
+ 0x72, 0x61, 0x73, 0x68, 0x20, 0x63, 0x61, 0x6e,
+ 0x00, 0x54, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61,
+ 0x72, 0x65, 0x20, 0x61, 0x20, 0x6c, 0x6f, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x70, 0x61, 0x70, 0x65,
+ 0x72, 0x73, 0x20, 0x69, 0x6e, 0x73, 0x69, 0x64,
+ 0x65, 0x2e, 0x00, 0x00, 0x08, 0x98, 0x00, 0x8d,
+ 0x00, 0xb2, 0x00, 0xc1, 0x00, 0xa5, 0x00, 0xc6,
+ 0x00, 0xa5, 0x00, 0xc6, 0x00, 0x01, 0x01, 0x63,
+ 0x68, 0x61, 0x69, 0x72, 0x00, 0x53, 0x6f, 0x66,
+ 0x74, 0x79, 0x2e, 0x00, 0x00, 0x09, 0x87, 0x00,
+ 0x86, 0x00, 0xa2, 0x00, 0x99, 0x00, 0x88, 0x00,
+ 0xc1, 0x00, 0x88, 0x00, 0xc1, 0x00, 0x01, 0x01,
+ 0x6c, 0x61, 0x6d, 0x70, 0x00, 0x01, 0x0a, 0x7c,
+ 0x00, 0x9e, 0x00, 0x95, 0x00, 0xa6, 0x00, 0x88,
+ 0x00, 0xc1, 0x00, 0x88, 0x00, 0xc1, 0x00, 0x01,
+ 0x01, 0x64, 0x72, 0x61, 0x77, 0x65, 0x72, 0x00,
+ 0x49, 0x74, 0x27, 0x73, 0x20, 0x63, 0x6c, 0x6f,
+ 0x73, 0x65, 0x64, 0x2e, 0x00, 0x00, 0x0b, 0x7c,
+ 0x00, 0xa8, 0x00, 0x95, 0x00, 0xaf, 0x00, 0x88,
+ 0x00, 0xc1, 0x00, 0x88, 0x00, 0xc1, 0x00, 0x01,
+ 0x01, 0x64, 0x72, 0x61, 0x77, 0x65, 0x72, 0x00,
+ 0x49, 0x74, 0x27, 0x73, 0x20, 0x63, 0x6c, 0x6f,
+ 0x73, 0x65, 0x64, 0x2e, 0x00, 0x00, 0x0c, 0x7c,
+ 0x00, 0xb1, 0x00, 0x95, 0x00, 0xb8, 0x00, 0x88,
+ 0x00, 0xc1, 0x00, 0x88, 0x00, 0xc1, 0x00, 0x01,
+ 0x01, 0x64, 0x72, 0x61, 0x77, 0x65, 0x72, 0x00,
+ 0x49, 0x74, 0x27, 0x73, 0x20, 0x63, 0x6c, 0x6f,
+ 0x73, 0x65, 0x64, 0x2e, 0x00, 0x00, 0x0d, 0xb6,
+ 0x00, 0x9e, 0x00, 0xd0, 0x00, 0xa6, 0x00, 0xc4,
+ 0x00, 0xc0, 0x00, 0xc4, 0x00, 0xc0, 0x00, 0x01,
+ 0x01, 0x64, 0x72, 0x61, 0x77, 0x65, 0x72, 0x00,
+ 0x49, 0x74, 0x27, 0x73, 0x20, 0x63, 0x6c, 0x6f,
+ 0x73, 0x65, 0x64, 0x2e, 0x00, 0x00, 0x0e, 0xb6,
+ 0x00, 0xa8, 0x00, 0xd0, 0x00, 0xaf, 0x00, 0xc4,
+ 0x00, 0xc0, 0x00, 0xc4, 0x00, 0xc0, 0x00, 0x01,
+ 0x01, 0x64, 0x72, 0x61, 0x77, 0x65, 0x72, 0x00,
+ 0x49, 0x74, 0x27, 0x73, 0x20, 0x63, 0x6c, 0x6f,
+ 0x73, 0x65, 0x64, 0x2e, 0x00, 0x00, 0x0f, 0xb6,
+ 0x00, 0xb1, 0x00, 0xd0, 0x00, 0xb8, 0x00, 0xc4,
+ 0x00, 0xc0, 0x00, 0xc4, 0x00, 0xc0, 0x00, 0x01,
+ 0x01, 0x64, 0x72, 0x61, 0x77, 0x65, 0x72, 0x00,
+ 0x49, 0x74, 0x27, 0x73, 0x20, 0x63, 0x6c, 0x6f,
+ 0x73, 0x65, 0x64, 0x2e, 0x00, 0x00, 0x10, 0xf3,
+ 0x00, 0x71, 0x00, 0x18, 0x01, 0x98, 0x00, 0x06,
+ 0x01, 0x9e, 0x00, 0x06, 0x01, 0x9e, 0x00, 0x01,
+ 0x01, 0x6c, 0x61, 0x64, 0x64, 0x65, 0x72, 0x00,
+ 0x49, 0x6e, 0x64, 0x69, 0x73, 0x70, 0x65, 0x6e,
+ 0x73, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x61, 0x64,
+ 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74,
+ 0x6f, 0x20, 0x67, 0x69, 0x72, 0x6c, 0x73, 0x20,
+ 0x69, 0x6e, 0x20, 0x73, 0x6b, 0x69, 0x72, 0x74,
+ 0x73, 0x2e, 0x00, 0x00, 0xd5, 0xa8, 0xee, 0xa8,
+ 0x1e, 0xa9, 0x58, 0xa9, 0x96, 0xa9, 0xcc, 0xa9,
+ 0xf4, 0xa9, 0x1f, 0xaa, 0x38, 0xaa, 0x00, 0x00,
+ 0x01, 0x73, 0x00, 0x5b, 0x00, 0xa3, 0x00, 0xa7,
+ 0x00, 0x8c, 0x00, 0xac, 0x00, 0x8c, 0x00, 0xa6,
+ 0x00, 0x01, 0x01, 0x64, 0x6f, 0x6f, 0x72, 0x00,
+ 0x01, 0x02, 0x36, 0x01, 0x8c, 0x00, 0x3b, 0x01,
+ 0x91, 0x00, 0x2c, 0x01, 0xb2, 0x00, 0x2c, 0x01,
+ 0xb2, 0x00, 0x02, 0x01, 0x68, 0x6f, 0x6c, 0x65,
+ 0x00, 0x49, 0x74, 0x20, 0x68, 0x61, 0x73, 0x20,
+ 0x61, 0x20, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65,
+ 0x20, 0x73, 0x68, 0x61, 0x70, 0x65, 0x2e, 0x00,
+ 0x00, 0x03, 0x31, 0x01, 0x8b, 0x00, 0x3b, 0x01,
+ 0x91, 0x00, 0x2c, 0x01, 0xb2, 0x00, 0x2c, 0x01,
+ 0xb2, 0x00, 0x02, 0x00, 0x68, 0x61, 0x6e, 0x64,
+ 0x6c, 0x65, 0x00, 0x49, 0x74, 0x20, 0x66, 0x69,
+ 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x68, 0x6f, 0x6c, 0x65, 0x20, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x63, 0x74, 0x6c, 0x79,
+ 0x2e, 0x00, 0x00, 0x04, 0x04, 0x00, 0x3f, 0x00,
+ 0x64, 0x00, 0x61, 0x00, 0x3b, 0x00, 0xb2, 0x00,
+ 0x3b, 0x00, 0xb2, 0x00, 0x01, 0x01, 0x70, 0x69,
+ 0x63, 0x74, 0x75, 0x72, 0x65, 0x00, 0x49, 0x20,
+ 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x20, 0x6c,
+ 0x69, 0x6b, 0x65, 0x64, 0x20, 0x53, 0x60, 0x54,
+ 0x60, 0x41, 0x60, 0x52, 0x60, 0x20, 0x57, 0x60,
+ 0x41, 0x60, 0x52, 0x60, 0x53, 0x60, 0x2e, 0x00,
+ 0x00, 0x05, 0xd8, 0x00, 0x4d, 0x00, 0x09, 0x01,
+ 0x79, 0x00, 0xf3, 0x00, 0xb5, 0x00, 0xf3, 0x00,
+ 0xb5, 0x00, 0x01, 0x01, 0x70, 0x69, 0x63, 0x74,
+ 0x75, 0x72, 0x65, 0x00, 0x41, 0x6e, 0x64, 0x20,
+ 0x49, 0x20, 0x74, 0x6f, 0x75, 0x67, 0x68, 0x74,
+ 0x20, 0x49, 0x20, 0x77, 0x61, 0x73, 0x20, 0x77,
+ 0x65, 0x69, 0x72, 0x64, 0x2e, 0x00, 0x00, 0x06,
+ 0xf3, 0x00, 0x91, 0x00, 0x15, 0x01, 0xc7, 0x00,
+ 0xf3, 0x00, 0xb5, 0x00, 0xf3, 0x00, 0xb5, 0x00,
+ 0x03, 0x01, 0x66, 0x6c, 0x6f, 0x77, 0x65, 0x72,
+ 0x73, 0x00, 0x4e, 0x69, 0x63, 0x65, 0x20, 0x73,
+ 0x6d, 0x65, 0x6c, 0x6c, 0x2e, 0x00, 0x00, 0x07,
+ 0x00, 0x00, 0xa8, 0x00, 0x1a, 0x00, 0xc7, 0x00,
+ 0x28, 0x00, 0xbc, 0x00, 0x00, 0x00, 0xbc, 0x00,
+ 0x04, 0x01, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20,
+ 0x63, 0x6f, 0x72, 0x72, 0x69, 0x64, 0x6f, 0x72,
+ 0x00, 0x01, 0x08, 0x25, 0x01, 0x5f, 0x00, 0x3f,
+ 0x01, 0xb6, 0x00, 0x11, 0x01, 0xab, 0x00, 0x11,
+ 0x01, 0xab, 0x00, 0x02, 0x01, 0x64, 0x6f, 0x6f,
+ 0x72, 0x00, 0x01, 0x09, 0x0e, 0x00, 0x5a, 0x00,
+ 0x32, 0x00, 0xb0, 0x00, 0x28, 0x00, 0xbc, 0x00,
+ 0x28, 0x00, 0xbc, 0x00, 0x01, 0x01, 0x73, 0x74,
+ 0x61, 0x74, 0x75, 0x65, 0x00, 0x42, 0x69, 0x7a,
+ 0x61, 0x72, 0x72, 0x65, 0x2e, 0x00, 0x00, 0x6e,
+ 0xaa, 0x9a, 0xaa, 0xcd, 0xaa, 0x12, 0xab, 0x5d,
+ 0xab, 0x79, 0xab, 0x92, 0xab, 0xda, 0xab, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x52, 0x00, 0xb6, 0x00, 0x52, 0x00,
+ 0xb6, 0x00, 0x01, 0x01, 0x72, 0x6f, 0x62, 0x6f,
+ 0x74, 0x00, 0x49, 0x6d, 0x70, 0x72, 0x65, 0x73,
+ 0x73, 0x69, 0x76, 0x65, 0x2e, 0x00, 0x00, 0x4d,
+ 0x69, 0x6b, 0x65, 0x00, 0xff, 0x02, 0x2d, 0x00,
+ 0x75, 0x00, 0x37, 0x00, 0x83, 0x00, 0x33, 0x00,
+ 0xaa, 0x00, 0x33, 0x00, 0xaa, 0x00, 0x01, 0x00,
+ 0x6a, 0x61, 0x72, 0x00, 0x54, 0x68, 0x69, 0x73,
+ 0x20, 0x6a, 0x61, 0x72, 0x20, 0x69, 0x73, 0x20,
+ 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x6f, 0x66, 0x20,
+ 0x70, 0x69, 0x6c, 0x6c, 0x73, 0x2e, 0x00, 0x00,
+ 0x03, 0x2d, 0x00, 0x75, 0x00, 0x37, 0x00, 0x83,
+ 0x00, 0x33, 0x00, 0xaa, 0x00, 0x33, 0x00, 0xaa,
+ 0x00, 0x01, 0x00, 0x62, 0x6f, 0x6f, 0x6b, 0x00,
+ 0x49, 0x74, 0x27, 0x73, 0x20, 0x62, 0x69, 0x67,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x6f,
+ 0x6b, 0x73, 0x00, 0x6c, 0x69, 0x6b, 0x65, 0x20,
+ 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x6b, 0x69, 0x6e,
+ 0x64, 0x20, 0x6f, 0x66, 0x00, 0x64, 0x69, 0x61,
+ 0x72, 0x79, 0x2e, 0x00, 0x00, 0x04, 0x74, 0x00,
+ 0x2d, 0x00, 0xb9, 0x00, 0x7e, 0x00, 0x98, 0x00,
+ 0xa5, 0x00, 0x98, 0x00, 0xa5, 0x00, 0x01, 0x01,
+ 0x70, 0x69, 0x63, 0x74, 0x75, 0x72, 0x65, 0x00,
+ 0x54, 0x68, 0x61, 0x74, 0x20, 0x6f, 0x6e, 0x65,
+ 0x27, 0x73, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74,
+ 0x2e, 0x20, 0x49, 0x27, 0x64, 0x20, 0x6c, 0x69,
+ 0x6b, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6d,
+ 0x79, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x00, 0x00,
+ 0x05, 0x88, 0x00, 0x88, 0x00, 0xa5, 0x00, 0x9f,
+ 0x00, 0x98, 0x00, 0xa5, 0x00, 0x98, 0x00, 0xa5,
+ 0x00, 0x01, 0x01, 0x63, 0x61, 0x62, 0x69, 0x6e,
+ 0x65, 0x74, 0x00, 0x01, 0x06, 0x4e, 0x00, 0xbd,
+ 0x00, 0xe0, 0x00, 0xc7, 0x00, 0x8b, 0x00, 0xbc,
+ 0x00, 0x8b, 0x00, 0xc7, 0x00, 0x03, 0x01, 0x65,
+ 0x78, 0x69, 0x74, 0x00, 0x01, 0x07, 0x00, 0x00,
+ 0xc7, 0x00, 0x4d, 0x00, 0xc7, 0x00, 0x8b, 0x00,
+ 0xbc, 0x00, 0x39, 0x00, 0xc6, 0x00, 0x03, 0x00,
+ 0x6c, 0x65, 0x66, 0x74, 0x20, 0x6c, 0x6f, 0x77,
+ 0x65, 0x72, 0x20, 0x65, 0x64, 0x67, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x73, 0x63, 0x72, 0x65, 0x65,
+ 0x6e, 0x00, 0x49, 0x20, 0x63, 0x6f, 0x75, 0x6c,
+ 0x64, 0x20, 0x74, 0x72, 0x79, 0x20, 0x74, 0x6f,
+ 0x20, 0x68, 0x69, 0x64, 0x65, 0x20, 0x68, 0x65,
+ 0x72, 0x65, 0x21, 0x00, 0x00, 0x08, 0x89, 0x00,
+ 0x7e, 0x00, 0x93, 0x00, 0x85, 0x00, 0x8f, 0x00,
+ 0xa3, 0x00, 0x8f, 0x00, 0xa3, 0x00, 0x01, 0x00,
+ 0x64, 0x6f, 0x6f, 0x72, 0x20, 0x68, 0x61, 0x6e,
+ 0x64, 0x6c, 0x65, 0x00, 0x4a, 0x6f, 0x68, 0x6e,
+ 0x20, 0x4e, 0x6f, 0x74, 0x79, 0x20, 0x6c, 0x65,
+ 0x66, 0x74, 0x20, 0x69, 0x74, 0x20, 0x68, 0x65,
+ 0x72, 0x65, 0x2e, 0x00, 0x00, 0x2c, 0xac, 0x6b,
+ 0xac, 0xb8, 0xac, 0xe3, 0xac, 0xff, 0xac, 0x43,
+ 0xad, 0x8d, 0xad, 0xcc, 0xad, 0x1d, 0xae, 0x6e,
+ 0xae, 0xbe, 0xae, 0xf8, 0xae, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x8d, 0x00, 0x9f, 0x00, 0x8d, 0x00, 0x9f, 0x00,
+ 0x04, 0x01, 0x63, 0x6f, 0x6f, 0x6b, 0x00, 0x48,
+ 0x65, 0x27, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x70,
+ 0x6c, 0x65, 0x74, 0x65, 0x6c, 0x79, 0x20, 0x61,
+ 0x64, 0x64, 0x69, 0x63, 0x74, 0x65, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77,
+ 0x6f, 0x72, 0x6b, 0x2e, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x04,
+ 0x01, 0x73, 0x74, 0x65, 0x77, 0x00, 0x49, 0x74,
+ 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65,
+ 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x6b, 0x69,
+ 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x6f,
+ 0x75, 0x70, 0x2e, 0x00, 0x4e, 0x6f, 0x77, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x65, 0x78, 0x74,
+ 0x72, 0x61, 0x20, 0x70, 0x6f, 0x77, 0x65, 0x72,
+ 0x2e, 0x00, 0x00, 0x03, 0x26, 0x00, 0x84, 0x00,
+ 0x30, 0x00, 0x8e, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x04, 0x01, 0x68, 0x6f,
+ 0x74, 0x20, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x00,
+ 0x54, 0x68, 0x61, 0x74, 0x27, 0x73, 0x20, 0x43,
+ 0x4f, 0x4f, 0x4c, 0x2e, 0x00, 0x00, 0x04, 0x1c,
+ 0x01, 0x9c, 0x00, 0x3f, 0x01, 0xc7, 0x00, 0x0b,
+ 0x01, 0xb2, 0x00, 0x3f, 0x01, 0xb2, 0x00, 0x02,
+ 0x01, 0x77, 0x61, 0x79, 0x20, 0x6f, 0x75, 0x74,
+ 0x00, 0x01, 0x05, 0x9e, 0x00, 0x7f, 0x00, 0xc1,
+ 0x00, 0x9b, 0x00, 0xc0, 0x00, 0xa0, 0x00, 0xc0,
+ 0x00, 0xa0, 0x00, 0x01, 0x01, 0x72, 0x65, 0x66,
+ 0x72, 0x69, 0x67, 0x65, 0x72, 0x61, 0x74, 0x6f,
+ 0x72, 0x00, 0x4d, 0x79, 0x20, 0x66, 0x61, 0x76,
+ 0x6f, 0x75, 0x72, 0x69, 0x74, 0x65, 0x20, 0x74,
+ 0x68, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6b, 0x69, 0x74, 0x63,
+ 0x68, 0x65, 0x6e, 0x2e, 0x00, 0x00, 0x06, 0x81,
+ 0x00, 0x74, 0x00, 0x9c, 0x00, 0x7c, 0x00, 0x8d,
+ 0x00, 0x9f, 0x00, 0x8d, 0x00, 0x9f, 0x00, 0x01,
+ 0x01, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x00, 0x49,
+ 0x74, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x62, 0x61, 0x74,
+ 0x74, 0x65, 0x72, 0x69, 0x65, 0x73, 0x2e, 0x20,
+ 0x4a, 0x75, 0x73, 0x74, 0x20, 0x6c, 0x69, 0x6b,
+ 0x65, 0x00, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x6c, 0x6b, 0x6d, 0x61, 0x6e, 0x2e, 0x00, 0x00,
+ 0x07, 0xdb, 0x00, 0x70, 0x00, 0xe0, 0x00, 0x7c,
+ 0x00, 0xdd, 0x00, 0xa0, 0x00, 0xdd, 0x00, 0xa0,
+ 0x00, 0x01, 0x01, 0x63, 0x68, 0x69, 0x6c, 0x6c,
+ 0x69, 0x00, 0x49, 0x74, 0x27, 0x73, 0x20, 0x72,
+ 0x65, 0x64, 0x2c, 0x20, 0x69, 0x74, 0x27, 0x73,
+ 0x20, 0x68, 0x6f, 0x74, 0x2c, 0x20, 0x69, 0x74,
+ 0x27, 0x73, 0x20, 0x2e, 0x2e, 0x2e, 0x43, 0x48,
+ 0x49, 0x4c, 0x4c, 0x49, 0x21, 0x00, 0x00, 0x08,
+ 0xd5, 0x00, 0x77, 0x00, 0xe6, 0x00, 0x7e, 0x00,
+ 0xdd, 0x00, 0xa0, 0x00, 0xdd, 0x00, 0xa0, 0x00,
+ 0x01, 0x00, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20,
+ 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x63, 0x68,
+ 0x69, 0x6c, 0x6c, 0x69, 0x20, 0x62, 0x6f, 0x74,
+ 0x74, 0x6c, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x6f,
+ 0x64, 0x00, 0x49, 0x74, 0x27, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65,
+ 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x2e, 0x2e,
+ 0x2e, 0x20, 0x65, 0x74, 0x63, 0x2e, 0x00, 0x00,
+ 0x09, 0x23, 0x01, 0x77, 0x00, 0x2f, 0x01, 0x7e,
+ 0x00, 0x28, 0x01, 0xa0, 0x00, 0x28, 0x01, 0xa0,
+ 0x00, 0x01, 0x01, 0x70, 0x61, 0x73, 0x74, 0x72,
+ 0x79, 0x20, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
+ 0x00, 0x4d, 0x65, 0x6e, 0x20, 0x75, 0x73, 0x65,
+ 0x20, 0x67, 0x75, 0x6e, 0x73, 0x2e, 0x20, 0x57,
+ 0x6f, 0x6d, 0x65, 0x6e, 0x20, 0x75, 0x73, 0x65,
+ 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x00, 0x31,
+ 0x20, 0x3a, 0x20, 0x30, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x77, 0x6f, 0x6d, 0x65, 0x6e, 0x2e, 0x00,
+ 0x00, 0x0a, 0x59, 0x00, 0x70, 0x00, 0x6d, 0x00,
+ 0x7d, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x01, 0x01, 0x6d, 0x69, 0x63, 0x72,
+ 0x6f, 0x77, 0x61, 0x76, 0x65, 0x00, 0x49, 0x74,
+ 0x27, 0x73, 0x20, 0x61, 0x20, 0x6d, 0x61, 0x67,
+ 0x69, 0x63, 0x20, 0x74, 0x6f, 0x6f, 0x6c, 0x2e,
+ 0x20, 0x49, 0x74, 0x20, 0x74, 0x75, 0x72, 0x6e,
+ 0x73, 0x00, 0x61, 0x6e, 0x79, 0x20, 0x64, 0x69,
+ 0x73, 0x68, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20,
+ 0x72, 0x75, 0x62, 0x62, 0x65, 0x72, 0x2e, 0x00,
+ 0x00, 0x0b, 0xb4, 0x00, 0x67, 0x00, 0xd5, 0x00,
+ 0x74, 0x00, 0xc7, 0x00, 0xa2, 0x00, 0xc7, 0x00,
+ 0xa2, 0x00, 0x01, 0x01, 0x6b, 0x6e, 0x69, 0x76,
+ 0x65, 0x73, 0x00, 0x41, 0x20, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63,
+ 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x63, 0x6f,
+ 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
+ 0x2e, 0x00, 0x00, 0x0c, 0xad, 0x00, 0x82, 0x00,
+ 0xb8, 0x00, 0x8c, 0x00, 0xc0, 0x00, 0xa0, 0x00,
+ 0xc0, 0x00, 0xa0, 0x00, 0x01, 0x01, 0x6d, 0x65,
+ 0x61, 0x74, 0x00, 0x49, 0x74, 0x27, 0x73, 0x20,
+ 0x69, 0x6e, 0x20, 0x61, 0x20, 0x70, 0x6c, 0x61,
+ 0x73, 0x74, 0x69, 0x63, 0x20, 0x62, 0x61, 0x67,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x68,
+ 0x61, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x7a, 0x65,
+ 0x6e, 0x20, 0x74, 0x6f, 0x00, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x68, 0x65, 0x6c, 0x66, 0x2e, 0x00,
+ 0x00, 0x56, 0xaf, 0x6f, 0xaf, 0x97, 0xaf, 0xaf,
+ 0xaf, 0xe4, 0xaf, 0x00, 0xb0, 0x29, 0xb0, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x2d, 0x00, 0x23, 0x00,
+ 0x82, 0x00, 0x34, 0x00, 0x85, 0x00, 0x28, 0x00,
+ 0x80, 0x00, 0x04, 0x01, 0x64, 0x6f, 0x6f, 0x72,
+ 0x00, 0x01, 0x02, 0x15, 0x01, 0x7d, 0x00, 0x36,
+ 0x01, 0x9e, 0x00, 0x25, 0x01, 0xa6, 0x00, 0x25,
+ 0x01, 0xa6, 0x00, 0x01, 0x01, 0x73, 0x69, 0x6e,
+ 0x6b, 0x00, 0x49, 0x74, 0x20, 0x68, 0x61, 0x73,
+ 0x20, 0x61, 0x20, 0x68, 0x6f, 0x6c, 0x65, 0x2e,
+ 0x00, 0x00, 0x03, 0x1e, 0x01, 0x70, 0x00, 0x2c,
+ 0x01, 0x7c, 0x00, 0x14, 0x01, 0x9f, 0x00, 0x14,
+ 0x01, 0x9f, 0x00, 0x02, 0x01, 0x74, 0x61, 0x70,
+ 0x00, 0x01, 0x04, 0x55, 0x00, 0x2e, 0x00, 0x76,
+ 0x00, 0x67, 0x00, 0x60, 0x00, 0x8c, 0x00, 0x60,
+ 0x00, 0x8c, 0x00, 0x01, 0x01, 0x6d, 0x69, 0x72,
+ 0x72, 0x6f, 0x72, 0x00, 0x49, 0x74, 0x27, 0x73,
+ 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64,
+ 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x6c, 0x64, 0x20,
+ 0x64, 0x69, 0x72, 0x74, 0x2e, 0x00, 0x00, 0x05,
+ 0x4a, 0x00, 0x6c, 0x00, 0x74, 0x00, 0x86, 0x00,
+ 0x62, 0x00, 0x87, 0x00, 0x62, 0x00, 0x87, 0x00,
+ 0x01, 0x01, 0x63, 0x61, 0x62, 0x69, 0x6e, 0x65,
+ 0x74, 0x00, 0x01, 0x06, 0x7a, 0x00, 0x82, 0x00,
+ 0xff, 0x00, 0xa4, 0x00, 0xc0, 0x00, 0xae, 0x00,
+ 0xc0, 0x00, 0xae, 0x00, 0x01, 0x01, 0x62, 0x61,
+ 0x74, 0x68, 0x00, 0x57, 0x68, 0x6f, 0x61, 0x21,
+ 0x20, 0x49, 0x74, 0x27, 0x73, 0x20, 0x62, 0x69,
+ 0x67, 0x21, 0x00, 0x00, 0x07, 0x34, 0x00, 0x72,
+ 0x00, 0x3a, 0x00, 0x7d, 0x00, 0x44, 0x00, 0x81,
+ 0x00, 0x44, 0x00, 0x81, 0x00, 0x04, 0x01, 0x73,
+ 0x6f, 0x63, 0x6b, 0x00, 0x49, 0x74, 0x20, 0x6d,
+ 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x4a,
+ 0x6f, 0x68, 0x6e, 0x20, 0x4e, 0x6f, 0x74, 0x79,
+ 0x27, 0x73, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x76,
+ 0xb0, 0xb4, 0xb0, 0xf9, 0xb0, 0x3b, 0xb1, 0x84,
+ 0xb1, 0xe6, 0xb1, 0x2a, 0xb2, 0x7d, 0xb2, 0xc3,
+ 0xb2, 0xdf, 0xb2, 0x1b, 0xb3, 0x6c, 0xb3, 0x00,
+ 0x00, 0x01, 0x52, 0x00, 0x8a, 0x00, 0x5e, 0x00,
+ 0x9b, 0x00, 0x68, 0x00, 0xb5, 0x00, 0x68, 0x00,
+ 0xb5, 0x00, 0x04, 0x01, 0x63, 0x6f, 0x67, 0x6e,
+ 0x61, 0x63, 0x00, 0x42, 0x6f, 0x74, 0x74, 0x6c,
+ 0x65, 0x20, 0x61, 0x73, 0x20, 0x62, 0x69, 0x67,
+ 0x20, 0x61, 0x73, 0x20, 0x4e, 0x61, 0x70, 0x6f,
+ 0x6c, 0x65, 0x6f, 0x6e, 0x20, 0x68, 0x69, 0x6d,
+ 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x00, 0x00, 0x02,
+ 0x52, 0x00, 0x8a, 0x00, 0x5e, 0x00, 0x96, 0x00,
+ 0x68, 0x00, 0xb5, 0x00, 0x68, 0x00, 0xb5, 0x00,
+ 0x04, 0x01, 0x70, 0x69, 0x6e, 0x63, 0x65, 0x72,
+ 0x73, 0x00, 0x54, 0x68, 0x65, 0x72, 0x65, 0x27,
+ 0x73, 0x20, 0x61, 0x20, 0x70, 0x61, 0x69, 0x72,
+ 0x20, 0x6f, 0x66, 0x20, 0x70, 0x69, 0x6e, 0x63,
+ 0x65, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x62, 0x75, 0x63, 0x6b, 0x65,
+ 0x74, 0x2e, 0x00, 0x00, 0x03, 0x71, 0x00, 0x27,
+ 0x00, 0x91, 0x00, 0x72, 0x00, 0x84, 0x00, 0xaf,
+ 0x00, 0x84, 0x00, 0xaf, 0x00, 0x01, 0x01, 0x6d,
+ 0x61, 0x73, 0x6b, 0x00, 0x54, 0x68, 0x69, 0x73,
+ 0x20, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6d, 0x65,
+ 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x63, 0x6f, 0x6f, 0x6c, 0x20, 0x70, 0x72,
+ 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x20,
+ 0x61, 0x72, 0x74, 0x2e, 0x00, 0x00, 0x04, 0x6c,
+ 0x00, 0x73, 0x00, 0x9e, 0x00, 0x91, 0x00, 0x87,
+ 0x00, 0xab, 0x00, 0x87, 0x00, 0xab, 0x00, 0x01,
+ 0x01, 0x54, 0x56, 0x00, 0x4f, 0x6e, 0x65, 0x20,
+ 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x69,
+ 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x6b, 0x69,
+ 0x6c, 0x6c, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20,
+ 0x74, 0x69, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64,
+ 0x00, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x61,
+ 0x6c, 0x69, 0x74, 0x79, 0x2e, 0x00, 0x00, 0x05,
+ 0x78, 0x00, 0x94, 0x00, 0x92, 0x00, 0x9a, 0x00,
+ 0x84, 0x00, 0xaf, 0x00, 0x84, 0x00, 0xaf, 0x00,
+ 0x01, 0x01, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x20,
+ 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x00, 0x49,
+ 0x74, 0x20, 0x68, 0x61, 0x73, 0x20, 0x6e, 0x6f,
+ 0x20, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x20,
+ 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
+ 0x2c, 0x00, 0x62, 0x75, 0x74, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x6e,
+ 0x27, 0x74, 0x20, 0x6d, 0x61, 0x74, 0x74, 0x65,
+ 0x72, 0x00, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x20,
+ 0x61, 0x6e, 0x79, 0x77, 0x61, 0x79, 0x2e, 0x00,
+ 0x00, 0x06, 0xb9, 0x00, 0x98, 0x00, 0xcb, 0x00,
+ 0xa4, 0x00, 0xc1, 0x00, 0xa9, 0x00, 0xc1, 0x00,
+ 0xa9, 0x00, 0x01, 0x01, 0x6e, 0x65, 0x77, 0x73,
+ 0x70, 0x61, 0x70, 0x65, 0x72, 0x00, 0x54, 0x68,
+ 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x73, 0x6f,
+ 0x6d, 0x65, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x20,
+ 0x6f, 0x66, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
+ 0x20, 0x6e, 0x65, 0x77, 0x73, 0x70, 0x61, 0x70,
+ 0x65, 0x72, 0x2e, 0x00, 0x00, 0x07, 0xd2, 0x00,
+ 0x93, 0x00, 0xe4, 0x00, 0xa0, 0x00, 0xdb, 0x00,
+ 0xaa, 0x00, 0xdb, 0x00, 0xaa, 0x00, 0x01, 0x01,
+ 0x68, 0x69, 0x2d, 0x66, 0x69, 0x00, 0x57, 0x68,
+ 0x61, 0x74, 0x20, 0x61, 0x20, 0x62, 0x61, 0x62,
+ 0x79, 0x21, 0x20, 0x49, 0x74, 0x20, 0x63, 0x6f,
+ 0x75, 0x6c, 0x64, 0x20, 0x64, 0x72, 0x69, 0x76,
+ 0x65, 0x00, 0x61, 0x6c, 0x6c, 0x20, 0x6d, 0x79,
+ 0x20, 0x6e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f,
+ 0x75, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x73, 0x61,
+ 0x6e, 0x65, 0x21, 0x2e, 0x2e, 0x2e, 0x00, 0x00,
+ 0x08, 0xc0, 0x00, 0xa4, 0x00, 0x3f, 0x01, 0xc7,
+ 0x00, 0xa5, 0x00, 0xc4, 0x00, 0xa5, 0x00, 0xc4,
+ 0x00, 0x02, 0x01, 0x63, 0x6f, 0x75, 0x63, 0x68,
+ 0x00, 0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64,
+ 0x20, 0x6e, 0x65, 0x76, 0x65, 0x72, 0x20, 0x6b,
+ 0x6e, 0x6f, 0x77, 0x20, 0x77, 0x68, 0x65, 0x72,
+ 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x6c, 0x61,
+ 0x63, 0x65, 0x00, 0x61, 0x20, 0x70, 0x69, 0x6c,
+ 0x6c, 0x6f, 0x77, 0x2e, 0x00, 0x00, 0x09, 0x00,
+ 0x00, 0xbe, 0x00, 0xbf, 0x00, 0xc7, 0x00, 0x9c,
+ 0x00, 0xbd, 0x00, 0x9c, 0x00, 0xc7, 0x00, 0x03,
+ 0x01, 0x77, 0x61, 0x79, 0x20, 0x6f, 0x75, 0x74,
+ 0x00, 0x01, 0x0a, 0xad, 0x00, 0x25, 0x00, 0x25,
+ 0x01, 0x79, 0x00, 0xdb, 0x00, 0xaa, 0x00, 0xdb,
+ 0x00, 0xaa, 0x00, 0x01, 0x01, 0x70, 0x69, 0x63,
+ 0x74, 0x75, 0x72, 0x65, 0x00, 0x54, 0x68, 0x61,
+ 0x74, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x69, 0x73,
+ 0x20, 0x72, 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x20,
+ 0x69, 0x6d, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74,
+ 0x69, 0x76, 0x65, 0x2e, 0x00, 0x00, 0x0b, 0xa1,
+ 0x00, 0xa5, 0x00, 0xac, 0x00, 0xaa, 0x00, 0x98,
+ 0x00, 0xad, 0x00, 0x98, 0x00, 0xad, 0x00, 0x02,
+ 0x00, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x20,
+ 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
+ 0x65, 0x72, 0x00, 0x49, 0x74, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e,
+ 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x65, 0x77,
+ 0x73, 0x70, 0x61, 0x70, 0x65, 0x72, 0x20, 0x70,
+ 0x61, 0x67, 0x65, 0x73, 0x2e, 0x00, 0x00, 0x0c,
+ 0x2f, 0x00, 0x4f, 0x00, 0x57, 0x00, 0xaf, 0x00,
+ 0x68, 0x00, 0xb5, 0x00, 0x64, 0x00, 0xb5, 0x00,
+ 0x04, 0x00, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x77,
+ 0x61, 0x72, 0x64, 0x72, 0x6f, 0x62, 0x65, 0x00,
+ 0x49, 0x74, 0x27, 0x73, 0x20, 0x61, 0x20, 0x73,
+ 0x65, 0x63, 0x72, 0x65, 0x74, 0x20, 0x70, 0x61,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x21, 0x00, 0x00,
+ 0xad, 0xb3, 0xc6, 0xb3, 0xdf, 0xb3, 0x00, 0x00,
+ 0x01, 0x11, 0x01, 0x72, 0x00, 0x3f, 0x01, 0xc7,
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x02, 0x01, 0x64, 0x6f, 0x6f, 0x72, 0x00,
+ 0x01, 0x02, 0x00, 0x00, 0x73, 0x00, 0x2a, 0x00,
+ 0xc7, 0x00, 0x2e, 0x00, 0xc1, 0x00, 0x2e, 0x00,
+ 0xc1, 0x00, 0x04, 0x01, 0x64, 0x6f, 0x6f, 0x72,
+ 0x00, 0x01, 0x03, 0xf2, 0x00, 0x89, 0x00, 0xf6,
+ 0x00, 0x8e, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x00, 0x01, 0x73, 0x77, 0x69,
+ 0x74, 0x63, 0x68, 0x00, 0x01, 0x00, 0x00, 0x08,
+ 0xb4, 0x4c, 0xb4, 0x74, 0xb4, 0x8d, 0xb4, 0xa6,
+ 0xb4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xa0, 0x00,
+ 0x78, 0x00, 0xa0, 0x00, 0x04, 0x01, 0x4a, 0x6f,
+ 0x68, 0x6e, 0x20, 0x4e, 0x6f, 0x74, 0x79, 0x00,
+ 0x48, 0x65, 0x27, 0x73, 0x20, 0x6f, 0x62, 0x73,
+ 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x69,
+ 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x6f, 0x6e, 0x65, 0x79, 0x2e, 0x00, 0x00, 0x02,
+ 0xcf, 0x00, 0x6c, 0x00, 0x3f, 0x01, 0xc1, 0x00,
+ 0xc1, 0x00, 0xae, 0x00, 0xc1, 0x00, 0xae, 0x00,
+ 0x02, 0x01, 0x74, 0x6f, 0x6e, 0x73, 0x20, 0x6f,
+ 0x66, 0x20, 0x67, 0x6f, 0x6c, 0x64, 0x00, 0x28,
+ 0x67, 0x75, 0x6c, 0x70, 0x29, 0x00, 0x00, 0x03,
+ 0x06, 0x00, 0x5c, 0x00, 0x24, 0x00, 0x96, 0x00,
+ 0x58, 0x00, 0xad, 0x00, 0x58, 0x00, 0xad, 0x00,
+ 0x04, 0x01, 0x73, 0x61, 0x66, 0x65, 0x00, 0x01,
+ 0x04, 0x72, 0x00, 0x5e, 0x00, 0xb0, 0x00, 0x8d,
+ 0x00, 0x8c, 0x00, 0x9e, 0x00, 0x8c, 0x00, 0x9e,
+ 0x00, 0x01, 0x01, 0x73, 0x61, 0x66, 0x65, 0x00,
+ 0x01, 0x05, 0x0b, 0x01, 0x36, 0x00, 0x1c, 0x01,
+ 0x47, 0x00, 0xc1, 0x00, 0xae, 0x00, 0xc1, 0x00,
+ 0xae, 0x00, 0x02, 0x01, 0x63, 0x61, 0x6d, 0x65,
+ 0x72, 0x61, 0x00, 0x49, 0x74, 0x20, 0x6d, 0x75,
+ 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20,
+ 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x75,
+ 0x72, 0x69, 0x74, 0x79, 0x20, 0x73, 0x79, 0x73,
+ 0x74, 0x65, 0x6d, 0x2e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x49, 0xb5, 0x4a, 0xb5, 0x4d, 0xb5, 0x4f, 0xb5,
+ 0x53, 0xb5, 0x55, 0xb5, 0x5a, 0xb5, 0x5d, 0xb5,
+ 0x61, 0xb5, 0x62, 0xb5, 0x63, 0xb5, 0x68, 0xb5,
+ 0x6c, 0xb5, 0x6f, 0xb5, 0x71, 0xb5, 0x75, 0xb5,
+ 0x7a, 0xb5, 0x7c, 0xb5, 0x7f, 0xb5, 0x82, 0xb5,
+ 0x88, 0xb5, 0x8b, 0xb5, 0x8d, 0xb5, 0x8f, 0xb5,
+ 0x93, 0xb5, 0x96, 0xb5, 0x99, 0xb5, 0xa0, 0xb5,
+ 0xa1, 0xb5, 0xa2, 0xb5, 0xaa, 0xb5, 0xac, 0xb5,
+ 0xb0, 0xb5, 0xb6, 0xb5, 0xb8, 0xb5, 0xbd, 0xb5,
+ 0xbe, 0xb5, 0xc3, 0xb5, 0xc4, 0xb5, 0xc6, 0xb5,
+ 0xc8, 0xb5, 0xcb, 0xb5, 0xff, 0x5f, 0x63, 0xff,
+ 0x00, 0xff, 0x5d, 0x00, 0x62, 0xff, 0x00, 0xff,
+ 0x54, 0x55, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
+ 0x65, 0x69, 0x00, 0xff, 0xff, 0xff, 0x00, 0x11,
+ 0x00, 0x00, 0xff, 0x0e, 0x00, 0x12, 0xff, 0x29,
+ 0x00, 0xff, 0x00, 0xff, 0x14, 0x15, 0x2b, 0xff,
+ 0x00, 0x0a, 0x0b, 0x0c, 0xff, 0x25, 0xff, 0x16,
+ 0x00, 0xff, 0x19, 0x27, 0xff, 0x02, 0x03, 0x00,
+ 0x00, 0x00, 0xff, 0x1b, 0x00, 0xff, 0x07, 0xff,
+ 0x0d, 0xff, 0x1f, 0x00, 0x30, 0xff, 0x1a, 0x2c,
+ 0xff, 0x00, 0x00, 0xff, 0x00, 0x13, 0x22, 0x00,
+ 0x26, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00,
+ 0x00, 0x00, 0xff, 0x3e, 0x3f, 0x40, 0x41, 0x00,
+ 0xff, 0x52, 0xff, 0x34, 0x3c, 0x00, 0x00, 0xff,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
+ 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x6e, 0x6f,
+ 0xff, 0x22, 0xb6, 0x24, 0xb6, 0x2e, 0xb6, 0x3a,
+ 0xb6, 0x48, 0xb6, 0x56, 0xb6, 0x6a, 0xb6, 0x7a,
+ 0xb6, 0x8c, 0xb6, 0x9a, 0xb6, 0xa2, 0xb6, 0xc0,
+ 0xb6, 0xd2, 0xb6, 0xe0, 0xb6, 0xea, 0xb6, 0xfa,
+ 0xb6, 0x00, 0xb7, 0x02, 0xb7, 0x10, 0xb7, 0x2e,
+ 0xb7, 0x4e, 0xb7, 0x66, 0xb7, 0x80, 0xb7, 0xa0,
+ 0xb7, 0xb2, 0xb7, 0xc0, 0xb7, 0xcc, 0xb7, 0xec,
+ 0xb7, 0xf4, 0xb7, 0x02, 0xb8, 0x22, 0xb8, 0x34,
+ 0xb8, 0x44, 0xb8, 0x5c, 0xb8, 0x6a, 0xb8, 0x82,
+ 0xb8, 0x88, 0xb8, 0x8a, 0xb8, 0x94, 0xb8, 0x96,
+ 0xb8, 0x98, 0xb8, 0x9a, 0xb8, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66,
+ 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x78, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xa9, 0x78, 0x00, 0x00, 0xbb, 0x78, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xcd, 0x78, 0xce, 0x78, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xe0, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7,
+ 0x78, 0xee, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xf5, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x79, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19,
+ 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x79, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x79, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x62, 0x79, 0x66, 0x79, 0x00,
+ 0x00, 0x75, 0x79, 0x87, 0x79, 0x96, 0x79, 0xa5,
+ 0x79, 0xb4, 0x79, 0xc3, 0x79, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xd2, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xe4, 0x79, 0xeb, 0x79, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd,
+ 0x79, 0x0f, 0x7a, 0x49, 0x7a, 0x5b, 0x7a, 0x6d,
+ 0x7a, 0x7f, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x7a, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xd0, 0x7a, 0xd7, 0x7a, 0x00, 0x00, 0x00,
+ 0x00, 0xde, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xf0, 0x7a, 0x00, 0x00, 0xf7, 0x7a, 0x00,
+ 0x00, 0x09, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0xb8, 0xf2, 0xb8, 0xfc, 0xb8, 0x08, 0xb9, 0x16,
+ 0xb9, 0x24, 0xb9, 0x38, 0xb9, 0x50, 0xb9, 0x62,
+ 0xb9, 0x70, 0xb9, 0x78, 0xb9, 0x96, 0xb9, 0xa8,
+ 0xb9, 0xb6, 0xb9, 0xc0, 0xb9, 0xd0, 0xb9, 0xd6,
+ 0xb9, 0xd8, 0xb9, 0xe6, 0xb9, 0x04, 0xba, 0x24,
+ 0xba, 0x3c, 0xba, 0x56, 0xba, 0x76, 0xba, 0x88,
+ 0xba, 0x96, 0xba, 0xa2, 0xba, 0xc2, 0xba, 0xca,
+ 0xba, 0xd8, 0xba, 0xf8, 0xba, 0x0a, 0xbb, 0x1a,
+ 0xbb, 0x32, 0xbb, 0x40, 0xbb, 0x58, 0xbb, 0x5e,
+ 0xbb, 0x60, 0xbb, 0x6a, 0xbb, 0x6c, 0xbb, 0x6e,
+ 0xbb, 0x70, 0xbb, 0x00, 0x00, 0xed, 0x3f, 0x07,
+ 0x40, 0x21, 0x40, 0x48, 0x40, 0x4f, 0x40, 0x56,
+ 0x40, 0x60, 0x40, 0x7a, 0x40, 0x94, 0x40, 0x95,
+ 0x41, 0x9c, 0x41, 0xc3, 0x41, 0xca, 0x41, 0xce,
+ 0x41, 0x2c, 0x42, 0x33, 0x42, 0x4d, 0x42, 0x67,
+ 0x42, 0x3a, 0x43, 0x54, 0x43, 0x6e, 0x43, 0x88,
+ 0x43, 0xb5, 0x43, 0x82, 0x44, 0xcb, 0x44, 0xfc,
+ 0x44, 0x32, 0x45, 0x39, 0x45, 0x62, 0x46, 0xaf,
+ 0x46, 0x05, 0x47, 0x94, 0x47, 0xbc, 0x47, 0xdb,
+ 0x47, 0x36, 0x48, 0x3a, 0x48, 0x44, 0x48, 0x71,
+ 0x48, 0x7e, 0x48, 0x85, 0x48, 0x8c, 0x48, 0x93,
+ 0x48, 0xd4, 0x48, 0xdb, 0x48, 0xe2, 0x48, 0xe6,
+ 0x48, 0xea, 0x48, 0x11, 0x49, 0x18, 0x49, 0x64,
+ 0x4a, 0x8c, 0x4a, 0xed, 0x4a, 0xf4, 0x4a, 0x23,
+ 0x4b, 0x27, 0x4b, 0x2e, 0x4b, 0x35, 0x4b, 0xf5,
+ 0x4b, 0x18, 0x4c, 0x1c, 0x4c, 0x29, 0x4c, 0x30,
+ 0x4c, 0x37, 0x4c, 0x3e, 0x4c, 0x70, 0x4c, 0xa5,
+ 0x4c, 0xac, 0x4c, 0xf1, 0x4c, 0x56, 0x4d, 0x7d,
+ 0x4d, 0x81, 0x4d, 0x85, 0x4d, 0x89, 0x4d, 0x90,
+ 0x4d, 0x94, 0x4d, 0x47, 0x4e, 0x61, 0x4e, 0x85,
+ 0x4e, 0x9f, 0x4e, 0xb9, 0x4e, 0xe1, 0x4e, 0xe5,
+ 0x4e, 0x13, 0x4f, 0x14, 0x4f, 0x25, 0x4f, 0x32,
+ 0x4f, 0x0d, 0x50, 0x5f, 0x50, 0x66, 0x50, 0x80,
+ 0x50, 0x9a, 0x50, 0xf6, 0x50, 0xfd, 0x50, 0x04,
+ 0x51, 0xc8, 0x51, 0xcf, 0x51, 0xe9, 0x51, 0xf0,
+ 0x51, 0x17, 0x52, 0x2c, 0x52, 0x33, 0x52, 0x37,
+ 0x52, 0x20, 0x53, 0x3a, 0x53, 0x41, 0x53, 0x48,
+ 0x53, 0xa1, 0x53, 0x03, 0x54, 0x0a, 0x54, 0x24,
+ 0x54, 0x3e, 0x54, 0x58, 0x54, 0xb3, 0x54, 0x02,
+ 0x55, 0x00, 0x00, 0x47, 0x55, 0x61, 0x55, 0xa1,
+ 0x55, 0xa8, 0x55, 0x34, 0x56, 0x3b, 0x56, 0x63,
+ 0x56, 0x74, 0x56, 0x8e, 0x56, 0x95, 0x56, 0x9c,
+ 0x56, 0xb3, 0x56, 0xb7, 0x56, 0xd6, 0x56, 0xdd,
+ 0x56, 0xe4, 0x56, 0xeb, 0x56, 0xf2, 0x56, 0xf6,
+ 0x56, 0x21, 0x57, 0x28, 0x57, 0x4f, 0x57, 0x56,
+ 0x57, 0x93, 0x57, 0xfa, 0x57, 0x01, 0x58, 0x05,
+ 0x58, 0x32, 0x58, 0x3f, 0x58, 0x46, 0x58, 0x4d,
+ 0x58, 0x54, 0x58, 0x6e, 0x58, 0x88, 0x58, 0xa2,
+ 0x58, 0xb7, 0x58, 0xdf, 0x58, 0x03, 0x59, 0x0a,
+ 0x59, 0x24, 0x59, 0x3e, 0x59, 0x78, 0x59, 0x7f,
+ 0x59, 0x86, 0x59, 0x8d, 0x59, 0x94, 0x59, 0x8b,
+ 0x5a, 0x3a, 0x5b, 0x44, 0x5b, 0x59, 0x5b, 0xe1,
+ 0x5b, 0xee, 0x5b, 0x0d, 0x5c, 0x72, 0x5c, 0x79,
+ 0x5c, 0x80, 0x5c, 0x84, 0x5c, 0xdb, 0x5c, 0xe2,
+ 0x5c, 0xe9, 0x5c, 0xf0, 0x5c, 0x1d, 0x5d, 0x24,
+ 0x5d, 0x88, 0x5d, 0x4d, 0x5e, 0x73, 0x5f, 0x9a,
+ 0x5f, 0xa1, 0x5f, 0xa8, 0x5f, 0xaf, 0x5f, 0xb6,
+ 0x5f, 0xba, 0x5f, 0xe5, 0x5f, 0xec, 0x5f, 0xf3,
+ 0x5f, 0x3a, 0x60, 0x3e, 0x60, 0x74, 0x60, 0x78,
+ 0x60, 0x7f, 0x60, 0x83, 0x60, 0x2b, 0x61, 0x76,
+ 0x61, 0xe9, 0x61, 0x05, 0x62, 0x17, 0x62, 0x29,
+ 0x62, 0xc1, 0x62, 0xd0, 0x62, 0x4a, 0x63, 0x51,
+ 0x63, 0x7f, 0x63, 0x99, 0x63, 0xa0, 0x63, 0xa7,
+ 0x63, 0xae, 0x63, 0xb5, 0x63, 0xbc, 0x63, 0xdc,
+ 0x63, 0xe3, 0x63, 0xea, 0x63, 0x11, 0x64, 0x6e,
+ 0x64, 0x75, 0x64, 0x79, 0x64, 0x80, 0x64, 0xc4,
+ 0x64, 0x07, 0x65, 0x19, 0x65, 0x41, 0x65, 0x5b,
+ 0x65, 0x92, 0x65, 0xc3, 0x65, 0x35, 0x66, 0x3c,
+ 0x66, 0x63, 0x66, 0x6a, 0x66, 0x71, 0x66, 0x78,
+ 0x66, 0x7c, 0x66, 0xa9, 0x66, 0xb5, 0x66, 0xe2,
+ 0x66, 0x0f, 0x67, 0x16, 0x67, 0x1d, 0x67, 0x72,
+ 0x67, 0x8c, 0x67, 0xa6, 0x67, 0xfa, 0x67, 0xfe,
+ 0x67, 0x05, 0x68, 0x7a, 0x68, 0x11, 0x69, 0x18,
+ 0x69, 0x54, 0x69, 0x5b, 0x69, 0x62, 0x69, 0xb8,
+ 0x69, 0x1b, 0x6a, 0x73, 0x6a, 0xcb, 0x6a, 0x2e,
+ 0x6b, 0xa6, 0x6b, 0xad, 0x6b, 0xda, 0x6b, 0xe1,
+ 0x6b, 0x1c, 0x6c, 0x20, 0x6c, 0x24, 0x6c, 0x2b,
+ 0x6c, 0x45, 0x6c, 0x7c, 0x6c, 0x83, 0x6c, 0x9d,
+ 0x6c, 0xc4, 0x6c, 0x20, 0x6f, 0x32, 0x6f, 0x4d,
+ 0x6f, 0x75, 0x6f, 0x96, 0x70, 0xbb, 0x70, 0xc8,
+ 0x70, 0xef, 0x70, 0xf9, 0x70, 0x2c, 0x71, 0xae,
+ 0x71, 0xeb, 0x71, 0x18, 0x72, 0x1c, 0x72, 0x44,
+ 0x72, 0x4e, 0x72, 0x55, 0x72, 0x91, 0x72, 0xbe,
+ 0x72, 0xc2, 0x72, 0x05, 0x73, 0x09, 0x73, 0x28,
+ 0x73, 0x2f, 0x73, 0x36, 0x73, 0x81, 0x73, 0x9c,
+ 0x73, 0xa3, 0x73, 0x01, 0x74, 0x08, 0x74, 0x6f,
+ 0x74, 0x76, 0x74, 0xb3, 0x74, 0xcd, 0x74, 0xd1,
+ 0x74, 0xf9, 0x74, 0x13, 0x75, 0xd5, 0x77, 0x02,
+ 0x78, 0x00, 0x00, 0x3d, 0x78, 0x4a, 0x78, 0x51,
+ 0x78, 0x58, 0x78, 0x5f, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfa, 0x98,
+ 0x04, 0x10, 0x99, 0x29, 0x21, 0x99, 0x25, 0xca,
+ 0x9a, 0xff, 0x66, 0x9c, 0x33, 0x6d, 0x9c, 0x48,
+ 0x79, 0x9c, 0xde, 0xbb, 0xdf, 0xbb, 0xfb, 0xbb,
+ 0x29, 0xbc, 0x33, 0xbc, 0x34, 0xbc, 0x3e, 0xbc,
+ 0x5a, 0xbc, 0x76, 0xbc, 0x77, 0xbc, 0x8a, 0xbc,
+ 0x94, 0xbc, 0xb9, 0xbc, 0xcc, 0xbc, 0xd6, 0xbc,
+ 0x04, 0xbd, 0x05, 0xbd, 0x06, 0xbd, 0x19, 0xbd,
+ 0x2c, 0xbd, 0x36, 0xbd, 0x49, 0xbd, 0x4a, 0xbd,
+ 0x8a, 0xbd, 0x8b, 0xbd, 0xb9, 0xbd, 0xc3, 0xbd,
+ 0xe8, 0xbd, 0xe9, 0xbd, 0xea, 0xbd, 0xeb, 0xbd,
+ 0xf5, 0xbd, 0x1a, 0xbe, 0x51, 0xbe, 0x76, 0xbe,
+ 0xa4, 0xbe, 0xa5, 0xbe, 0xa6, 0xbe, 0xb0, 0xbe,
+ 0xb1, 0xbe, 0xb2, 0xbe, 0xb3, 0xbe, 0x00, 0x00,
+ 0x00, 0x00, 0x4f, 0x04, 0x02, 0x00, 0x01, 0x5f,
+ 0x00, 0x26, 0x7b, 0x51, 0x03, 0x01, 0x10, 0x01,
+ 0x64, 0x00, 0x89, 0x7b, 0x4f, 0x03, 0x02, 0x19,
+ 0x01, 0x5f, 0x00, 0xf6, 0x7b, 0x00, 0x5b, 0x04,
+ 0x01, 0xd1, 0x00, 0x9a, 0x00, 0xfd, 0x7b, 0x5b,
+ 0x01, 0x04, 0xf0, 0x00, 0xa3, 0x00, 0xc9, 0x7c,
+ 0x57, 0x01, 0x04, 0xf0, 0x00, 0xa3, 0x00, 0xd0,
+ 0x7c, 0x57, 0x04, 0x04, 0xd1, 0x00, 0x9a, 0x00,
+ 0xd7, 0x7c, 0x55, 0x05, 0x01, 0x73, 0x00, 0xc2,
+ 0x00, 0xde, 0x7c, 0x00, 0x50, 0x02, 0x04, 0xc7,
+ 0x00, 0xb3, 0x00, 0xe5, 0x7c, 0x00, 0x00, 0x4d,
+ 0x07, 0x02, 0x23, 0x01, 0xb9, 0x00, 0x1a, 0x7d,
+ 0x00, 0x4e, 0x01, 0x02, 0x52, 0x00, 0xb8, 0x00,
+ 0x02, 0x7e, 0x53, 0x01, 0x02, 0x49, 0x00, 0xbc,
+ 0x00, 0x4f, 0x7e, 0x59, 0x07, 0x01, 0xce, 0x00,
+ 0xc2, 0x00, 0x23, 0x7f, 0x00, 0x5c, 0x05, 0x04,
+ 0x6e, 0x00, 0x98, 0x00, 0xbd, 0x7f, 0x56, 0x01,
+ 0x01, 0xc0, 0x00, 0x98, 0x00, 0x47, 0x80, 0x5a,
+ 0x06, 0x02, 0x04, 0x01, 0xc2, 0x00, 0x84, 0x80,
+ 0x00, 0x00, 0x4b, 0x02, 0x01, 0x7a, 0x00, 0x97,
+ 0x00, 0x8b, 0x80, 0x52, 0x02, 0x01, 0x8b, 0x00,
+ 0x9c, 0x00, 0xc3, 0x80, 0x00, 0x32, 0x01, 0x02,
+ 0xbd, 0x00, 0x9f, 0x00, 0x17, 0x81, 0x00, 0x0e,
+ 0x03, 0x02, 0xcb, 0x00, 0xab, 0x00, 0x74, 0x81,
+ 0x22, 0x02, 0x02, 0x94, 0x00, 0xbd, 0x00, 0xc2,
+ 0x81, 0x2b, 0x06, 0x01, 0x5a, 0x00, 0xbc, 0x00,
+ 0x3d, 0x82, 0x0d, 0x03, 0x02, 0xcb, 0x00, 0xab,
+ 0x00, 0x0b, 0x83, 0x00, 0x1b, 0x06, 0x04, 0x67,
+ 0x00, 0xc0, 0x00, 0x12, 0x83, 0x2b, 0x04, 0x01,
+ 0xc5, 0x00, 0xb7, 0x00, 0x98, 0x83, 0x00, 0x20,
+ 0x01, 0x02, 0x6e, 0x00, 0xb9, 0x00, 0x9f, 0x83,
+ 0x00, 0x09, 0x03, 0x02, 0x2c, 0x00, 0xa8, 0x00,
+ 0xc7, 0x84, 0x2c, 0x04, 0x03, 0xec, 0x00, 0xb3,
+ 0x00, 0x38, 0x85, 0x08, 0x03, 0x02, 0x2c, 0x00,
+ 0xa8, 0x00, 0xd6, 0x85, 0x0f, 0x03, 0x02, 0x2c,
+ 0x00, 0xa8, 0x00, 0xdd, 0x85, 0x2e, 0x04, 0x03,
+ 0xec, 0x00, 0xb3, 0x00, 0xe4, 0x85, 0x00, 0x00,
+ 0x00, 0x19, 0x07, 0x04, 0xa2, 0x00, 0xc2, 0x00,
+ 0xeb, 0x85, 0x15, 0x07, 0x04, 0xa2, 0x00, 0xc2,
+ 0x00, 0x2c, 0x86, 0x00, 0x13, 0x05, 0x01, 0x8b,
+ 0x00, 0xa5, 0x00, 0x3d, 0x86, 0x0c, 0x09, 0x02,
+ 0x0e, 0x01, 0xb6, 0x00, 0x65, 0x86, 0x00, 0x05,
+ 0x03, 0x04, 0x57, 0x00, 0xb9, 0x00, 0xa9, 0x86,
+ 0x00, 0x07, 0x04, 0x04, 0x30, 0x00, 0xbe, 0x00,
+ 0x82, 0x8b, 0x24, 0x0a, 0x02, 0xcf, 0x00, 0xc2,
+ 0x00, 0xfc, 0x8b, 0x00, 0x00, 0x0a, 0x01, 0x04,
+ 0x3d, 0x00, 0xbb, 0x00, 0xc9, 0x88, 0x0b, 0x01,
+ 0x04, 0x3d, 0x00, 0xbb, 0x00, 0x18, 0x89, 0x0a,
+ 0x02, 0x04, 0x02, 0x01, 0xb5, 0x00, 0x2d, 0x89,
+ 0x0b, 0x02, 0x04, 0x02, 0x01, 0xb5, 0x00, 0xb7,
+ 0x89, 0x17, 0x02, 0x04, 0x02, 0x01, 0xb5, 0x00,
+ 0xcc, 0x89, 0x1a, 0x09, 0x03, 0x9e, 0x00, 0xc6,
+ 0x00, 0x22, 0x8a, 0x33, 0x02, 0x04, 0x02, 0x01,
+ 0xb5, 0x00, 0x6f, 0x8a, 0x00, 0x00, 0x23, 0x05,
+ 0x04, 0x0c, 0x01, 0x91, 0x00, 0x6e, 0x8c, 0x2e,
+ 0x02, 0x04, 0xcd, 0x00, 0x99, 0x00, 0xc8, 0x8c,
+ 0x2c, 0x02, 0x04, 0xea, 0x00, 0x98, 0x00, 0x42,
+ 0x8d, 0x0d, 0x02, 0x04, 0xea, 0x00, 0x98, 0x00,
+ 0x49, 0x8d, 0x0e, 0x02, 0x04, 0xea, 0x00, 0x98,
+ 0x00, 0x50, 0x8d, 0x00, 0x30, 0x05, 0x01, 0x9f,
+ 0x00, 0xa6, 0x00, 0x57, 0x8d, 0x00, 0x02, 0x02,
+ 0x01, 0xe6, 0x00, 0xa4, 0x00, 0x1d, 0x8f, 0x02,
+ 0x03, 0x01, 0xe6, 0x00, 0xa4, 0x00, 0x1d, 0x8f,
+ 0x2d, 0x04, 0x04, 0xec, 0x00, 0x8e, 0x00, 0xc8,
+ 0x8f, 0x2f, 0x0c, 0x04, 0xec, 0x00, 0x8e, 0x00,
+ 0x54, 0x90, 0x00, 0x00, 0x00, 0x00, 0x49, 0x02,
+ 0x02, 0x2c, 0x01, 0xb2, 0x00, 0xbc, 0x90, 0x00,
+ 0x34, 0x01, 0x01, 0x3d, 0x00, 0xaf, 0x00, 0xf5,
+ 0x90, 0x43, 0x01, 0x01, 0x3d, 0x00, 0xaf, 0x00,
+ 0xfc, 0x90, 0x47, 0x01, 0x01, 0x3d, 0x00, 0xaf,
+ 0x00, 0xcb, 0x91, 0x3d, 0x01, 0x01, 0x3d, 0x00,
+ 0xaf, 0x00, 0x09, 0x92, 0x00, 0x38, 0x08, 0x01,
+ 0xdd, 0x00, 0xa0, 0x00, 0x47, 0x92, 0x40, 0x08,
+ 0x01, 0xdd, 0x00, 0xa0, 0x00, 0x4e, 0x92, 0x3f,
+ 0x06, 0x01, 0x8d, 0x00, 0x9f, 0x00, 0x3d, 0x93,
+ 0x37, 0x03, 0x04, 0x3f, 0x00, 0xa8, 0x00, 0xaf,
+ 0x93, 0x44, 0x0c, 0x01, 0xc0, 0x00, 0xa0, 0x00,
+ 0xd5, 0x93, 0x45, 0x02, 0x04, 0x51, 0x00, 0xa0,
+ 0x00, 0x49, 0x94, 0x00, 0x3c, 0x02, 0x02, 0x14,
+ 0x01, 0x9f, 0x00, 0x72, 0x94, 0x3e, 0x02, 0x02,
+ 0x14, 0x01, 0x9f, 0x00, 0x9b, 0x94, 0x3a, 0x07,
+ 0x04, 0x44, 0x00, 0x81, 0x00, 0xd4, 0x94, 0x3b,
+ 0x02, 0x02, 0x14, 0x01, 0x9f, 0x00, 0x1b, 0x95,
+ 0x00, 0x39, 0x05, 0x01, 0x91, 0x00, 0xc5, 0x00,
+ 0x37, 0x95, 0x36, 0x05, 0x01, 0x81, 0x00, 0xad,
+ 0x00, 0xc8, 0x95, 0x35, 0x04, 0x01, 0x74, 0x00,
+ 0xbf, 0x00, 0xeb, 0x95, 0x43, 0x04, 0x01, 0x74,
+ 0x00, 0xbf, 0x00, 0x2f, 0x96, 0x34, 0x04, 0x01,
+ 0x74, 0x00, 0xbf, 0x00, 0x6c, 0x96, 0x00, 0x00,
+ 0x00, 0x4a, 0x01, 0x01, 0x3b, 0x00, 0xa3, 0x00,
+ 0x73, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
+ 0x6f, 0x77, 0x2c, 0x20, 0x6e, 0x6f, 0x77, 0x20,
+ 0x69, 0x74, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x73,
+ 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x69, 0x74,
+ 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x73, 0x74,
+ 0x72, 0x61, 0x69, 0x67, 0x68, 0x74, 0x00, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x74, 0x6f, 0x72, 0x65, 0x21, 0x00, 0x00,
+ 0x54, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x72, 0x69, 0x62, 0x62, 0x6f, 0x6e,
+ 0x20, 0x61, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x72, 0x61, 0x6b, 0x65,
+ 0x20, 0x6e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x65,
+ 0x64, 0x00, 0x74, 0x68, 0x65, 0x20, 0x73, 0x70,
+ 0x61, 0x63, 0x65, 0x20, 0x62, 0x65, 0x74, 0x77,
+ 0x65, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x74, 0x65, 0x65, 0x74, 0x68, 0x21, 0x00, 0x00,
+ 0x57, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x68, 0x65, 0x6c, 0x70, 0x20, 0x6f, 0x66,
+ 0x20, 0x73, 0x75, 0x70, 0x65, 0x72, 0x20, 0x67,
+ 0x6c, 0x75, 0x65, 0x20, 0x49, 0x20, 0x6d, 0x61,
+ 0x64, 0x65, 0x2e, 0x2e, 0x2e, 0x00, 0x73, 0x6f,
+ 0x6d, 0x65, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2e,
+ 0x2e, 0x2e, 0x00, 0x00, 0x55, 0x73, 0x69, 0x6e,
+ 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x75,
+ 0x70, 0x65, 0x72, 0x20, 0x67, 0x6c, 0x75, 0x65,
+ 0x20, 0x6f, 0x6e, 0x63, 0x65, 0x20, 0x61, 0x67,
+ 0x61, 0x69, 0x6e, 0x2e, 0x2e, 0x2e, 0x00, 0x00,
+ 0x54, 0x68, 0x65, 0x20, 0x77, 0x68, 0x69, 0x73,
+ 0x6b, 0x79, 0x20, 0x69, 0x73, 0x20, 0x73, 0x74,
+ 0x72, 0x6f, 0x6e, 0x67, 0x20, 0x65, 0x6e, 0x6f,
+ 0x75, 0x67, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x75,
+ 0x73, 0x65, 0x20, 0x61, 0x73, 0x00, 0x66, 0x75,
+ 0x65, 0x6c, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20,
+ 0x49, 0x20, 0x77, 0x6f, 0x6e, 0x64, 0x65, 0x72,
+ 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x61, 0x77,
+ 0x00, 0x63, 0x61, 0x6e, 0x20, 0x74, 0x61, 0x6b,
+ 0x65, 0x20, 0x69, 0x74, 0x2e, 0x2e, 0x2e, 0x00,
+ 0x00, 0x4f, 0x6e, 0x63, 0x65, 0x20, 0x61, 0x67,
+ 0x61, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x75, 0x70, 0x65, 0x72, 0x2d, 0x67, 0x6c,
+ 0x75, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x73,
+ 0x20, 0x69, 0x6e, 0x20, 0x68, 0x61, 0x6e, 0x64,
+ 0x79, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x54, 0x68,
+ 0x65, 0x20, 0x73, 0x6f, 0x6f, 0x74, 0x20, 0x67,
+ 0x69, 0x76, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x70, 0x6f, 0x74, 0x61, 0x74, 0x6f, 0x65,
+ 0x20, 0x61, 0x20, 0x62, 0x72, 0x61, 0x6e, 0x64,
+ 0x20, 0x6e, 0x65, 0x77, 0x20, 0x6c, 0x6f, 0x6f,
+ 0x6b, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x4e, 0x6f,
+ 0x77, 0x20, 0x49, 0x27, 0x6d, 0x20, 0x72, 0x65,
+ 0x61, 0x64, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x63,
+ 0x6f, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6b, 0x65, 0x21,
+ 0x00, 0x00, 0x49, 0x74, 0x20, 0x6d, 0x61, 0x6b,
+ 0x65, 0x73, 0x20, 0x6d, 0x65, 0x20, 0x66, 0x65,
+ 0x65, 0x6c, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20,
+ 0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x00,
+ 0x77, 0x61, 0x6e, 0x6e, 0x61, 0x2d, 0x62, 0x65,
+ 0x20, 0x63, 0x6c, 0x69, 0x66, 0x66, 0x68, 0x61,
+ 0x6e, 0x67, 0x65, 0x72, 0x2e, 0x00, 0x00, 0x49,
+ 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x6e, 0x27,
+ 0x74, 0x20, 0x69, 0x6d, 0x70, 0x72, 0x65, 0x73,
+ 0x73, 0x20, 0x61, 0x6e, 0x79, 0x6f, 0x6e, 0x65,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x73, 0x75,
+ 0x63, 0x68, 0x20, 0x63, 0x61, 0x6e, 0x64, 0x79,
+ 0x2e, 0x00, 0x00, 0x49, 0x74, 0x27, 0x73, 0x20,
+ 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x65,
+ 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x2e, 0x00, 0x00,
+ 0x47, 0x72, 0x65, 0x61, 0x74, 0x20, 0x69, 0x64,
+ 0x65, 0x61, 0x21, 0x20, 0x42, 0x75, 0x74, 0x2c,
+ 0x20, 0x79, 0x6f, 0x75, 0x20, 0x73, 0x65, 0x65,
+ 0x2c, 0x20, 0x65, 0x63, 0x6f, 0x6d, 0x61, 0x6e,
+ 0x69, 0x61, 0x63, 0x73, 0x20, 0x6d, 0x69, 0x67,
+ 0x68, 0x74, 0x00, 0x62, 0x65, 0x20, 0x77, 0x61,
+ 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x2e, 0x2e,
+ 0x2e, 0x00, 0x00, 0x49, 0x74, 0x20, 0x77, 0x6f,
+ 0x6e, 0x27, 0x74, 0x20, 0x6c, 0x6f, 0x6f, 0x6b,
+ 0x20, 0x61, 0x6e, 0x79, 0x20, 0x62, 0x65, 0x74,
+ 0x74, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x61,
+ 0x20, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72,
+ 0x2e, 0x00, 0x00, 0x54, 0x68, 0x65, 0x20, 0x63,
+ 0x61, 0x6b, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74,
+ 0x6f, 0x6f, 0x20, 0x62, 0x69, 0x67, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20,
+ 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x2e,
+ 0x00, 0x00, 0x49, 0x20, 0x64, 0x6f, 0x6e, 0x27,
+ 0x74, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, 0x74,
+ 0x6f, 0x20, 0x77, 0x61, 0x73, 0x74, 0x65, 0x20,
+ 0x74, 0x68, 0x69, 0x73, 0x20, 0x63, 0x61, 0x6e,
+ 0x64, 0x79, 0x2e, 0x00, 0x00, 0x54, 0x68, 0x65,
+ 0x20, 0x66, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20,
+ 0x69, 0x73, 0x20, 0x62, 0x65, 0x61, 0x75, 0x74,
+ 0x69, 0x66, 0x75, 0x6c, 0x20, 0x65, 0x6e, 0x6f,
+ 0x75, 0x67, 0x68, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x6f, 0x75, 0x74, 0x00, 0x61, 0x6e, 0x79, 0x20,
+ 0x66, 0x61, 0x6e, 0x63, 0x79, 0x20, 0x65, 0x78,
+ 0x74, 0x72, 0x61, 0x73, 0x2e, 0x00, 0x00, 0x47,
+ 0x6f, 0x6f, 0x64, 0x20, 0x69, 0x64, 0x65, 0x61,
+ 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x49, 0x20,
+ 0x6e, 0x65, 0x65, 0x64, 0x20, 0x73, 0x6f, 0x6d,
+ 0x65, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x73,
+ 0x6d, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x00, 0x74,
+ 0x68, 0x61, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x72, 0x6f, 0x70, 0x65, 0x2e, 0x00, 0x00,
+ 0x49, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x20,
+ 0x6e, 0x65, 0x65, 0x64, 0x20, 0x74, 0x68, 0x69,
+ 0x73, 0x20, 0x63, 0x68, 0x65, 0x65, 0x73, 0x65,
+ 0x2e, 0x20, 0x41, 0x67, 0x61, 0x69, 0x6e, 0x2e,
+ 0x00, 0x00, 0x49, 0x74, 0x27, 0x73, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x44, 0x4f, 0x4f, 0x4d, 0x2e,
+ 0x20, 0x49, 0x74, 0x27, 0x73, 0x20, 0x61, 0x20,
+ 0x68, 0x61, 0x72, 0x6d, 0x6c, 0x65, 0x73, 0x73,
+ 0x20, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63,
+ 0x20, 0x61, 0x64, 0x76, 0x65, 0x6e, 0x74, 0x75,
+ 0x72, 0x65, 0x00, 0x66, 0x6f, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x68, 0x6f, 0x6c, 0x65,
+ 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x20,
+ 0x28, 0x77, 0x65, 0x20, 0x77, 0x61, 0x6e, 0x74,
+ 0x20, 0x44, 0x4f, 0x4f, 0x4d, 0x21, 0x20, 0x77,
+ 0x65, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x00, 0x44,
+ 0x4f, 0x4f, 0x4d, 0x21, 0x29, 0x2e, 0x00, 0x00,
+ 0x49, 0x20, 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x20,
+ 0x6e, 0x65, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20,
+ 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x69,
+ 0x73, 0x20, 0x6e, 0x75, 0x74, 0x2e, 0x00, 0x00,
+ 0x4c, 0x65, 0x74, 0x27, 0x73, 0x20, 0x6d, 0x61,
+ 0x6b, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20,
+ 0x63, 0x6f, 0x72, 0x6b, 0x20, 0x6c, 0x61, 0x72,
+ 0x67, 0x65, 0x72, 0x2e, 0x00, 0x00, 0x4f, 0x6e,
+ 0x63, 0x65, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x75, 0x70,
+ 0x65, 0x72, 0x20, 0x67, 0x6c, 0x75, 0x65, 0x20,
+ 0x63, 0x6f, 0x6d, 0x65, 0x73, 0x20, 0x69, 0x6e,
+ 0x20, 0x68, 0x61, 0x6e, 0x64, 0x79, 0x2e, 0x00,
+ 0x00, 0x54, 0x68, 0x65, 0x20, 0x62, 0x61, 0x74,
+ 0x74, 0x65, 0x72, 0x69, 0x65, 0x73, 0x20, 0x66,
+ 0x69, 0x74, 0x21, 0x00, 0x00, 0x49, 0x20, 0x74,
+ 0x69, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x72, 0x6f, 0x70, 0x65, 0x20, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x70, 0x69, 0x6e, 0x2e,
+ 0x00, 0x00, 0x4c, 0x65, 0x74, 0x27, 0x73, 0x20,
+ 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x69, 0x74, 0x20,
+ 0x73, 0x70, 0x69, 0x63, 0x79, 0x2e, 0x00, 0x00,
+ 0x12, 0x16, 0x17, 0xb4, 0xbe, 0x15, 0x18, 0x19,
+ 0xed, 0xbe, 0x01, 0x1c, 0x1f, 0x35, 0xbf, 0x11,
+ 0x1c, 0x1e, 0x35, 0xbf, 0x1f, 0x11, 0x20, 0x69,
+ 0xbf, 0x1e, 0x01, 0x20, 0x69, 0xbf, 0x0d, 0x10,
+ 0x0e, 0x8d, 0xbf, 0x08, 0x0f, 0x09, 0xe6, 0xbf,
+ 0x14, 0x21, 0x22, 0x13, 0xc0, 0x27, 0x28, 0x29,
+ 0x43, 0xc0, 0x26, 0x2a, 0x2b, 0x67, 0xc0, 0x12,
+ 0x13, 0x00, 0x9c, 0xc0, 0x01, 0x30, 0x00, 0xc8,
+ 0xc0, 0x10, 0x30, 0x00, 0xdd, 0xc0, 0x12, 0x14,
+ 0x00, 0x18, 0xc1, 0x12, 0x22, 0x00, 0x18, 0xc1,
+ 0x12, 0x1a, 0x00, 0x18, 0xc1, 0x12, 0x1c, 0x00,
+ 0x18, 0xc1, 0x12, 0x31, 0x00, 0x18, 0xc1, 0x12,
+ 0x13, 0x00, 0x40, 0xc1, 0x13, 0x30, 0x00, 0x67,
+ 0xc1, 0x18, 0x0a, 0x00, 0x8a, 0xc1, 0x18, 0x0b,
+ 0x00, 0x8a, 0xc1, 0x15, 0x26, 0x00, 0xc4, 0xc1,
+ 0x2d, 0x30, 0x00, 0xfd, 0xc1, 0x2c, 0x30, 0x00,
+ 0x1f, 0xc2, 0x2e, 0x30, 0x00, 0x1f, 0xc2, 0x31,
+ 0x1a, 0x00, 0x85, 0xc2, 0x31, 0x30, 0x00, 0x1f,
+ 0xc2, 0x37, 0x3b, 0x3c, 0xa5, 0xc2, 0x41, 0x38,
+ 0x40, 0xc3, 0xc2, 0x42, 0x34, 0x43, 0xee, 0xc2,
+ 0x54, 0x58, 0x59, 0x02, 0xc3, 0x57, 0x5a, 0x5b,
+ 0x1f, 0xc3, 0x00, 0x00, 0x00, 0x55, 0x73, 0x69,
+ 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65,
+ 0x20, 0x74, 0x77, 0x6f, 0x20, 0x6f, 0x62, 0x6a,
+ 0x65, 0x63, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x67,
+ 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x6f,
+ 0x6e, 0x27, 0x74, 0x00, 0x61, 0x63, 0x63, 0x6f,
+ 0x6d, 0x70, 0x6c, 0x69, 0x73, 0x68, 0x20, 0x61,
+ 0x6e, 0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2e,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5e, 0xc5, 0x7b, 0xc5, 0x9a, 0xc5, 0xc3,
+ 0xc5, 0xcf, 0xc5, 0xfd, 0xc5, 0x2c, 0xc6, 0x3f,
+ 0xc6, 0x62, 0xc6, 0x93, 0xc6, 0xb9, 0xc6, 0xda,
+ 0xc6, 0x0a, 0xc7, 0x42, 0xc7, 0x75, 0xc7, 0x96,
+ 0xc7, 0xcb, 0xc7, 0xf4, 0xc7, 0x60, 0xc8, 0xa0,
+ 0xc8, 0xd3, 0xc8, 0x21, 0xc9, 0x65, 0xc9, 0xa2,
+ 0xc9, 0xf2, 0xc9, 0x09, 0xca, 0x22, 0xca, 0x6b,
+ 0xca, 0xe7, 0xca, 0x2d, 0xcb, 0x61, 0xcb, 0x96,
+ 0xcb, 0xba, 0xcb, 0xf2, 0xcb, 0x5d, 0xcc, 0x79,
+ 0xcc, 0xdd, 0xcc, 0x0f, 0xcd, 0x25, 0xcd, 0x54,
+ 0xcd, 0x95, 0xcd, 0xc8, 0xcd, 0xfe, 0xcd, 0x33,
+ 0xce, 0x75, 0xce, 0xa6, 0xce, 0xe3, 0xce, 0x4f,
+ 0xcf, 0x6a, 0xcf, 0x9d, 0xcf, 0xf8, 0xcf, 0x05,
+ 0xd0, 0x32, 0xd0, 0x5c, 0xd0, 0x7b, 0xd0, 0xb1,
+ 0xd0, 0xe7, 0xd0, 0x30, 0xd1, 0x4e, 0xd1, 0x73,
+ 0xd1, 0x9d, 0xd1, 0xf4, 0xd1, 0x41, 0xd2, 0x6f,
+ 0xd2, 0xa7, 0xd2, 0xcb, 0xd2, 0xf6, 0xd2, 0x46,
+ 0xd3, 0x8a, 0xd3, 0xb3, 0xd3, 0xfb, 0xd3, 0x16,
+ 0xd4, 0x49, 0xd4, 0x7b, 0xd4, 0xa4, 0xd4, 0xca,
+ 0xd4, 0xeb, 0xd4, 0x1f, 0xd5, 0x43, 0xd5, 0x7f,
+ 0xd5, 0xaa, 0xd5, 0xc6, 0xd5, 0x42, 0xd6, 0xb7,
+ 0xd6, 0x0a, 0xd7, 0x1d, 0xd7, 0x67, 0xd7, 0x92,
+ 0xd7, 0xae, 0xd7, 0xe6, 0xd7, 0x35, 0xd8, 0x5e,
+ 0xd8, 0x01, 0x00, 0x66, 0x65, 0x61, 0x74, 0x68,
+ 0x65, 0x72, 0x00, 0x49, 0x74, 0x27, 0x73, 0x20,
+ 0x6b, 0x69, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x20,
+ 0x61, 0x73, 0x73, 0x21, 0x00, 0x00, 0x02, 0x00,
+ 0x73, 0x68, 0x6f, 0x74, 0x67, 0x75, 0x6e, 0x00,
+ 0x4c, 0x6f, 0x6f, 0x6b, 0x73, 0x20, 0x69, 0x6d,
+ 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x76, 0x65,
+ 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x03, 0x00, 0x74,
+ 0x6f, 0x6f, 0x6c, 0x62, 0x6f, 0x78, 0x00, 0x44,
+ 0x6f, 0x65, 0x73, 0x6e, 0x27, 0x74, 0x20, 0x73,
+ 0x65, 0x65, 0x6d, 0x20, 0x74, 0x6f, 0x20, 0x62,
+ 0x65, 0x20, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64,
+ 0x21, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x04, 0x00,
+ 0x74, 0x6f, 0x6f, 0x6c, 0x62, 0x6f, 0x78, 0x00,
+ 0x00, 0x00, 0x05, 0x00, 0x73, 0x70, 0x61, 0x6e,
+ 0x6e, 0x65, 0x72, 0x00, 0x54, 0x68, 0x65, 0x73,
+ 0x65, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x73,
+ 0x20, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x20,
+ 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20,
+ 0x68, 0x61, 0x6e, 0x64, 0x79, 0x2e, 0x00, 0x00,
+ 0x06, 0x00, 0x63, 0x6f, 0x6d, 0x62, 0x00, 0x49,
+ 0x27, 0x76, 0x65, 0x20, 0x68, 0x65, 0x61, 0x72,
+ 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73,
+ 0x6f, 0x6d, 0x65, 0x20, 0x70, 0x65, 0x6f, 0x70,
+ 0x6c, 0x65, 0x20, 0x75, 0x73, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x73, 0x65, 0x2e, 0x00, 0x00, 0x07,
+ 0x01, 0x66, 0x61, 0x6e, 0x00, 0x52, 0x65, 0x66,
+ 0x72, 0x65, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x2e,
+ 0x00, 0x00, 0x08, 0x00, 0x62, 0x72, 0x6f, 0x6b,
+ 0x65, 0x6e, 0x20, 0x70, 0x61, 0x64, 0x64, 0x6c,
+ 0x65, 0x00, 0x54, 0x6f, 0x6f, 0x20, 0x73, 0x68,
+ 0x6f, 0x72, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x75,
+ 0x73, 0x65, 0x2e, 0x00, 0x00, 0x09, 0x00, 0x70,
+ 0x61, 0x64, 0x64, 0x6c, 0x65, 0x00, 0x54, 0x68,
+ 0x65, 0x20, 0x67, 0x6c, 0x75, 0x65, 0x20, 0x6b,
+ 0x65, 0x65, 0x70, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x00,
+ 0x72, 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x68,
+ 0x61, 0x72, 0x64, 0x2e, 0x00, 0x00, 0x0a, 0x00,
+ 0x66, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x00, 0x49,
+ 0x74, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x6c, 0x79,
+ 0x20, 0x73, 0x6d, 0x65, 0x6c, 0x6c, 0x73, 0x00,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x6e, 0x69, 0x63,
+ 0x65, 0x2e, 0x00, 0x00, 0x0b, 0x00, 0x66, 0x6c,
+ 0x6f, 0x77, 0x65, 0x72, 0x00, 0x49, 0x74, 0x27,
+ 0x73, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x6c, 0x79,
+ 0x20, 0x62, 0x65, 0x61, 0x75, 0x74, 0x69, 0x66,
+ 0x75, 0x6c, 0x2e, 0x00, 0x00, 0x0c, 0x00, 0x66,
+ 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x64,
+ 0x75, 0x73, 0x74, 0x65, 0x72, 0x00, 0x49, 0x20,
+ 0x63, 0x61, 0x6e, 0x20, 0x70, 0x6c, 0x61, 0x79,
+ 0x20, 0x6a, 0x61, 0x6e, 0x69, 0x74, 0x6f, 0x72,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x69, 0x73, 0x2e, 0x00, 0x00, 0x0d, 0x00, 0x63,
+ 0x68, 0x61, 0x69, 0x6e, 0x73, 0x61, 0x77, 0x00,
+ 0x49, 0x74, 0x27, 0x73, 0x20, 0x69, 0x6e, 0x20,
+ 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x63, 0x6f, 0x6e,
+ 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20,
+ 0x62, 0x75, 0x74, 0x20, 0x69, 0x74, 0x20, 0x68,
+ 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x20, 0x66, 0x75,
+ 0x65, 0x6c, 0x2e, 0x00, 0x00, 0x0e, 0x01, 0x64,
+ 0x72, 0x75, 0x6e, 0x6b, 0x65, 0x6e, 0x20, 0x63,
+ 0x68, 0x61, 0x69, 0x6e, 0x73, 0x61, 0x77, 0x00,
+ 0x41, 0x20, 0x62, 0x69, 0x74, 0x20, 0x75, 0x6e,
+ 0x73, 0x74, 0x65, 0x61, 0x64, 0x79, 0x2c, 0x20,
+ 0x62, 0x75, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x00, 0x00,
+ 0x0f, 0x00, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68,
+ 0x00, 0x54, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6f,
+ 0x64, 0x20, 0x69, 0x73, 0x20, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x68, 0x61, 0x72, 0x64, 0x2e, 0x00,
+ 0x00, 0x10, 0x00, 0x77, 0x68, 0x69, 0x73, 0x6b,
+ 0x79, 0x00, 0x54, 0x68, 0x65, 0x20, 0x6c, 0x61,
+ 0x62, 0x65, 0x6c, 0x20, 0x73, 0x61, 0x79, 0x73,
+ 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x77, 0x68,
+ 0x69, 0x73, 0x6b, 0x79, 0x20, 0x69, 0x73, 0x00,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x73, 0x74, 0x72,
+ 0x6f, 0x6e, 0x67, 0x2e, 0x00, 0x00, 0x11, 0x00,
+ 0x6e, 0x65, 0x65, 0x64, 0x6c, 0x65, 0x00, 0x49,
+ 0x74, 0x27, 0x73, 0x20, 0x71, 0x75, 0x69, 0x74,
+ 0x65, 0x20, 0x62, 0x69, 0x67, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x61, 0x20, 0x6e, 0x65, 0x65, 0x64,
+ 0x6c, 0x65, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x12,
+ 0x00, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72,
+ 0x00, 0x4e, 0x69, 0x63, 0x65, 0x20, 0x64, 0x65,
+ 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x20, 0x45, 0x73,
+ 0x70, 0x65, 0x63, 0x69, 0x61, 0x6c, 0x6c, 0x79,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x27, 0x4c,
+ 0x4f, 0x56, 0x45, 0x20, 0x43, 0x41, 0x4e, 0x44,
+ 0x59, 0x27, 0x20, 0x6c, 0x61, 0x62, 0x65, 0x6c,
+ 0x2e, 0x00, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x72, 0x65, 0x27, 0x73, 0x20, 0x61, 0x20,
+ 0x68, 0x65, 0x61, 0x72, 0x74, 0x20, 0x70, 0x61,
+ 0x69, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x6f, 0x6e,
+ 0x20, 0x69, 0x74, 0x2e, 0x00, 0x48, 0x6f, 0x77,
+ 0x20, 0x53, 0x57, 0x45, 0x45, 0x54, 0x2e, 0x2e,
+ 0x2e, 0x00, 0x00, 0x13, 0x00, 0x63, 0x68, 0x6f,
+ 0x63, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x63,
+ 0x61, 0x6e, 0x64, 0x79, 0x00, 0x49, 0x74, 0x27,
+ 0x73, 0x20, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20,
+ 0x63, 0x68, 0x6f, 0x63, 0x6f, 0x6c, 0x61, 0x74,
+ 0x65, 0x20, 0x63, 0x61, 0x6e, 0x64, 0x79, 0x2e,
+ 0x00, 0x41, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74,
+ 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74,
+ 0x2e, 0x00, 0x00, 0x14, 0x00, 0x77, 0x69, 0x6c,
+ 0x64, 0x20, 0x70, 0x6f, 0x74, 0x61, 0x74, 0x6f,
+ 0x65, 0x00, 0x57, 0x6f, 0x77, 0x21, 0x20, 0x49,
+ 0x74, 0x27, 0x73, 0x20, 0x73, 0x68, 0x61, 0x70,
+ 0x65, 0x64, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20,
+ 0x61, 0x20, 0x67, 0x72, 0x65, 0x6e, 0x61, 0x64,
+ 0x65, 0x21, 0x2e, 0x2e, 0x00, 0x00, 0x15, 0x00,
+ 0x72, 0x61, 0x6b, 0x65, 0x00, 0x54, 0x68, 0x65,
+ 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x62,
+ 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x65, 0x65, 0x74, 0x68,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x6f, 0x6f, 0x20,
+ 0x6c, 0x61, 0x72, 0x67, 0x65, 0x00, 0x74, 0x6f,
+ 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x74, 0x68,
+ 0x69, 0x73, 0x20, 0x72, 0x61, 0x6b, 0x65, 0x20,
+ 0x61, 0x6e, 0x20, 0x75, 0x73, 0x65, 0x66, 0x75,
+ 0x6c, 0x2e, 0x00, 0x00, 0x16, 0x00, 0x68, 0x65,
+ 0x61, 0x72, 0x74, 0x2d, 0x73, 0x68, 0x61, 0x70,
+ 0x65, 0x64, 0x20, 0x63, 0x61, 0x6e, 0x64, 0x79,
+ 0x00, 0x49, 0x20, 0x64, 0x6f, 0x6e, 0x27, 0x74,
+ 0x20, 0x74, 0x68, 0x69, 0x6e, 0x6b, 0x20, 0x74,
+ 0x68, 0x69, 0x73, 0x20, 0x6f, 0x6e, 0x65, 0x20,
+ 0x69, 0x6d, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x20, 0x69, 0x73, 0x20, 0x65,
+ 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x2e, 0x00, 0x00,
+ 0x17, 0x00, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65,
+ 0x64, 0x20, 0x63, 0x61, 0x6e, 0x64, 0x79, 0x00,
+ 0x42, 0x72, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x65,
+ 0x77, 0x20, 0x63, 0x61, 0x6e, 0x64, 0x79, 0x2e,
+ 0x20, 0x41, 0x74, 0x20, 0x6c, 0x65, 0x61, 0x73,
+ 0x74, 0x20, 0x69, 0x74, 0x20, 0x6c, 0x6f, 0x6f,
+ 0x6b, 0x73, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20,
+ 0x69, 0x74, 0x2e, 0x00, 0x00, 0x18, 0x00, 0x72,
+ 0x69, 0x62, 0x62, 0x6f, 0x6e, 0x00, 0x49, 0x74,
+ 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x72, 0x65,
+ 0x6d, 0x69, 0x6e, 0x64, 0x20, 0x6d, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x62, 0x65, 0x61, 0x74, 0x69, 0x66, 0x75, 0x6c,
+ 0x20, 0x63, 0x68, 0x69, 0x63, 0x6b, 0x2c, 0x00,
+ 0x49, 0x20, 0x6d, 0x65, 0x61, 0x6e, 0x2c, 0x20,
+ 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65, 0x20, 0x68,
+ 0x75, 0x6d, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x69,
+ 0x6e, 0x67, 0x2e, 0x00, 0x00, 0x19, 0x00, 0x72,
+ 0x61, 0x6b, 0x65, 0x00, 0x52, 0x65, 0x61, 0x64,
+ 0x79, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x6f, 0x72,
+ 0x6b, 0x2e, 0x00, 0x00, 0x1a, 0x00, 0x6e, 0x75,
+ 0x74, 0x00, 0x41, 0x20, 0x72, 0x65, 0x61, 0x6c,
+ 0x6c, 0x79, 0x20, 0x62, 0x69, 0x67, 0x20, 0x6f,
+ 0x6e, 0x65, 0x2e, 0x00, 0x00, 0x1b, 0x00, 0x70,
+ 0x6c, 0x61, 0x73, 0x74, 0x69, 0x63, 0x20, 0x61,
+ 0x70, 0x70, 0x6c, 0x65, 0x00, 0x49, 0x74, 0x20,
+ 0x6c, 0x6f, 0x6f, 0x6b, 0x73, 0x20, 0x73, 0x6f,
+ 0x20, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x49, 0x20, 0x63, 0x6f, 0x75,
+ 0x6c, 0x64, 0x00, 0x65, 0x76, 0x65, 0x6e, 0x20,
+ 0x73, 0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x70, 0x69, 0x70, 0x73, 0x20, 0x69, 0x6e, 0x73,
+ 0x69, 0x64, 0x65, 0x2e, 0x00, 0x00, 0x1c, 0x00,
+ 0x63, 0x6f, 0x6e, 0x65, 0x00, 0x49, 0x74, 0x20,
+ 0x6c, 0x6f, 0x6f, 0x6b, 0x73, 0x20, 0x6c, 0x69,
+ 0x6b, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65, 0x20,
+ 0x48, 0x61, 0x76, 0x61, 0x6e, 0x61, 0x20, 0x67,
+ 0x6f, 0x6f, 0x64, 0x69, 0x65, 0x73, 0x20, 0x65,
+ 0x76, 0x65, 0x72, 0x79, 0x00, 0x73, 0x65, 0x6c,
+ 0x66, 0x2d, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63,
+ 0x74, 0x69, 0x6e, 0x67, 0x20, 0x62, 0x75, 0x73,
+ 0x69, 0x6e, 0x65, 0x73, 0x73, 0x6d, 0x61, 0x6e,
+ 0x20, 0x69, 0x73, 0x20, 0x73, 0x75, 0x70, 0x70,
+ 0x6f, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x00, 0x67, 0x6c, 0x75,
+ 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x73, 0x6d, 0x69, 0x6c, 0x65, 0x2e,
+ 0x00, 0x00, 0x1d, 0x00, 0x73, 0x75, 0x70, 0x65,
+ 0x72, 0x20, 0x67, 0x6c, 0x75, 0x65, 0x00, 0x49,
+ 0x74, 0x27, 0x73, 0x20, 0x74, 0x75, 0x72, 0x62,
+ 0x6f, 0x20, 0x6d, 0x65, 0x67, 0x61, 0x20, 0x67,
+ 0x69, 0x67, 0x61, 0x20, 0x73, 0x75, 0x70, 0x65,
+ 0x72, 0x20, 0x75, 0x6c, 0x74, 0x72, 0x61, 0x00,
+ 0x66, 0x61, 0x73, 0x74, 0x20, 0x64, 0x72, 0x79,
+ 0x69, 0x6e, 0x67, 0x20, 0x67, 0x6c, 0x75, 0x65,
+ 0x20, 0x70, 0x6c, 0x75, 0x73, 0x2e, 0x00, 0x00,
+ 0x1e, 0x00, 0x63, 0x6f, 0x6e, 0x65, 0x20, 0x26,
+ 0x20, 0x6e, 0x65, 0x65, 0x64, 0x6c, 0x65, 0x00,
+ 0x53, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x69, 0x6e,
+ 0x67, 0x20, 0x69, 0x73, 0x20, 0x73, 0x74, 0x69,
+ 0x6c, 0x6c, 0x20, 0x6d, 0x69, 0x73, 0x73, 0x69,
+ 0x6e, 0x67, 0x20, 0x68, 0x65, 0x72, 0x65, 0x2e,
+ 0x2e, 0x2e, 0x00, 0x00, 0x1f, 0x00, 0x63, 0x6f,
+ 0x6e, 0x65, 0x20, 0x26, 0x20, 0x66, 0x65, 0x61,
+ 0x74, 0x68, 0x65, 0x72, 0x00, 0x53, 0x6f, 0x6d,
+ 0x65, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x69,
+ 0x73, 0x20, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x20,
+ 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x20,
+ 0x68, 0x65, 0x72, 0x65, 0x2e, 0x2e, 0x2e, 0x00,
+ 0x00, 0x20, 0x00, 0x64, 0x61, 0x72, 0x74, 0x00,
+ 0x4e, 0x6f, 0x77, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x49, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x20, 0x69,
+ 0x73, 0x20, 0x61, 0x20, 0x74, 0x61, 0x72, 0x67,
+ 0x65, 0x74, 0x21, 0x00, 0x00, 0x21, 0x00, 0x64,
+ 0x69, 0x72, 0x74, 0x79, 0x20, 0x66, 0x65, 0x61,
+ 0x74, 0x68, 0x65, 0x72, 0x20, 0x64, 0x75, 0x73,
+ 0x74, 0x65, 0x72, 0x00, 0x49, 0x74, 0x27, 0x73,
+ 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x6d, 0x79, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x6f, 0x69, 0x6c,
+ 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x73, 0x6f,
+ 0x6f, 0x74, 0x2e, 0x00, 0x00, 0x22, 0x00, 0x70,
+ 0x61, 0x69, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x70,
+ 0x6f, 0x74, 0x61, 0x74, 0x6f, 0x65, 0x00, 0x54,
+ 0x68, 0x65, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20,
+ 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e,
+ 0x63, 0x65, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65,
+ 0x65, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x67, 0x72,
+ 0x65, 0x6e, 0x61, 0x64, 0x65, 0x00, 0x69, 0x73,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x6f,
+ 0x74, 0x61, 0x74, 0x6f, 0x65, 0x65, 0x73, 0x20,
+ 0x75, 0x73, 0x75, 0x61, 0x6c, 0x6c, 0x79, 0x20,
+ 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x20, 0x62, 0x6c,
+ 0x6f, 0x77, 0x20, 0x75, 0x70, 0x2e, 0x00, 0x00,
+ 0x23, 0x00, 0x63, 0x61, 0x72, 0x20, 0x6a, 0x61,
+ 0x63, 0x6b, 0x00, 0x4c, 0x6f, 0x6f, 0x6b, 0x73,
+ 0x20, 0x72, 0x65, 0x6c, 0x69, 0x61, 0x62, 0x6c,
+ 0x65, 0x2e, 0x00, 0x00, 0x24, 0x00, 0x64, 0x69,
+ 0x6e, 0x6f, 0x20, 0x62, 0x6f, 0x6e, 0x65, 0x00,
+ 0x49, 0x74, 0x27, 0x73, 0x20, 0x62, 0x69, 0x67,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x6c,
+ 0x6c, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x72,
+ 0x76, 0x65, 0x64, 0x2e, 0x20, 0x49, 0x74, 0x20,
+ 0x6d, 0x75, 0x73, 0x74, 0x20, 0x68, 0x61, 0x76,
+ 0x65, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x00, 0x61,
+ 0x20, 0x72, 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x20,
+ 0x62, 0x69, 0x67, 0x2c, 0x20, 0x65, 0x72, 0x2e,
+ 0x2e, 0x2e, 0x2c, 0x20, 0x61, 0x6e, 0x69, 0x6d,
+ 0x61, 0x6c, 0x2c, 0x20, 0x49, 0x20, 0x74, 0x68,
+ 0x69, 0x6e, 0x6b, 0x2e, 0x2e, 0x2e, 0x00, 0x00,
+ 0x25, 0x00, 0x73, 0x68, 0x6f, 0x76, 0x65, 0x6c,
+ 0x00, 0x49, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x50,
+ 0x4c, 0x41, 0x59, 0x20, 0x44, 0x49, 0x47, 0x47,
+ 0x45, 0x52, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x69, 0x74, 0x2e, 0x20, 0x53, 0x6f, 0x20, 0x74,
+ 0x6f, 0x20, 0x73, 0x70, 0x65, 0x61, 0x6b, 0x2e,
+ 0x00, 0x00, 0x26, 0x00, 0x72, 0x6f, 0x70, 0x65,
+ 0x00, 0x4c, 0x6f, 0x6f, 0x6b, 0x73, 0x20, 0x73,
+ 0x74, 0x72, 0x6f, 0x6e, 0x67, 0x2e, 0x00, 0x00,
+ 0x27, 0x00, 0x6d, 0x61, 0x73, 0x6b, 0x00, 0x49,
+ 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x68,
+ 0x65, 0x6c, 0x70, 0x20, 0x6d, 0x65, 0x20, 0x73,
+ 0x65, 0x65, 0x20, 0x62, 0x65, 0x74, 0x74, 0x65,
+ 0x72, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x2e, 0x00, 0x00, 0x28,
+ 0x00, 0x66, 0x69, 0x6e, 0x73, 0x00, 0x54, 0x68,
+ 0x65, 0x79, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x68, 0x65, 0x6c, 0x70, 0x20, 0x6d, 0x65, 0x20,
+ 0x66, 0x65, 0x65, 0x6c, 0x20, 0x6d, 0x6f, 0x72,
+ 0x65, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x6d,
+ 0x79, 0x00, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x20, 0x62, 0x72, 0x6f,
+ 0x74, 0x68, 0x65, 0x72, 0x73, 0x2e, 0x00, 0x00,
+ 0x29, 0x00, 0x64, 0x69, 0x76, 0x69, 0x6e, 0x67,
+ 0x20, 0x65, 0x71, 0x75, 0x69, 0x70, 0x6d, 0x65,
+ 0x6e, 0x74, 0x00, 0x57, 0x61, 0x74, 0x63, 0x68,
+ 0x20, 0x6f, 0x75, 0x74, 0x2c, 0x20, 0x77, 0x61,
+ 0x74, 0x65, 0x72, 0x21, 0x20, 0x48, 0x65, 0x72,
+ 0x65, 0x20, 0x49, 0x20, 0x63, 0x6f, 0x6d, 0x65,
+ 0x21, 0x00, 0x00, 0x2a, 0x00, 0x61, 0x6e, 0x63,
+ 0x68, 0x6f, 0x72, 0x00, 0x4e, 0x6f, 0x74, 0x20,
+ 0x62, 0x69, 0x67, 0x2c, 0x20, 0x62, 0x75, 0x74,
+ 0x20, 0x68, 0x65, 0x61, 0x76, 0x79, 0x20, 0x65,
+ 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x74, 0x6f,
+ 0x20, 0x73, 0x69, 0x6e, 0x6b, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x62, 0x6f, 0x61, 0x74, 0x2e, 0x00,
+ 0x00, 0x2b, 0x00, 0x67, 0x72, 0x61, 0x70, 0x70,
+ 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x6f, 0x6f,
+ 0x6b, 0x00, 0x57, 0x61, 0x74, 0x63, 0x68, 0x20,
+ 0x6f, 0x75, 0x74, 0x2c, 0x20, 0x6d, 0x6f, 0x75,
+ 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x2c, 0x20,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x49, 0x20, 0x63,
+ 0x6f, 0x6d, 0x65, 0x21, 0x00, 0x00, 0x2c, 0x00,
+ 0x73, 0x69, 0x63, 0x6b, 0x6c, 0x65, 0x00, 0x49,
+ 0x74, 0x27, 0x73, 0x20, 0x73, 0x6f, 0x20, 0x62,
+ 0x6c, 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x49, 0x20, 0x63, 0x6f, 0x75,
+ 0x6c, 0x64, 0x6e, 0x27, 0x74, 0x20, 0x65, 0x76,
+ 0x65, 0x6e, 0x20, 0x63, 0x75, 0x74, 0x00, 0x62,
+ 0x75, 0x74, 0x74, 0x65, 0x72, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x69, 0x74, 0x2e, 0x00, 0x00,
+ 0x2d, 0x00, 0x73, 0x6f, 0x6d, 0x65, 0x77, 0x68,
+ 0x61, 0x74, 0x20, 0x72, 0x6f, 0x74, 0x74, 0x65,
+ 0x6e, 0x20, 0x63, 0x68, 0x65, 0x65, 0x73, 0x65,
+ 0x00, 0x52, 0x65, 0x6d, 0x69, 0x6e, 0x64, 0x73,
+ 0x20, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6d,
+ 0x79, 0x20, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x00,
+ 0x00, 0x2e, 0x00, 0x73, 0x68, 0x61, 0x72, 0x70,
+ 0x65, 0x6e, 0x65, 0x64, 0x20, 0x73, 0x69, 0x63,
+ 0x6b, 0x6c, 0x65, 0x00, 0x4c, 0x61, 0x6d, 0x62,
+ 0x73, 0x2c, 0x20, 0x62, 0x65, 0x20, 0x73, 0x69,
+ 0x6c, 0x65, 0x6e, 0x74, 0x2e, 0x20, 0x48, 0x65,
+ 0x72, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x61, 0x69,
+ 0x6e, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x2f, 0x00,
+ 0x68, 0x61, 0x6e, 0x64, 0x6b, 0x65, 0x72, 0x63,
+ 0x68, 0x69, 0x65, 0x66, 0x00, 0x54, 0x68, 0x65,
+ 0x20, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x20, 0x6d,
+ 0x75, 0x73, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65,
+ 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x62, 0x69,
+ 0x67, 0x20, 0x6e, 0x6f, 0x73, 0x65, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x20, 0x6e,
+ 0x65, 0x65, 0x64, 0x73, 0x00, 0x74, 0x6f, 0x20,
+ 0x75, 0x73, 0x65, 0x20, 0x61, 0x20, 0x77, 0x68,
+ 0x6f, 0x6c, 0x65, 0x20, 0x62, 0x61, 0x72, 0x20,
+ 0x6f, 0x66, 0x20, 0x73, 0x6f, 0x61, 0x70, 0x20,
+ 0x6a, 0x75, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x20,
+ 0x77, 0x61, 0x73, 0x68, 0x20, 0x69, 0x74, 0x2e,
+ 0x00, 0x00, 0x30, 0x01, 0x6d, 0x6f, 0x75, 0x73,
+ 0x65, 0x00, 0x49, 0x74, 0x27, 0x73, 0x20, 0x76,
+ 0x65, 0x72, 0x79, 0x20, 0x61, 0x63, 0x74, 0x69,
+ 0x76, 0x65, 0x2e, 0x00, 0x00, 0x31, 0x00, 0x72,
+ 0x6f, 0x63, 0x6b, 0x00, 0x49, 0x74, 0x27, 0x73,
+ 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x72, 0x65,
+ 0x67, 0x75, 0x6c, 0x61, 0x72, 0x2c, 0x20, 0x6a,
+ 0x75, 0x73, 0x74, 0x20, 0x6c, 0x69, 0x6b, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6e, 0x6f,
+ 0x77, 0x62, 0x61, 0x6c, 0x6c, 0x2e, 0x00, 0x00,
+ 0x32, 0x01, 0x6e, 0x75, 0x67, 0x67, 0x65, 0x74,
+ 0x00, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x3a,
+ 0x20, 0x41, 0x75, 0x2c, 0x20, 0x61, 0x74, 0x6f,
+ 0x6d, 0x69, 0x63, 0x20, 0x6e, 0x6f, 0x3a, 0x20,
+ 0x37, 0x39, 0x2c, 0x20, 0x61, 0x74, 0x6f, 0x6d,
+ 0x69, 0x63, 0x20, 0x77, 0x74, 0x2e, 0x3a, 0x20,
+ 0x31, 0x39, 0x36, 0x2e, 0x39, 0x37, 0x2e, 0x00,
+ 0x49, 0x6e, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x3a, 0x20,
+ 0x47, 0x4f, 0x4c, 0x44, 0x21, 0x21, 0x21, 0x20,
+ 0x59, 0x65, 0x73, 0x21, 0x20, 0x59, 0x65, 0x73,
+ 0x21, 0x00, 0x00, 0x33, 0x00, 0x62, 0x61, 0x6e,
+ 0x6b, 0x6e, 0x6f, 0x74, 0x65, 0x00, 0x00, 0x00,
+ 0x34, 0x00, 0x64, 0x69, 0x63, 0x74, 0x61, 0x70,
+ 0x68, 0x6f, 0x6e, 0x65, 0x00, 0x54, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e,
+ 0x6f, 0x20, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72,
+ 0x69, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x73, 0x69,
+ 0x64, 0x65, 0x2e, 0x00, 0x00, 0x35, 0x00, 0x70,
+ 0x6f, 0x6c, 0x61, 0x72, 0x6f, 0x69, 0x64, 0x00,
+ 0x49, 0x74, 0x27, 0x73, 0x20, 0x72, 0x65, 0x61,
+ 0x64, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x61,
+ 0x6b, 0x65, 0x20, 0x61, 0x20, 0x70, 0x69, 0x63,
+ 0x74, 0x75, 0x72, 0x65, 0x2e, 0x00, 0x00, 0x36,
+ 0x00, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x20, 0x74,
+ 0x61, 0x70, 0x65, 0x00, 0x49, 0x74, 0x20, 0x68,
+ 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x20, 0x6c, 0x61,
+ 0x62, 0x65, 0x6c, 0x2e, 0x00, 0x00, 0x37, 0x00,
+ 0x73, 0x68, 0x65, 0x65, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x70, 0x61, 0x70, 0x65, 0x72, 0x00, 0x54,
+ 0x68, 0x65, 0x72, 0x65, 0x27, 0x73, 0x20, 0x6e,
+ 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x69,
+ 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6e, 0x74,
+ 0x20, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x20, 0x69,
+ 0x74, 0x2e, 0x00, 0x00, 0x38, 0x00, 0x63, 0x6f,
+ 0x67, 0x6e, 0x61, 0x63, 0x00, 0x46, 0x61, 0x6e,
+ 0x63, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20,
+ 0x6a, 0x75, 0x73, 0x74, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x61, 0x6e, 0x20, 0x65, 0x78, 0x63, 0x75,
+ 0x73, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64,
+ 0x72, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x2e,
+ 0x00, 0x00, 0x39, 0x00, 0x72, 0x65, 0x6d, 0x6f,
+ 0x74, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72,
+ 0x6f, 0x6c, 0x00, 0x49, 0x74, 0x20, 0x68, 0x61,
+ 0x73, 0x20, 0x75, 0x73, 0x65, 0x72, 0x2d, 0x66,
+ 0x72, 0x69, 0x65, 0x6e, 0x64, 0x6c, 0x79, 0x20,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63,
+ 0x65, 0x2e, 0x00, 0x4f, 0x6e, 0x65, 0x20, 0x63,
+ 0x61, 0x6e, 0x20, 0x70, 0x6c, 0x61, 0x79, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x74, 0x6f, 0x70,
+ 0x2e, 0x00, 0x00, 0x3a, 0x00, 0x69, 0x63, 0x65,
+ 0x20, 0x74, 0x6f, 0x6e, 0x67, 0x73, 0x00, 0x56,
+ 0x65, 0x72, 0x79, 0x20, 0x68, 0x61, 0x6e, 0x64,
+ 0x79, 0x20, 0x74, 0x6f, 0x6f, 0x6c, 0x2e, 0x00,
+ 0x00, 0x3b, 0x00, 0x63, 0x6f, 0x72, 0x6b, 0x00,
+ 0x49, 0x74, 0x27, 0x73, 0x20, 0x61, 0x20, 0x73,
+ 0x74, 0x6f, 0x70, 0x70, 0x65, 0x72, 0x20, 0x6b,
+ 0x69, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x63,
+ 0x6f, 0x72, 0x6b, 0x2e, 0x00, 0x00, 0x3c, 0x00,
+ 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x20,
+ 0x63, 0x6f, 0x72, 0x6b, 0x00, 0x4e, 0x6f, 0x77,
+ 0x20, 0x69, 0x74, 0x27, 0x73, 0x20, 0x6d, 0x6f,
+ 0x72, 0x65, 0x20, 0x61, 0x70, 0x70, 0x72, 0x6f,
+ 0x70, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x00, 0x00,
+ 0x3d, 0x00, 0x70, 0x68, 0x6f, 0x74, 0x6f, 0x00,
+ 0x49, 0x74, 0x27, 0x73, 0x20, 0x61, 0x20, 0x70,
+ 0x68, 0x6f, 0x74, 0x6f, 0x20, 0x6f, 0x66, 0x20,
+ 0x4a, 0x6f, 0x68, 0x6e, 0x20, 0x4e, 0x6f, 0x74,
+ 0x79, 0x2e, 0x20, 0x49, 0x20, 0x63, 0x61, 0x75,
+ 0x67, 0x68, 0x74, 0x20, 0x68, 0x69, 0x6d, 0x00,
+ 0x77, 0x68, 0x65, 0x6e, 0x20, 0x68, 0x65, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x73, 0x69, 0x6e, 0x67,
+ 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x68, 0x69, 0x67, 0x68, 0x20, 0x43, 0x2e, 0x20,
+ 0x59, 0x75, 0x63, 0x6b, 0x21, 0x00, 0x00, 0x3e,
+ 0x00, 0x63, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x00,
+ 0x54, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x62, 0x65,
+ 0x6c, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x62, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x20,
+ 0x73, 0x61, 0x79, 0x73, 0x20, 0x69, 0x74, 0x27,
+ 0x73, 0x00, 0x27, 0x4f, 0x52, 0x49, 0x47, 0x49,
+ 0x4e, 0x41, 0x4c, 0x20, 0x4d, 0x45, 0x58, 0x49,
+ 0x43, 0x41, 0x4e, 0x20, 0x43, 0x48, 0x49, 0x4c,
+ 0x4c, 0x49, 0x27, 0x2e, 0x20, 0x53, 0x75, 0x72,
+ 0x65, 0x2e, 0x00, 0x00, 0x3f, 0x00, 0x70, 0x61,
+ 0x73, 0x74, 0x72, 0x79, 0x20, 0x72, 0x6f, 0x6c,
+ 0x6c, 0x65, 0x72, 0x00, 0x49, 0x74, 0x27, 0x73,
+ 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x68, 0x61,
+ 0x72, 0x64, 0x20, 0x77, 0x6f, 0x6f, 0x64, 0x2e,
+ 0x00, 0x00, 0x40, 0x00, 0x66, 0x61, 0x6b, 0x65,
+ 0x20, 0x63, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x00,
+ 0x4e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x27, 0x73, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20,
+ 0x49, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x73,
+ 0x74, 0x72, 0x6f, 0x6e, 0x67, 0x20, 0x73, 0x65,
+ 0x61, 0x73, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x2e,
+ 0x00, 0x00, 0x41, 0x00, 0x6c, 0x61, 0x62, 0x65,
+ 0x6c, 0x00, 0x27, 0x4f, 0x52, 0x49, 0x47, 0x49,
+ 0x4e, 0x41, 0x4c, 0x20, 0x4d, 0x45, 0x58, 0x49,
+ 0x43, 0x41, 0x4e, 0x20, 0x43, 0x48, 0x49, 0x4c,
+ 0x4c, 0x49, 0x27, 0x2e, 0x00, 0x00, 0x42, 0x00,
+ 0x62, 0x61, 0x74, 0x74, 0x65, 0x72, 0x69, 0x65,
+ 0x73, 0x00, 0x49, 0x74, 0x27, 0x73, 0x20, 0x61,
+ 0x20, 0x70, 0x61, 0x69, 0x72, 0x20, 0x6f, 0x66,
+ 0x20, 0x6e, 0x65, 0x77, 0x20, 0x62, 0x61, 0x74,
+ 0x74, 0x65, 0x72, 0x69, 0x65, 0x73, 0x2e, 0x00,
+ 0x00, 0x43, 0x00, 0x64, 0x69, 0x63, 0x74, 0x61,
+ 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x00, 0x27, 0x4f,
+ 0x6e, 0x65, 0x2d, 0x74, 0x77, 0x6f, 0x2d, 0x6f,
+ 0x6e, 0x65, 0x2d, 0x74, 0x77, 0x6f, 0x2c, 0x20,
+ 0x69, 0x74, 0x27, 0x73, 0x20, 0x6d, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x00,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x6e, 0x6c, 0x79,
+ 0x20, 0x4d, 0x61, 0x72, 0x6b, 0x20, 0x4d, 0x43,
+ 0x2e, 0x2e, 0x2e, 0x2e, 0x27, 0x00, 0x49, 0x74,
+ 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x00,
+ 0x00, 0x44, 0x01, 0x62, 0x75, 0x72, 0x6e, 0x69,
+ 0x6e, 0x67, 0x20, 0x70, 0x61, 0x70, 0x65, 0x72,
+ 0x00, 0x41, 0x6d, 0x61, 0x7a, 0x69, 0x6e, 0x67,
+ 0x2c, 0x20, 0x69, 0x73, 0x6e, 0x27, 0x74, 0x20,
+ 0x69, 0x74, 0x3f, 0x00, 0x28, 0x4e, 0x6f, 0x74,
+ 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x6e, 0x74,
+ 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x75, 0x6e, 0x62,
+ 0x65, 0x6c, 0x69, 0x65, 0x76, 0x61, 0x62, 0x6c,
+ 0x65, 0x29, 0x2e, 0x00, 0x00, 0x45, 0x00, 0x6d,
+ 0x65, 0x61, 0x74, 0x00, 0x54, 0x68, 0x65, 0x72,
+ 0x65, 0x27, 0x73, 0x20, 0x76, 0x65, 0x61, 0x6c,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x70, 0x6c, 0x61, 0x73, 0x74, 0x69, 0x63, 0x20,
+ 0x62, 0x61, 0x67, 0x2e, 0x00, 0x00, 0x46, 0x00,
+ 0x70, 0x6c, 0x61, 0x73, 0x74, 0x69, 0x63, 0x20,
+ 0x62, 0x61, 0x67, 0x00, 0x47, 0x65, 0x65, 0x2c,
+ 0x20, 0x49, 0x20, 0x68, 0x6f, 0x70, 0x65, 0x20,
+ 0x69, 0x74, 0x27, 0x73, 0x20, 0x72, 0x65, 0x63,
+ 0x79, 0x63, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e,
+ 0x20, 0x49, 0x20, 0x63, 0x6f, 0x75, 0x6c, 0x64,
+ 0x6e, 0x27, 0x74, 0x00, 0x73, 0x6c, 0x65, 0x65,
+ 0x70, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x77,
+ 0x69, 0x73, 0x65, 0x2e, 0x00, 0x00, 0x47, 0x00,
+ 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x00, 0x54, 0x68,
+ 0x65, 0x73, 0x65, 0x20, 0x73, 0x6f, 0x63, 0x6b,
+ 0x73, 0x20, 0x73, 0x75, 0x63, 0x6b, 0x2e, 0x00,
+ 0x00, 0x48, 0x00, 0x70, 0x69, 0x6c, 0x6c, 0x73,
+ 0x00, 0x54, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61,
+ 0x72, 0x65, 0x20, 0x61, 0x62, 0x6f, 0x75, 0x74,
+ 0x20, 0x74, 0x77, 0x65, 0x6e, 0x74, 0x79, 0x20,
+ 0x70, 0x69, 0x6c, 0x6c, 0x73, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6a, 0x61,
+ 0x72, 0x2e, 0x00, 0x00, 0x49, 0x00, 0x68, 0x61,
+ 0x6e, 0x64, 0x6c, 0x65, 0x00, 0x49, 0x74, 0x20,
+ 0x6c, 0x6f, 0x6f, 0x6b, 0x73, 0x20, 0x6c, 0x69,
+ 0x6b, 0x65, 0x20, 0x61, 0x20, 0x73, 0x74, 0x61,
+ 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x64, 0x6f,
+ 0x6f, 0x72, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c,
+ 0x65, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x4a, 0x00,
+ 0x63, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x00, 0x4e,
+ 0x69, 0x63, 0x65, 0x20, 0x62, 0x6f, 0x74, 0x74,
+ 0x6c, 0x65, 0x2e, 0x20, 0x49, 0x20, 0x6c, 0x69,
+ 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x70, 0x65, 0x2e, 0x00, 0x00, 0x4b,
+ 0x00, 0x70, 0x61, 0x73, 0x73, 0x00, 0x22, 0x4c,
+ 0x65, 0x74, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20,
+ 0x67, 0x75, 0x79, 0x20, 0x69, 0x6e, 0x2e, 0x20,
+ 0x52, 0x47, 0x42, 0x20, 0x43, 0x68, 0x69, 0x65,
+ 0x66, 0x2e, 0x22, 0x00, 0x00, 0x4c, 0x00, 0x62,
+ 0x75, 0x6c, 0x62, 0x00, 0x49, 0x74, 0x27, 0x73,
+ 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74,
+ 0x65, 0x6c, 0x79, 0x20, 0x75, 0x73, 0x65, 0x6c,
+ 0x65, 0x73, 0x73, 0x2e, 0x00, 0x00, 0x4d, 0x00,
+ 0x6a, 0x61, 0x69, 0x6c, 0x20, 0x6b, 0x65, 0x79,
+ 0x00, 0x53, 0x75, 0x72, 0x70, 0x72, 0x69, 0x73,
+ 0x69, 0x6e, 0x67, 0x6c, 0x79, 0x2c, 0x20, 0x69,
+ 0x74, 0x27, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6b, 0x65, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6a, 0x61, 0x69, 0x6c, 0x2e,
+ 0x00, 0x00, 0x4e, 0x00, 0x64, 0x65, 0x6c, 0x69,
+ 0x63, 0x61, 0x74, 0x65, 0x20, 0x70, 0x6c, 0x61,
+ 0x6e, 0x74, 0x00, 0x57, 0x68, 0x6f, 0x61, 0x2c,
+ 0x20, 0x69, 0x74, 0x20, 0x74, 0x69, 0x63, 0x6b,
+ 0x6c, 0x65, 0x73, 0x21, 0x00, 0x00, 0x4f, 0x00,
+ 0x53, 0x77, 0x69, 0x73, 0x73, 0x20, 0x41, 0x72,
+ 0x6d, 0x79, 0x20, 0x6b, 0x6e, 0x69, 0x66, 0x65,
+ 0x00, 0x49, 0x20, 0x77, 0x6f, 0x6e, 0x64, 0x65,
+ 0x72, 0x20, 0x69, 0x66, 0x20, 0x69, 0x74, 0x27,
+ 0x73, 0x20, 0x67, 0x6f, 0x74, 0x20, 0x61, 0x20,
+ 0x54, 0x56, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x73, 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x2e,
+ 0x00, 0x00, 0x50, 0x00, 0x73, 0x70, 0x72, 0x69,
+ 0x6e, 0x67, 0x00, 0x49, 0x20, 0x63, 0x6f, 0x75,
+ 0x6c, 0x64, 0x20, 0x6c, 0x61, 0x75, 0x6e, 0x63,
+ 0x68, 0x20, 0x61, 0x20, 0x72, 0x6f, 0x63, 0x6b,
+ 0x65, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x69, 0x74, 0x21, 0x00, 0x00, 0x51, 0x00, 0x73,
+ 0x68, 0x6f, 0x76, 0x65, 0x6c, 0x00, 0x4e, 0x69,
+ 0x63, 0x65, 0x2c, 0x20, 0x68, 0x61, 0x6e, 0x64,
+ 0x79, 0x20, 0x74, 0x6f, 0x6f, 0x6c, 0x2e, 0x00,
+ 0x00, 0x52, 0x00, 0x6b, 0x61, 0x6c, 0x65, 0x69,
+ 0x64, 0x6f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x00,
+ 0x49, 0x20, 0x63, 0x6f, 0x75, 0x6c, 0x64, 0x20,
+ 0x73, 0x70, 0x65, 0x6e, 0x64, 0x20, 0x6d, 0x79,
+ 0x20, 0x77, 0x68, 0x6f, 0x6c, 0x65, 0x20, 0x6c,
+ 0x69, 0x66, 0x65, 0x20, 0x6c, 0x6f, 0x6f, 0x6b,
+ 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x72, 0x6f,
+ 0x75, 0x67, 0x68, 0x00, 0x74, 0x68, 0x69, 0x73,
+ 0x2e, 0x20, 0x57, 0x65, 0x6c, 0x6c, 0x2c, 0x20,
+ 0x6c, 0x65, 0x74, 0x27, 0x73, 0x20, 0x73, 0x61,
+ 0x79, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20, 0x6d,
+ 0x69, 0x6e, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x00,
+ 0x4f, 0x68, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x72, 0x69, 0x67, 0x68, 0x74, 0x2c, 0x20, 0x69,
+ 0x74, 0x27, 0x73, 0x20, 0x62, 0x6f, 0x72, 0x69,
+ 0x6e, 0x67, 0x2e, 0x00, 0x00, 0x53, 0x00, 0x22,
+ 0x53, 0x6f, 0x6c, 0x64, 0x69, 0x65, 0x72, 0x20,
+ 0x4e, 0x65, 0x77, 0x73, 0x22, 0x00, 0x49, 0x74,
+ 0x27, 0x73, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65,
+ 0x20, 0x61, 0x73, 0x20, 0x77, 0x6f, 0x6d, 0x65,
+ 0x6e, 0x27, 0x73, 0x20, 0x6d, 0x61, 0x67, 0x61,
+ 0x7a, 0x69, 0x6e, 0x65, 0x73, 0x2c, 0x00, 0x62,
+ 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65,
+ 0x20, 0x61, 0x72, 0x65, 0x20, 0x67, 0x75, 0x6e,
+ 0x73, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x65, 0x61,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x70, 0x65, 0x72,
+ 0x66, 0x75, 0x6d, 0x65, 0x73, 0x2e, 0x00, 0x49,
+ 0x74, 0x27, 0x73, 0x20, 0x63, 0x6f, 0x6f, 0x6c,
+ 0x20, 0x61, 0x6e, 0x79, 0x77, 0x61, 0x79, 0x2e,
+ 0x00, 0x00, 0x54, 0x00, 0x67, 0x72, 0x65, 0x6e,
+ 0x61, 0x64, 0x65, 0x00, 0x49, 0x20, 0x6d, 0x75,
+ 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x63, 0x72,
+ 0x61, 0x7a, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x70,
+ 0x75, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x6d, 0x79,
+ 0x20, 0x70, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2e,
+ 0x00, 0x53, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x69,
+ 0x6e, 0x67, 0x20, 0x68, 0x6f, 0x72, 0x72, 0x69,
+ 0x62, 0x6c, 0x65, 0x20, 0x6d, 0x69, 0x67, 0x68,
+ 0x74, 0x20, 0x68, 0x61, 0x70, 0x70, 0x65, 0x6e,
+ 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x55, 0x00, 0x6d,
+ 0x75, 0x67, 0x00, 0x49, 0x74, 0x27, 0x73, 0x20,
+ 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x00, 0x00,
+ 0x56, 0x00, 0x6d, 0x75, 0x67, 0x20, 0x66, 0x75,
+ 0x6c, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x75,
+ 0x64, 0x00, 0x57, 0x68, 0x79, 0x20, 0x64, 0x69,
+ 0x64, 0x20, 0x49, 0x20, 0x66, 0x69, 0x6c, 0x6c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x75, 0x67,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x75,
+ 0x64, 0x3f, 0x00, 0x00, 0x54, 0x68, 0x61, 0x74,
+ 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x73, 0x20, 0x6e,
+ 0x6f, 0x20, 0x73, 0x65, 0x6e, 0x73, 0x65, 0x21,
+ 0x00, 0x00, 0x57, 0x00, 0x63, 0x72, 0x75, 0x6d,
+ 0x62, 0x73, 0x00, 0x54, 0x68, 0x65, 0x73, 0x65,
+ 0x20, 0x61, 0x72, 0x65, 0x20, 0x73, 0x6f, 0x6d,
+ 0x65, 0x20, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x62, 0x72, 0x65,
+ 0x61, 0x64, 0x2e, 0x00, 0x00, 0x58, 0x00, 0x72,
+ 0x6f, 0x70, 0x65, 0x00, 0x49, 0x74, 0x27, 0x73,
+ 0x20, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x2e, 0x00,
+ 0x00, 0x59, 0x00, 0x72, 0x6f, 0x70, 0x65, 0x20,
+ 0x74, 0x69, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20,
+ 0x67, 0x72, 0x65, 0x6e, 0x61, 0x64, 0x65, 0x00,
+ 0x4d, 0x79, 0x20, 0x70, 0x61, 0x74, 0x65, 0x6e,
+ 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20,
+ 0x62, 0x6f, 0x6d, 0x62, 0x61, 0x73, 0x74, 0x69,
+ 0x63, 0x20, 0x79, 0x6f, 0x79, 0x6f, 0x2e, 0x00,
+ 0x00, 0x5a, 0x00, 0x6d, 0x65, 0x64, 0x69, 0x63,
+ 0x69, 0x6e, 0x65, 0x00, 0x54, 0x68, 0x65, 0x79,
+ 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x20, 0x6c, 0x69,
+ 0x6b, 0x65, 0x20, 0x73, 0x6c, 0x65, 0x65, 0x70,
+ 0x69, 0x6e, 0x67, 0x20, 0x70, 0x69, 0x6c, 0x6c,
+ 0x73, 0x2e, 0x00, 0x41, 0x6c, 0x74, 0x68, 0x6f,
+ 0x75, 0x67, 0x68, 0x20, 0x49, 0x20, 0x64, 0x6f,
+ 0x6e, 0x27, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65,
+ 0x20, 0x61, 0x6e, 0x79, 0x20, 0x69, 0x64, 0x65,
+ 0x61, 0x20, 0x77, 0x68, 0x79, 0x2e, 0x00, 0x00,
+ 0x5b, 0x00, 0x64, 0x72, 0x75, 0x67, 0x67, 0x65,
+ 0x64, 0x20, 0x66, 0x6f, 0x6f, 0x64, 0x00, 0x53,
+ 0x6d, 0x65, 0x6c, 0x6c, 0x73, 0x20, 0x6c, 0x69,
+ 0x6b, 0x65, 0x20, 0x54, 0x65, 0x65, 0x6e, 0x20,
+ 0x53, 0x70, 0x69, 0x72, 0x69, 0x74, 0x2e, 0x00,
+ 0x00, 0x5c, 0x01, 0x62, 0x69, 0x72, 0x64, 0x00,
+ 0x49, 0x74, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64,
+ 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x61, 0x20,
+ 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x64, 0x69,
+ 0x6e, 0x6e, 0x2e, 0x2e, 0x2e, 0x20, 0x49, 0x20,
+ 0x6d, 0x65, 0x61, 0x6e, 0x00, 0x66, 0x72, 0x69,
+ 0x65, 0x6e, 0x64, 0x2c, 0x20, 0x6f, 0x66, 0x20,
+ 0x63, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x2e, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0x01, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00,
+ 0x00, 0x01, 0xff, 0x00, 0x00, 0x02, 0xff, 0xff,
+ 0xff, 0x01, 0xff, 0x00, 0x00, 0x02, 0xff, 0x00,
+ 0x00, 0x01, 0xff, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x06, 0xff, 0xff, 0x00, 0x02, 0xff, 0x00,
+ 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
+ 0x00, 0x01, 0x02, 0xff, 0x00, 0x04, 0xff, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00,
+ 0x00, 0x0a, 0xff, 0x00, 0x00, 0x01, 0x0d, 0x00,
+ 0x00, 0x01, 0x02, 0xff, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x06, 0x07, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0x00, 0x01, 0x04, 0x02, 0x03, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0x00, 0xff, 0xff, 0x00, 0x00, 0x01, 0xff, 0xff,
+ 0x00, 0x01, 0x02, 0xff, 0x00, 0xff, 0xff, 0x00,
+ 0x00, 0x04, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00,
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x00,
+ 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff,
+ 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
+ 0x00, 0xf8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x28, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x67, 0x7c, 0x04, 0x4f, 0x29, 0x00,
+ 0x00, 0xec, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x2a, 0x66, 0x37, 0x03, 0xca, 0x0c, 0x00,
+ 0x00, 0x75, 0xbf, 0x91, 0x0c, 0x00, 0x00, 0x00,
+ 0x00, 0x99, 0x5f, 0x87, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x64, 0x34, 0xbe, 0x47, 0xad, 0x03, 0x86,
+ 0x02, 0x18, 0x20, 0xd4, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0xd6, 0x22, 0x58, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x0c, 0x67, 0xac, 0xf3, 0x00, 0x00, 0x00,
+ 0x00, 0xc3, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xdf, 0x27, 0xc8, 0x4d, 0x64, 0x08, 0x00,
+ 0x00, 0x4e, 0x7e, 0x5c, 0xe6, 0x00, 0x00, 0x00,
+ 0x00, 0x69, 0x0d, 0x27, 0x0d, 0x00, 0x00, 0x00,
+ 0x00, 0x4a, 0x0d, 0x45, 0x0d, 0x00, 0x00, 0x00,
+ 0x00, 0xb9, 0x48, 0x71, 0x12, 0x04, 0x27, 0x00,
+ 0x00, 0xdb, 0x73, 0xfe, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0xfc, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x5b, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x13, 0x40, 0x51, 0x93, 0x00, 0x00, 0x00,
+ 0x00, 0x13, 0x4f, 0x4f, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x7a, 0x50, 0x64, 0x5d, 0x6f, 0x04, 0x00,
+ 0x00, 0xa3, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x88, 0x02, 0x91, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0xce, 0x02, 0x77, 0x04, 0x2f, 0x1d, 0x00,
+ 0x00, 0x08, 0x69, 0x06, 0x23, 0x32, 0x4b, 0x3e,
+ 0x6c, 0x46, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xf6, 0x16, 0xc5, 0x13, 0x00, 0x00, 0x00,
+ 0x00, 0xfb, 0x0a, 0x21, 0x73, 0x68, 0x3b, 0x00,
+ 0x00, 0x9b, 0x15, 0x0d, 0x1a, 0x00, 0x00, 0x00,
+ 0x00, 0xce, 0xf7, 0x25, 0x6b, 0xcb, 0x13, 0x00,
+ 0x00, 0x33, 0xa5, 0xbf, 0x01, 0xb3, 0x10, 0x00,
+ 0x00, 0xcb, 0x13, 0x7c, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x7e, 0x0f, 0x14, 0x59, 0xc5, 0x13, 0x00,
+ 0x00, 0x95, 0x51, 0xce, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x4d, 0x29, 0xfc, 0x14, 0xe1, 0xa4, 0xad,
+ 0x8e, 0x07, 0x5b, 0x47, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0xbf, 0x52, 0x3c, 0x0e, 0xc5, 0x0e, 0x00,
+ 0x00, 0x44, 0x6b, 0xe0, 0x76, 0x97, 0x00, 0x00,
+ 0x00, 0x5a, 0x1a, 0xb8, 0xb3, 0x00, 0x00, 0x00,
+ 0x00, 0x6c, 0x66, 0x8f, 0xdc, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0xb4, 0x01, 0x6f, 0x04, 0xcb,
+ 0x07, 0x01, 0x09, 0xff, 0xff, 0x36, 0x09, 0x02,
+ 0x0a, 0x2d, 0x0a, 0xff, 0xff, 0x43, 0x0c, 0x75,
+ 0x0d, 0x0e, 0x0f, 0xb8, 0x0f, 0xff, 0xff, 0xdb,
+ 0x10, 0xac, 0x11, 0xd9, 0x12, 0x68, 0x14, 0xff,
+ 0xff, 0x85, 0x14, 0x28, 0x15, 0xff, 0xff, 0xde,
+ 0x16, 0x26, 0x17, 0xff, 0xff, 0x52, 0x17, 0x8c,
+ 0x17, 0x13, 0x19, 0x3e, 0x1a, 0x63, 0x1a, 0x84,
+ 0x1a, 0xc9, 0x1a, 0xf7, 0x1a, 0x27, 0x1b, 0x4a,
+ 0x1b, 0xff, 0xff, 0x97, 0x1c, 0xec, 0x1c, 0xff,
+ 0xff, 0x2c, 0x1d, 0xd8, 0x1d, 0xff, 0xff, 0x41,
+ 0x20, 0x5f, 0x21, 0xff, 0xff, 0x82, 0x25, 0xfe,
+ 0x25, 0xff, 0xff, 0x6f, 0x2b, 0xb2, 0x2b, 0xdd,
+ 0x2b, 0x5d, 0x2c, 0x9b, 0x2c, 0xff, 0xff, 0x02,
+ 0x31, 0x1b, 0x31, 0x37, 0x31, 0x6f, 0x31, 0xff,
+ 0xff, 0x7d, 0x31, 0x15, 0x32, 0xff, 0xff, 0x41,
+ 0x3e, 0xa3, 0x3e, 0x08, 0x3f, 0xea, 0x3f, 0xff,
+ 0xff, 0x0d, 0x40, 0x39, 0x44, 0x6a, 0x44, 0xff,
+ 0xff, 0xe2, 0x58, 0xc5, 0x59, 0x9d, 0x5a, 0xd7,
+ 0x5a, 0xff, 0xff, 0xf3, 0x5a, 0xa9, 0x5b, 0x53,
+ 0x5c, 0x99, 0x5c, 0x3e, 0x5d, 0xff, 0xff, 0x5b,
+ 0x5d, 0x0a, 0x5f, 0xae, 0x5f, 0xcf, 0x5f, 0xff,
+ 0xff, 0xfe, 0x5f, 0x88, 0x60, 0xff, 0xff, 0xf0,
+ 0x62, 0x18, 0x63, 0x47, 0x63, 0x6b, 0x63, 0x82,
+ 0x63, 0xff, 0xff, 0xf7, 0x6b, 0x7f, 0x6d, 0x7b,
+ 0x6e, 0xa4, 0x6e, 0xff, 0xff, 0xc0, 0x6e, 0xe9,
+ 0x6e, 0x03, 0x6f, 0xff, 0xff, 0x5e, 0x73, 0xb3,
+ 0x73, 0xe8, 0x73, 0xff, 0xff, 0xfc, 0x64, 0x4c,
+ 0x65, 0xab, 0x65, 0xff, 0xff, 0x03, 0x74, 0x59,
+ 0x74, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xdd, 0xec, 0x50,
+ 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75,
+ 0x6e, 0x64, 0x73, 0x00, 0x69, 0x41, 0x4e, 0x44,
+ 0x52, 0x5a, 0x45, 0x4a, 0x20, 0x44, 0x4f, 0x42,
+ 0x52, 0x5a, 0x59, 0x3b, 0x53, 0x4b, 0x49, 0x00,
+ 0x00, 0xe3, 0xd2, 0x50, 0x6d, 0x75, 0x73, 0x69,
+ 0x63, 0x00, 0x69, 0x52, 0x41, 0x44, 0x45, 0x4b,
+ 0x20, 0x53, 0x5a, 0x41, 0x4d, 0x52, 0x45, 0x4a,
+ 0x00, 0x00, 0xd7, 0xe6, 0x50, 0x61, 0x6e, 0x69,
+ 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x67, 0x72, 0x61, 0x70, 0x68,
+ 0x69, 0x63, 0x73, 0x00, 0x69, 0x47, 0x52, 0x5a,
+ 0x45, 0x47, 0x4f, 0x52, 0x5a, 0x20, 0x4d, 0x49,
+ 0x45, 0x43, 0x48, 0x4f, 0x57, 0x53, 0x4b, 0x49,
+ 0x00, 0x00, 0xd9, 0xe8, 0x50, 0x70, 0x72, 0x6f,
+ 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x69, 0x6e, 0x67,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x63, 0x72,
+ 0x69, 0x70, 0x74, 0x00, 0x69, 0x41, 0x44, 0x52,
+ 0x49, 0x41, 0x4e, 0x20, 0x43, 0x48, 0x4d, 0x49,
+ 0x45, 0x4c, 0x41, 0x52, 0x5a, 0x00, 0x00, 0xdd,
+ 0xec, 0x5c, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x74, 0x69, 0x72, 0x69,
+ 0x6e, 0x67, 0x20, 0x6a, 0x6f, 0x75, 0x72, 0x6e,
+ 0x65, 0x79, 0x2e, 0x2e, 0x2e, 0x00, 0x00, 0xdd,
+ 0xec, 0x5c, 0x54, 0x48, 0x45, 0x20, 0x45, 0x4e,
+ 0x44, 0x00, 0x00, 0x70, 0x72, 0x6f, 0x67, 0x72,
+ 0x61, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x00, 0x41,
+ 0x44, 0x52, 0x49, 0x41, 0x4e, 0x20, 0x43, 0x48,
+ 0x4d, 0x49, 0x45, 0x4c, 0x41, 0x52, 0x5a, 0x00,
+ 0x20, 0x00, 0x20, 0x00, 0x61, 0x6e, 0x69, 0x6d,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x47, 0x52,
+ 0x5a, 0x45, 0x47, 0x4f, 0x52, 0x5a, 0x20, 0x4d,
+ 0x49, 0x45, 0x43, 0x48, 0x4f, 0x57, 0x53, 0x4b,
+ 0x49, 0x00, 0x20, 0x00, 0x20, 0x00, 0x61, 0x64,
+ 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c,
+ 0x20, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x00, 0x54, 0x4f, 0x4d, 0x41,
+ 0x53, 0x5a, 0x20, 0x50, 0x49, 0x4c, 0x49, 0x4b,
+ 0x00, 0x20, 0x00, 0x20, 0x00, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x73,
+ 0x00, 0x41, 0x4e, 0x44, 0x52, 0x5a, 0x45, 0x4a,
+ 0x20, 0x44, 0x4f, 0x42, 0x52, 0x5a, 0x59, 0x4e,
+ 0x53, 0x4b, 0x49, 0x00, 0x20, 0x00, 0x20, 0x00,
+ 0x6d, 0x75, 0x73, 0x69, 0x63, 0x00, 0x52, 0x41,
+ 0x44, 0x45, 0x4b, 0x20, 0x53, 0x5a, 0x41, 0x4d,
+ 0x52, 0x45, 0x4a, 0x00, 0x20, 0x00, 0x20, 0x00,
+ 0x63, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x61, 0x72,
+ 0x74, 0x00, 0x44, 0x41, 0x52, 0x49, 0x55, 0x53,
+ 0x5a, 0x20, 0x41, 0x4e, 0x41, 0x43, 0x4b, 0x49,
+ 0x00, 0x20, 0x00, 0x20, 0x00, 0x74, 0x72, 0x61,
+ 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x20, 0x68, 0x65, 0x6c, 0x70, 0x00, 0x50, 0x45,
+ 0x54, 0x45, 0x52, 0x20, 0x57, 0x45, 0x4c, 0x4c,
+ 0x53, 0x00, 0x20, 0x00, 0x20, 0x00, 0x62, 0x65,
+ 0x74, 0x61, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72,
+ 0x73, 0x00, 0x54, 0x4f, 0x4d, 0x41, 0x53, 0x5a,
+ 0x20, 0x46, 0x55, 0x52, 0x4d, 0x41, 0x4e, 0x49,
+ 0x55, 0x4b, 0x00, 0x50, 0x41, 0x54, 0x52, 0x59,
+ 0x4b, 0x20, 0x53, 0x41, 0x57, 0x49, 0x43, 0x4b,
+ 0x49, 0x00, 0x50, 0x41, 0x57, 0x45, 0x4c, 0x20,
+ 0x4d, 0x49, 0x45, 0x43, 0x48, 0x4f, 0x57, 0x53,
+ 0x4b, 0x49, 0x00, 0x4d, 0x41, 0x52, 0x45, 0x4b,
+ 0x20, 0x43, 0x48, 0x4d, 0x49, 0x45, 0x4c, 0x41,
+ 0x52, 0x5a, 0x00, 0x4a, 0x45, 0x44, 0x52, 0x45,
+ 0x4b, 0x20, 0x57, 0x49, 0x43, 0x48, 0x41, 0x00,
+ 0x4d, 0x52, 0x2e, 0x20, 0x4a, 0x4f, 0x48, 0x4e,
+ 0x20, 0x44, 0x4f, 0x45, 0x00, 0x4d, 0x41, 0x52,
+ 0x43, 0x49, 0x4e, 0x20, 0x44, 0x52, 0x45, 0x57,
+ 0x53, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00,
+ 0x69, 0x64, 0x65, 0x61, 0x73, 0x00, 0x41, 0x44,
+ 0x52, 0x49, 0x41, 0x4e, 0x20, 0x43, 0x48, 0x4d,
+ 0x49, 0x45, 0x4c, 0x41, 0x52, 0x5a, 0x00, 0x47,
+ 0x52, 0x5a, 0x45, 0x47, 0x4f, 0x52, 0x5a, 0x20,
+ 0x4d, 0x49, 0x45, 0x43, 0x48, 0x4f, 0x57, 0x53,
+ 0x4b, 0x49, 0x00, 0x41, 0x4e, 0x44, 0x52, 0x5a,
+ 0x45, 0x4a, 0x20, 0x53, 0x41, 0x57, 0x49, 0x43,
+ 0x4b, 0x49, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20,
+ 0x00, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x00, 0x4a,
+ 0x41, 0x52, 0x4f, 0x53, 0x5d, 0x41, 0x57, 0x20,
+ 0x57, 0x45, 0x49, 0x53, 0x53, 0x00, 0x41, 0x47,
+ 0x45, 0x4e, 0x43, 0x4a, 0x41, 0x20, 0x53, 0x54,
+ 0x59, 0x4c, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20,
+ 0x00, 0x74, 0x68, 0x61, 0x6e, 0x6b, 0x73, 0x00,
+ 0x48, 0x45, 0x4e, 0x52, 0x59, 0x20, 0x4b, 0x55,
+ 0x54, 0x54, 0x4e, 0x45, 0x52, 0x00, 0x55, 0x2d,
+ 0x4b, 0x4e, 0x4f, 0x57, 0x2d, 0x57, 0x48, 0x4f,
+ 0x2d, 0x55, 0x2d, 0x52, 0x2d, 0x42, 0x55, 0x54,
+ 0x2d, 0x57, 0x41, 0x4e, 0x54, 0x2d, 0x32, 0x2d,
+ 0x53, 0x54, 0x41, 0x59, 0x2d, 0x49, 0x4e, 0x2d,
+ 0x53, 0x48, 0x41, 0x44, 0x4f, 0x57, 0x00, 0x45,
+ 0x50, 0x49, 0x43, 0x20, 0x4d, 0x45, 0x47, 0x41,
+ 0x47, 0x41, 0x4d, 0x45, 0x53, 0x00, 0x58, 0x4c,
+ 0x41, 0x4e, 0x44, 0x20, 0x53, 0x4f, 0x46, 0x54,
+ 0x57, 0x41, 0x52, 0x45, 0x20, 0x50, 0x55, 0x42,
+ 0x4c, 0x49, 0x53, 0x48, 0x49, 0x4e, 0x47, 0x00,
+ 0x4b, 0x41, 0x54, 0x41, 0x52, 0x5a, 0x59, 0x4e,
+ 0x41, 0x20, 0x4d, 0x49, 0x45, 0x43, 0x48, 0x4f,
+ 0x57, 0x53, 0x4b, 0x41, 0x00, 0x20, 0x00, 0x20,
+ 0x00, 0x20, 0x00, 0x73, 0x70, 0x65, 0x63, 0x69,
+ 0x61, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x6b,
+ 0x73, 0x00, 0x41, 0x4e, 0x44, 0x52, 0x5a, 0x45,
+ 0x4a, 0x20, 0x4d, 0x49, 0x43, 0x48, 0x41, 0x4c,
+ 0x41, 0x4b, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20,
+ 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20,
+ 0x00, 0x20, 0x00, 0x20, 0x00, 0x70, 0x72, 0x6f,
+ 0x64, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00,
+ 0x4d, 0x45, 0x54, 0x52, 0x4f, 0x50, 0x4f, 0x4c,
+ 0x49, 0x53, 0x20, 0x53, 0x4f, 0x46, 0x54, 0x57,
+ 0x41, 0x52, 0x45, 0x20, 0x48, 0x4f, 0x55, 0x53,
+ 0x45, 0x00, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39,
+ 0x39, 0x34, 0x2d, 0x31, 0x39, 0x39, 0x35, 0x00,
+ 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x41, 0x6c,
+ 0x6c, 0x20, 0x61, 0x6c, 0x6c, 0x75, 0x73, 0x69,
+ 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x70, 0x75, 0x6e, 0x73, 0x00, 0x61, 0x72, 0x65,
+ 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69,
+ 0x6f, 0x6e, 0x61, 0x6c, 0x00, 0x20, 0x00, 0x20,
+ 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20,
+ 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20,
+ 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20,
+ 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00
+};
+
+// Dialog Strings Block
+
+#define ANIM_WAIT "\xff"
+#define NEW_LINE "\n"
+#define DISPLAY_MESSAGE "\n\n"
+#define CHANGE_CHARACTER "\n\n\n"
+#define END_DIALOG "\n\n\n\n"
+
+const static char* dialog_0[] = {
+ ANIM_WAIT,
+ "Good day.",
+ CHANGE_CHARACTER,
+ "Yeah.",
+ CHANGE_CHARACTER,
+ "Why are you standing here?",
+ CHANGE_CHARACTER,
+ "It's a question of gravitation.",
+ CHANGE_CHARACTER,
+ "Extremely funny joke.",
+ DISPLAY_MESSAGE,
+ "For a soldier.",
+ CHANGE_CHARACTER,
+ "I'm not a soldier, although I tried",
+ NEW_LINE,
+ "to be.",
+ DISPLAY_MESSAGE,
+ "I didn't pass the intell...",
+ NEW_LINE,
+ "the physical test.",
+ DISPLAY_MESSAGE,
+ "They ordered me to shoot at",
+ NEW_LINE,
+ "a thrown coin when jumping",
+ NEW_LINE,
+ "from the tree onto a horse.",
+ CHANGE_CHARACTER,
+ "Yep, that seems hard.",
+ CHANGE_CHARACTER,
+ "Special Forces ain't a piece of cake,",
+ NEW_LINE,
+ "you know.",
+ CHANGE_CHARACTER,
+ "I'm sorry you didn't make it.",
+ CHANGE_CHARACTER,
+ "Yeah, I missed the horse.",
+ END_DIALOG
+};
+
+const static char* dialog_1[] = {
+ "So...",
+ DISPLAY_MESSAGE,
+ "What are you doing now?",
+ CHANGE_CHARACTER,
+ "Wanna hear a funny answer?",
+ CHANGE_CHARACTER,
+ "Please don't bother.",
+ CHANGE_CHARACTER,
+ "All right, but you know, there's not much",
+ NEW_LINE,
+ "entertainment here.",
+ DISPLAY_MESSAGE,
+ "Sometimes I like to joke a bit.",
+ NEW_LINE,
+ "Or a byte, heh-heh!",
+ CHANGE_CHARACTER,
+ "Well then...",
+ CHANGE_CHARACTER,
+ "I'm guarding this place...",
+ CHANGE_CHARACTER,
+ "Wow. That's a surprise.",
+ CHANGE_CHARACTER,
+ "...And I'm told to kill ANYBODY",
+ NEW_LINE,
+ "who tries to get in.",
+ CHANGE_CHARACTER,
+ "What about the owner?",
+ CHANGE_CHARACTER,
+ "He's not just ANYBODY, you know.",
+ CHANGE_CHARACTER,
+ "I guess you won't let ME in then?",
+ CHANGE_CHARACTER,
+ "Bingo.",
+ CHANGE_CHARACTER,
+ "Even if say I please?",
+ CHANGE_CHARACTER,
+ "No way, kiddo.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "PLEEEEEASE.",
+ CHANGE_CHARACTER,
+ "Forget it.",
+ NEW_LINE,
+ "I've got a heart of stone.",
+ CHANGE_CHARACTER,
+ "Like your brain.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "I don't follow.",
+ CHANGE_CHARACTER,
+ "Never mind.",
+ NEW_LINE,
+ "How can I soften your stone heart?",
+ CHANGE_CHARACTER,
+ "You can't. I'm a really tough guy.",
+ DISPLAY_MESSAGE,
+ "But come here, I'll give you",
+ NEW_LINE,
+ "a consolation...",
+ END_DIALOG
+};
+
+const static char* dialog_2[] = {
+ "Thanks. What is it?",
+ CHANGE_CHARACTER,
+ "Chocolate candy.",
+ DISPLAY_MESSAGE,
+ "My employer gave me a few of these",
+ NEW_LINE,
+ "for lunch and...",
+ CHANGE_CHARACTER,
+ "Is your employer home?!",
+ CHANGE_CHARACTER,
+ "Mr. John Noty? Yeah, why?",
+ CHANGE_CHARACTER,
+ "Oh, nothing...",
+ DISPLAY_MESSAGE,
+ "John Noty...",
+ DISPLAY_MESSAGE,
+ "I think I've heard of him...",
+ CHANGE_CHARACTER,
+ "You should have. He's making big money,",
+ NEW_LINE,
+ "you know.",
+ DISPLAY_MESSAGE,
+ "Especially lately...",
+ CHANGE_CHARACTER,
+ "Yeah?...",
+ CHANGE_CHARACTER,
+ "Well, I don't know how.",
+ DISPLAY_MESSAGE,
+ "Maybe it has something to do with",
+ NEW_LINE,
+ "the mad scientist that came round",
+ NEW_LINE,
+ "one day...",
+ DISPLAY_MESSAGE,
+ "Oh, you think you're smart, don't you?!",
+ NEW_LINE,
+ "Are you a spy?!",
+ CHANGE_CHARACTER,
+ "Hey, I'm just a common homeboy.",
+ DISPLAY_MESSAGE,
+ "If you don't wanna talk,",
+ NEW_LINE,
+ "don't talk.",
+ CHANGE_CHARACTER,
+ "Mr. Bad Gay told me to watch",
+ NEW_LINE,
+ "for spies...",
+ CHANGE_CHARACTER,
+ "Do I really look like a spy?",
+ CHANGE_CHARACTER,
+ "...And kill them immediately...",
+ CHANGE_CHARACTER,
+ "Hey, chill...",
+ CHANGE_CHARACTER,
+ "...And I haven't killed anybody",
+ NEW_LINE,
+ "for a loooong time...",
+ CHANGE_CHARACTER,
+ "It's about this candy, isn't it?",
+ NEW_LINE,
+ "Do you want it back? No problem.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "Sorry, I just got carried away.",
+ CHANGE_CHARACTER,
+ "I understand.",
+ NEW_LINE,
+ "It's hot around here.",
+ CHANGE_CHARACTER,
+ "Yeah.",
+ END_DIALOG
+};
+
+const static char* dialog_3[] = {
+ "Mister guard, I...",
+ CHANGE_CHARACTER,
+ "Listen, boy.",
+ DISPLAY_MESSAGE,
+ "A spy or not a spy, it's out of",
+ NEW_LINE,
+ "the question.",
+ DISPLAY_MESSAGE,
+ "You won't get in, no matter if you just want",
+ NEW_LINE,
+ "to visit the place, steal something or",
+ NEW_LINE,
+ "talk to Mr. John Noty.",
+ DISPLAY_MESSAGE,
+ "Also you won't make me talk.",
+ DISPLAY_MESSAGE,
+ "One more try and I'll make a few",
+ NEW_LINE,
+ "highways for worms.",
+ DISPLAY_MESSAGE,
+ "In your body.",
+ DISPLAY_MESSAGE,
+ "Got it?",
+ CHANGE_CHARACTER,
+ "Got it.",
+ END_DIALOG
+};
+
+const static char* dialog_4[] = {
+ "Nice suit.",
+ CHANGE_CHARACTER,
+ "Yeah.",
+ END_DIALOG
+};
+
+const static char* dialog_5[] = {
+ CHANGE_CHARACTER,
+ "Damn!",
+ DISPLAY_MESSAGE,
+ "It's only you!...",
+ END_DIALOG
+};
+
+const static char* dialog_6[] = {
+ "Hey!",
+ CHANGE_CHARACTER,
+ "What?",
+ CHANGE_CHARACTER,
+ "What's in this bottle?",
+ CHANGE_CHARACTER,
+ "You can't prove anything!",
+ CHANGE_CHARACTER,
+ "Something hot, I guess?..",
+ CHANGE_CHARACTER,
+ "None of your business.",
+ CHANGE_CHARACTER,
+ "Drinking on duty, huh?",
+ CHANGE_CHARACTER,
+ "You think you've almost got me,",
+ NEW_LINE,
+ "don't you?",
+ DISPLAY_MESSAGE,
+ "Forget it.",
+ END_DIALOG
+};
+
+const static char* dialog_7[] = {
+ "Hey!",
+ CHANGE_CHARACTER,
+ "You've seen nothing.",
+ DISPLAY_MESSAGE,
+ "I'm clean.",
+ END_DIALOG
+};
+
+const static char* dialog_8[] = {
+ "Hey!",
+ CHANGE_CHARACTER,
+ "Get lost.",
+ END_DIALOG
+};
+
+const static char* dialog_9[] = {
+ "What would you say if I gave you some",
+ NEW_LINE,
+ "gold?...",
+ CHANGE_CHARACTER,
+ "I'd say thanks.",
+ CHANGE_CHARACTER,
+ "Would you let me in?",
+ CHANGE_CHARACTER,
+ "I guess so...",
+ CHANGE_CHARACTER,
+ "You have to be sure.",
+ CHANGE_CHARACTER,
+ "OK, I'm sure. I will let you in.",
+ CHANGE_CHARACTER,
+ "All right. Here we go.",
+ END_DIALOG
+};
+
+const static char* dialog_10[] = {
+ "Now please open the door.",
+ CHANGE_CHARACTER,
+ "No way. Now buzz off.",
+ CHANGE_CHARACTER,
+ "Hey! I gave you the gold, remember?...",
+ CHANGE_CHARACTER,
+ "What gold?",
+ CHANGE_CHARACTER,
+ "WHAT GOLD?!?",
+ CHANGE_CHARACTER,
+ "I don't know nothing 'bout any gold.",
+ END_DIALOG
+};
+
+const static char* dialog_11[] = {
+ "You... You...",
+ CHANGE_CHARACTER,
+ "Buzz off.",
+ CHANGE_CHARACTER,
+ "You said you'd let me in!",
+ DISPLAY_MESSAGE,
+ "But you've let me down!",
+ CHANGE_CHARACTER,
+ "Yeah, but I'll let you off.",
+ END_DIALOG
+};
+
+const static char* dialog_12[] = {
+ "You can't even trust corrupt",
+ NEW_LINE,
+ "guards these days.",
+ END_DIALOG
+};
+
+const static char* dialog_13[] = {
+ "Hi.",
+ CHANGE_CHARACTER,
+ "Hello.",
+ CHANGE_CHARACTER,
+ "I'm Mark.",
+ DISPLAY_MESSAGE,
+ "What's your name?",
+ CHANGE_CHARACTER,
+ "What's my name?",
+ CHANGE_CHARACTER,
+ "I don't know, you tell me.",
+ CHANGE_CHARACTER,
+ "Me.",
+ CHANGE_CHARACTER,
+ "Don't tell me 'me', just say",
+ NEW_LINE,
+ "your name!",
+ CHANGE_CHARACTER,
+ "Your na..",
+ CHANGE_CHARACTER,
+ "Gee!",
+ DISPLAY_MESSAGE,
+ "What did your dad call you?",
+ CHANGE_CHARACTER,
+ "Sonny.",
+ CHANGE_CHARACTER,
+ "Sonny as in the name or sonny",
+ NEW_LINE,
+ "as in son?",
+ CHANGE_CHARACTER,
+ "Sonny.",
+ CHANGE_CHARACTER,
+ "Are you stupid or just rude?",
+ CHANGE_CHARACTER,
+ "Sonny, I am.",
+ CHANGE_CHARACTER,
+ "(sigh)",
+ END_DIALOG
+};
+
+const static char* dialog_14[] = {
+ "Listen, Sonny or whatever.",
+ DISPLAY_MESSAGE,
+ "What are you trying to do",
+ NEW_LINE,
+ "with this ball?",
+ CHANGE_CHARACTER,
+ "Well, grandpa said he'd take",
+ NEW_LINE,
+ "me to ZOO if I score.",
+ CHANGE_CHARACTER,
+ "I think you should throw the ball",
+ NEW_LINE,
+ "a little bit higher.",
+ CHANGE_CHARACTER,
+ "Yeah, I know.",
+ CHANGE_CHARACTER,
+ "So?",
+ CHANGE_CHARACTER,
+ "So what?",
+ CHANGE_CHARACTER,
+ "So why don't you do it?!",
+ CHANGE_CHARACTER,
+ "It must be something with",
+ NEW_LINE,
+ "my eyes.",
+ CHANGE_CHARACTER,
+ "You should wear glassess?",
+ CHANGE_CHARACTER,
+ "No, why?",
+ CHANGE_CHARACTER,
+ "(sigh)",
+ DISPLAY_MESSAGE,
+ "Maybe you're just too weak to",
+ NEW_LINE,
+ "send the ball high enough?",
+ CHANGE_CHARACTER,
+ "No kidding.",
+ CHANGE_CHARACTER,
+ "(sigh)",
+ END_DIALOG
+};
+
+const static char* dialog_15[] = {
+ "Hey, kid!",
+ DISPLAY_MESSAGE,
+ "I've got a great idea!",
+ CHANGE_CHARACTER,
+ "Yeah?",
+ CHANGE_CHARACTER,
+ "Go to your grandpa and",
+ NEW_LINE,
+ "say you've scored!",
+ CHANGE_CHARACTER,
+ "You mean lie?",
+ CHANGE_CHARACTER,
+ "Well, sort of...",
+ CHANGE_CHARACTER,
+ "I NEVER LIE!",
+ CHANGE_CHARACTER,
+ "Never?!",
+ CHANGE_CHARACTER,
+ "NEVER!",
+ CHANGE_CHARACTER,
+ "Good boy.",
+ END_DIALOG
+};
+
+const static char* dialog_16[] = {
+ "Hey...",
+ CHANGE_CHARACTER,
+ "Go away.",
+ END_DIALOG
+};
+
+const static char* dialog_17[] = {
+ "Hey, boy! It's unbelievable!",
+ CHANGE_CHARACTER,
+ "What?",
+ CHANGE_CHARACTER,
+ "You might think it's a joke,",
+ NEW_LINE,
+ "but there's a hand holding",
+ NEW_LINE,
+ "a sword appearing from the lake!",
+ CHANGE_CHARACTER,
+ "OK, I'll look but just don't ",
+ NEW_LINE,
+ "think you've fooled me.",
+ NEW_LINE,
+ "This hand appears every year.",
+ DISPLAY_MESSAGE,
+ "Maybe this time will bring me luck",
+ NEW_LINE,
+ "at basketball...",
+ END_DIALOG
+};
+
+const static char* dialog_18[] = {
+ "Good day, sir!",
+ CHANGE_CHARACTER,
+ "And good day to",
+ NEW_LINE,
+ "you, my son.",
+ CHANGE_CHARACTER,
+ "My name is Mark, sir.",
+ CHANGE_CHARACTER,
+ "Great.",
+ DISPLAY_MESSAGE,
+ "What do you want?",
+ CHANGE_CHARACTER,
+ "I'm just admiring your arm-chair.",
+ DISPLAY_MESSAGE,
+ "It's nice.",
+ CHANGE_CHARACTER,
+ "Nice and pretty",
+ NEW_LINE,
+ "comfortable.",
+ CHANGE_CHARACTER,
+ "And big.",
+ CHANGE_CHARACTER,
+ "2-person model.",
+ END_DIALOG
+};
+
+const static char* dialog_19[] = {
+ "Do you know the boy",
+ NEW_LINE,
+ "playing with the ball",
+ NEW_LINE,
+ "outside?",
+ CHANGE_CHARACTER,
+ "Of course, he's",
+ NEW_LINE,
+ "my grandson.",
+ CHANGE_CHARACTER,
+ "Nice kid.",
+ CHANGE_CHARACTER,
+ "Nice and smart.",
+ CHANGE_CHARACTER,
+ "Nice and small.",
+ CHANGE_CHARACTER,
+ "He'll grow.",
+ CHANGE_CHARACTER,
+ "And become a very",
+ NEW_LINE,
+ "famous basketball",
+ NEW_LINE,
+ "player?...",
+ CHANGE_CHARACTER,
+ "I hope he won't.",
+ CHANGE_CHARACTER,
+ "Then tell him to stop playing!",
+ CHANGE_CHARACTER,
+ "Yeah.",
+ DISPLAY_MESSAGE,
+ "Later.",
+ DISPLAY_MESSAGE,
+ "Maybe.",
+ DISPLAY_MESSAGE,
+ "Right now I need",
+ NEW_LINE,
+ "some rest.",
+ END_DIALOG
+};
+
+const static char* dialog_20[] = {
+ "Are you going to sit here",
+ NEW_LINE,
+ "all day long?",
+ CHANGE_CHARACTER,
+ "Hope so.",
+ CHANGE_CHARACTER,
+ "For all of this beautiful day?",
+ CHANGE_CHARACTER,
+ "Hope so.",
+ CHANGE_CHARACTER,
+ "Aren't you interested",
+ NEW_LINE,
+ "in the outside world?!",
+ CHANGE_CHARACTER,
+ "Not really.",
+ CHANGE_CHARACTER,
+ "Why's that?",
+ CHANGE_CHARACTER,
+ "I'm not interested",
+ NEW_LINE,
+ "in news.",
+ CHANGE_CHARACTER,
+ "But...",
+ CHANGE_CHARACTER,
+ "As they say...",
+ DISPLAY_MESSAGE,
+ "The best news",
+ NEW_LINE,
+ "is no news.",
+ CHANGE_CHARACTER,
+ "But people must know about",
+ NEW_LINE,
+ "progress and stuff!",
+ CHANGE_CHARACTER,
+ "I won't even bother",
+ NEW_LINE,
+ "to ask you why...",
+ CHANGE_CHARACTER,
+ "Because...",
+ DISPLAY_MESSAGE,
+ "Er...",
+ DISPLAY_MESSAGE,
+ "Because...",
+ DISPLAY_MESSAGE,
+ "Uhm...",
+ CHANGE_CHARACTER,
+ "Right.",
+ NEW_LINE,
+ " ",
+ END_DIALOG
+};
+
+const static char* dialog_21[] = {
+ "Anything new?",
+ CHANGE_CHARACTER,
+ "Hope not.",
+ END_DIALOG
+};
+
+const static char* dialog_22[] = {
+ "May I borrow this shotgun?",
+ CHANGE_CHARACTER,
+ "No.",
+ CHANGE_CHARACTER,
+ "Pleeeease...",
+ CHANGE_CHARACTER,
+ "Young man, this weapon is",
+ NEW_LINE,
+ "very old and dangerous...",
+ DISPLAY_MESSAGE,
+ "and I'm a responsible man,",
+ NEW_LINE,
+ "got it?",
+ CHANGE_CHARACTER,
+ "But I will...",
+ CHANGE_CHARACTER,
+ "No.",
+ END_DIALOG
+};
+
+const static char* dialog_23[] = {
+ "Maybe you will change your mind",
+ NEW_LINE,
+ "about the shotgun?...",
+ CHANGE_CHARACTER,
+ "No.",
+ DISPLAY_MESSAGE,
+ "Nope.",
+ DISPLAY_MESSAGE,
+ "Niet.",
+ DISPLAY_MESSAGE,
+ "Nein.",
+ DISPLAY_MESSAGE,
+ "Niente.",
+ DISPLAY_MESSAGE,
+ "Nie.",
+ DISPLAY_MESSAGE,
+ "Ne.",
+ CHANGE_CHARACTER,
+ "OK, I got it.",
+ END_DIALOG
+};
+
+const static char* dialog_24[] = {
+ "May I search your drawers?",
+ CHANGE_CHARACTER,
+ "Yes.",
+ CHANGE_CHARACTER,
+ "YES?!?",
+ CHANGE_CHARACTER,
+ "Oh, I forgot to tell you they are all",
+ NEW_LINE,
+ "empty.",
+ DISPLAY_MESSAGE,
+ "Only the right upper one has a handkerchief",
+ NEW_LINE,
+ "in it.",
+ DISPLAY_MESSAGE,
+ "You can take if you want, I don't need it.",
+ CHANGE_CHARACTER,
+ "Well, thank you.",
+ DISPLAY_MESSAGE,
+ "You are very... kind...",
+ CHANGE_CHARACTER,
+ "Just don't think I let you take",
+ NEW_LINE,
+ "anything else.",
+ CHANGE_CHARACTER,
+ "Of course, I wouldn't even dream.",
+ END_DIALOG
+};
+
+const static char* dialog_25[] = {
+ "May I borrow the fan?",
+ CHANGE_CHARACTER,
+ "No way. It makes this hot day more",
+ NEW_LINE,
+ "bearable.",
+ END_DIALOG
+};
+
+const static char* dialog_26[] = {
+ "About this fan...",
+ CHANGE_CHARACTER,
+ "Come back in winter.",
+ END_DIALOG
+};
+
+const static char* dialog_27[] = {
+ "Nice weather we have",
+ NEW_LINE,
+ "today...",
+ CHANGE_CHARACTER,
+ "Indeed it is,",
+ NEW_LINE,
+ "my dear.",
+ END_DIALOG
+};
+
+const static char* dialog_28[] = {
+ "Is it your daughter?",
+ CHANGE_CHARACTER,
+ "You are very kind,",
+ NEW_LINE,
+ "my dear, making",
+ NEW_LINE,
+ "me so young,",
+ DISPLAY_MESSAGE,
+ "but of course",
+ NEW_LINE,
+ "that sweetie is my",
+ NEW_LINE,
+ "grand-daughter.",
+ CHANGE_CHARACTER,
+ "Oh, yes! She really",
+ NEW_LINE,
+ "looks grand!",
+ CHANGE_CHARACTER,
+ "Well, I was once",
+ NEW_LINE,
+ "like that...",
+ CHANGE_CHARACTER,
+ "But you still are!",
+ CHANGE_CHARACTER,
+ "How sweet of you...",
+ DISPLAY_MESSAGE,
+ "But nobody sings",
+ NEW_LINE,
+ "at my window",
+ NEW_LINE,
+ "anymore,",
+ DISPLAY_MESSAGE,
+ "if you know",
+ NEW_LINE,
+ "what I mean.",
+ CHANGE_CHARACTER,
+ "Errr...",
+ DISPLAY_MESSAGE,
+ "Yes...",
+ DISPLAY_MESSAGE,
+ "I know...",
+ DISPLAY_MESSAGE,
+ "I have similiar",
+ NEW_LINE,
+ "feelings myself...",
+ DISPLAY_MESSAGE,
+ "Sometimes...",
+ DISPLAY_MESSAGE,
+ "I guess...",
+ END_DIALOG
+};
+
+const static char* dialog_29[] = {
+ "May I ask what you are",
+ NEW_LINE,
+ "doing?",
+ CHANGE_CHARACTER,
+ "Yes, you may,",
+ NEW_LINE,
+ "my dear.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "What are you doing?",
+ CHANGE_CHARACTER,
+ "I'm knitting.",
+ CHANGE_CHARACTER,
+ "I understand.",
+ DISPLAY_MESSAGE,
+ "What are you knitting?",
+ CHANGE_CHARACTER,
+ "This time you",
+ NEW_LINE,
+ "didn't ask if",
+ NEW_LINE,
+ "you may ask.",
+ CHANGE_CHARACTER,
+ "Oh, sorry. May I ask?",
+ CHANGE_CHARACTER,
+ "Ask about what?",
+ CHANGE_CHARACTER,
+ "About what are you",
+ NEW_LINE,
+ "knitting.",
+ CHANGE_CHARACTER,
+ "You asked me",
+ NEW_LINE,
+ "about that before,",
+ NEW_LINE,
+ "didn't you?",
+ END_DIALOG
+};
+
+const static char* dialog_30[] = {
+ "Is everything OK?",
+ CHANGE_CHARACTER,
+ "Indeed it is.",
+ END_DIALOG
+};
+
+const static char* dialog_31[] = {
+ "Is everything OK?",
+ CHANGE_CHARACTER,
+ "You know.",
+ END_DIALOG
+};
+
+const static char* dialog_32[] = {
+ "Is everything OK?",
+ CHANGE_CHARACTER,
+ "It's nice you ask,",
+ NEW_LINE,
+ "but I've told you",
+ NEW_LINE,
+ "already.",
+ END_DIALOG
+};
+
+const static char* dialog_33[] = {
+ "Is everything OK?",
+ CHANGE_CHARACTER,
+ "Don't repeat",
+ NEW_LINE,
+ "yourself.",
+ END_DIALOG
+};
+
+const static char* dialog_34[] = {
+ "Is everything OK?",
+ CHANGE_CHARACTER,
+ "Don't interrupt",
+ NEW_LINE,
+ "my work.",
+ END_DIALOG
+};
+
+const static char* dialog_35[] = {
+ "Is everything OK?",
+ CHANGE_CHARACTER,
+ "Oh shut up.",
+ END_DIALOG
+};
+
+const static char* dialog_36[] = {
+ "Is everything OK?",
+ END_DIALOG
+};
+
+const static char* dialog_37[] = {
+ "Excuse my",
+ NEW_LINE,
+ "immodesty...",
+ CHANGE_CHARACTER,
+ "Yes?...",
+ CHANGE_CHARACTER,
+ "...but I thought",
+ NEW_LINE,
+ "that an innocent",
+ NEW_LINE,
+ "flower...",
+ DISPLAY_MESSAGE,
+ "...would express",
+ NEW_LINE,
+ "my happiness at",
+ NEW_LINE,
+ "meeting you.",
+ END_DIALOG
+};
+
+const static char* dialog_38[] = {
+ "I hope you",
+ NEW_LINE,
+ "like it...",
+ CHANGE_CHARACTER,
+ "Oh, dear!",
+ DISPLAY_MESSAGE,
+ "I'm really",
+ NEW_LINE,
+ "touched...",
+ DISPLAY_MESSAGE,
+ "That's the nicest",
+ NEW_LINE,
+ "thing anybody has",
+ NEW_LINE,
+ "done for me...",
+ DISPLAY_MESSAGE,
+ "...in last ten",
+ NEW_LINE,
+ "years!",
+ DISPLAY_MESSAGE,
+ "Thank you from all",
+ NEW_LINE,
+ "my heart!",
+ CHANGE_CHARACTER,
+ "You're welcome.",
+ END_DIALOG
+};
+
+const static char* dialog_39[] = {
+ "Would you care for",
+ NEW_LINE,
+ "another flower?",
+ CHANGE_CHARACTER,
+ "You're very kind,",
+ NEW_LINE,
+ "my boy, but no,",
+ NEW_LINE,
+ "thank you.",
+ END_DIALOG
+};
+
+const static char* dialog_40[] = {
+ "Are you sure you don't",
+ NEW_LINE,
+ "want another flower?",
+ CHANGE_CHARACTER,
+ "Yes. I'm sure.",
+ END_DIALOG
+};
+
+const static char* dialog_41[] = {
+ "May I borrow this",
+ NEW_LINE,
+ "duster?",
+ CHANGE_CHARACTER,
+ "We don't know each",
+ NEW_LINE,
+ "other too well, and",
+ NEW_LINE,
+ "I don't...",
+ DISPLAY_MESSAGE,
+ "...lend things to",
+ NEW_LINE,
+ "anybody who asks",
+ NEW_LINE,
+ "for them.",
+ CHANGE_CHARACTER,
+ "Don't I look reliable?",
+ CHANGE_CHARACTER,
+ "I've said enough.",
+ END_DIALOG
+};
+
+const static char* dialog_42[] = {
+ "Any chances to borrow the",
+ NEW_LINE,
+ "feather duster?",
+ CHANGE_CHARACTER,
+ "I like it where it is.",
+ END_DIALOG
+};
+
+const static char* dialog_43[] = {
+ "Do you think you could",
+ NEW_LINE,
+ "lend me the feather duster",
+ NEW_LINE,
+ "now?",
+ CHANGE_CHARACTER,
+ "But of course, I can't",
+ NEW_LINE,
+ "see why I shouldn't...",
+ DISPLAY_MESSAGE,
+ "...help to such a nice",
+ NEW_LINE,
+ "young man like you!..",
+ CHANGE_CHARACTER,
+ "Thank you very much.",
+ END_DIALOG
+};
+
+const static char* dialog_44[] = {
+ "Ha! I'm even faster than Indy`!",
+ CHANGE_CHARACTER,
+ "I've seen it all, boy!",
+ END_DIALOG
+};
+
+const static char* dialog_45[] = {
+ "Er...",
+ DISPLAY_MESSAGE,
+ "Uh...",
+ DISPLAY_MESSAGE,
+ "I just...",
+ CHANGE_CHARACTER,
+ "Don't worry. I hope you killed",
+ NEW_LINE,
+ "that fly.",
+ END_DIALOG
+};
+
+const static char* dialog_46[] = {
+ "Excuse me, lady, but I think your",
+ NEW_LINE,
+ "laundry is dry now...",
+ DISPLAY_MESSAGE,
+ "...and too much sun will distort",
+ NEW_LINE,
+ "the clothes...",
+ CHANGE_CHARACTER,
+ "How come the laundry dried",
+ NEW_LINE,
+ "out so fast?",
+ DISPLAY_MESSAGE,
+ "I'd better go and check it.",
+ END_DIALOG
+};
+
+const static char* dialog_47[] = {
+ CHANGE_CHARACTER,
+ "You were right, young man.",
+ DISPLAY_MESSAGE,
+ "Thank you.",
+ CHANGE_CHARACTER,
+ "You're welcome.",
+ END_DIALOG
+};
+
+const static char* dialog_48[] = {
+ "Do you need this fake apple?",
+ CHANGE_CHARACTER,
+ "It depends. This apple",
+ NEW_LINE,
+ "has its own story.",
+ DISPLAY_MESSAGE,
+ "I remember how one day",
+ NEW_LINE,
+ "my younger sister Mary",
+ NEW_LINE,
+ "was making...",
+ CHANGE_CHARACTER,
+ "Er, how long is the story?",
+ CHANGE_CHARACTER,
+ "Oh, there's no need to rush.",
+ DISPLAY_MESSAGE,
+ "We do have hours to talk,",
+ NEW_LINE,
+ "don't we?",
+ CHANGE_CHARACTER,
+ "I just realised I don't need that",
+ NEW_LINE,
+ "apple.",
+ DISPLAY_MESSAGE,
+ "Thanks.",
+ END_DIALOG
+};
+
+const static char* dialog_49[] = {
+ "This apple...",
+ CHANGE_CHARACTER,
+ "No story, no apple.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "No apple.",
+ END_DIALOG
+};
+
+const static char* dialog_50[] = {
+ "Could she be...",
+ DISPLAY_MESSAGE,
+ "...the most beautiful girl...",
+ DISPLAY_MESSAGE,
+ "in the world?...",
+ END_DIALOG
+};
+
+const static char* dialog_51[] = {
+ "I think it's high time to",
+ NEW_LINE,
+ "introduce myself.",
+ DISPLAY_MESSAGE,
+ "I'm Mark.",
+ CHANGE_CHARACTER,
+ "Anne.",
+ END_DIALOG
+};
+
+const static char* dialog_52[] = {
+ "The moment I saw those eyes",
+ NEW_LINE,
+ "was the best moment of my entire",
+ NEW_LINE,
+ "life.",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "Not counting the time",
+ NEW_LINE,
+ "I played doctor with",
+ NEW_LINE,
+ "Susie.",
+ END_DIALOG
+};
+
+const static char* dialog_53[] = {
+ "Uh...",
+ DISPLAY_MESSAGE,
+ "Er...",
+ DISPLAY_MESSAGE,
+ "I wonder...",
+ DISPLAY_MESSAGE,
+ "I wonder if",
+ NEW_LINE,
+ "you would like",
+ NEW_LINE,
+ "to get some...",
+ DISPLAY_MESSAGE,
+ "Er...",
+ DISPLAY_MESSAGE,
+ "I mean...",
+ DISPLAY_MESSAGE,
+ "I have something",
+ NEW_LINE,
+ "I would like to give",
+ NEW_LINE,
+ "you, because...",
+ DISPLAY_MESSAGE,
+ "Uh...",
+ DISPLAY_MESSAGE,
+ "I think you",
+ NEW_LINE,
+ "are... And...",
+ CHANGE_CHARACTER,
+ "Hey! I don't bite!",
+ DISPLAY_MESSAGE,
+ "I see you want to tell me",
+ NEW_LINE,
+ "something nice.",
+ DISPLAY_MESSAGE,
+ "Just use simple",
+ NEW_LINE,
+ "words...",
+ CHANGE_CHARACTER,
+ "Simple words?!",
+ CHANGE_CHARACTER,
+ "Yes, simple words make",
+ NEW_LINE,
+ "things simple.",
+ CHANGE_CHARACTER,
+ "Oh, yes.",
+ DISPLAY_MESSAGE,
+ "OK.",
+ DISPLAY_MESSAGE,
+ "Simple words.",
+ DISPLAY_MESSAGE,
+ "OK.",
+ DISPLAY_MESSAGE,
+ "Here I go.",
+ DISPLAY_MESSAGE,
+ "Me like you and",
+ NEW_LINE,
+ "want give flower.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "Well, maybe you should",
+ NEW_LINE,
+ "try something...",
+ DISPLAY_MESSAGE,
+ "...more complicated.",
+ CHANGE_CHARACTER,
+ "Uh...",
+ DISPLAY_MESSAGE,
+ "Sorry...",
+ DISPLAY_MESSAGE,
+ "I just...",
+ DISPLAY_MESSAGE,
+ "I just brought you",
+ NEW_LINE,
+ "a flower.",
+ CHANGE_CHARACTER,
+ "Oh?...",
+ END_DIALOG
+};
+
+const static char* dialog_54[] = {
+ "Do you like it?",
+ CHANGE_CHARACTER,
+ "You're charming.",
+ END_DIALOG
+};
+
+const static char* dialog_55[] = {
+ "As a matter",
+ NEW_LINE,
+ "of fact...",
+ CHANGE_CHARACTER,
+ "Simple words, boy!",
+ NEW_LINE,
+ "Simple words!",
+ END_DIALOG
+};
+
+const static char* dialog_56[] = {
+ "Oh,yes...",
+ DISPLAY_MESSAGE,
+ "I just wanted to say",
+ NEW_LINE,
+ "that you're charming",
+ NEW_LINE,
+ "too.",
+ CHANGE_CHARACTER,
+ "I guess I should say",
+ NEW_LINE,
+ "thanks.",
+ END_DIALOG
+};
+
+const static char* dialog_57[] = {
+ "I hate myself.",
+ END_DIALOG
+};
+
+const static char* dialog_58[] = {
+ "I have another",
+ NEW_LINE,
+ "flower...",
+ CHANGE_CHARACTER,
+ "Oh, let's not",
+ NEW_LINE,
+ "exaggerate.",
+ DISPLAY_MESSAGE,
+ "And, as you can see, I'm",
+ NEW_LINE,
+ "not the only...",
+ DISPLAY_MESSAGE,
+ "...woman in this room...",
+ END_DIALOG
+};
+
+const static char* dialog_59[] = {
+ "So you don't want",
+ NEW_LINE,
+ "another flower?",
+ CHANGE_CHARACTER,
+ "No, thank you.",
+ END_DIALOG
+};
+
+const static char* dialog_60[] = {
+ "Would you like some candy?",
+ CHANGE_CHARACTER,
+ "You're nice, but no, thanks.",
+ NEW_LINE,
+ "I don't want to get fat.",
+ CHANGE_CHARACTER,
+ "Hey, don't worry. Even Obelix",
+ NEW_LINE,
+ "has friends.",
+ CHANGE_CHARACTER,
+ "Who's Obelix?!",
+ CHANGE_CHARACTER,
+ "Er, never mind. It's just that I found",
+ NEW_LINE,
+ "this candy...",
+ CHANGE_CHARACTER,
+ "You FOUND IT?!",
+ CHANGE_CHARACTER,
+ "...I found it's pretty hard to get,",
+ NEW_LINE,
+ "of course.",
+ DISPLAY_MESSAGE,
+ "It's not some cheap pseudo-chocolate,",
+ NEW_LINE,
+ "but the highest quality goodie!",
+ DISPLAY_MESSAGE,
+ "It's made only from the things you",
+ NEW_LINE,
+ "can find in a natural environment.",
+ DISPLAY_MESSAGE,
+ "No preservatives added.",
+ CHANGE_CHARACTER,
+ "Oh, all right. If you insist...",
+ END_DIALOG
+};
+
+const static char* dialog_61[] = {
+ ANIM_WAIT,
+ "Khm...",
+ CHANGE_CHARACTER,
+ "Oh yes, I think I should give you",
+ NEW_LINE,
+ "something in return...",
+ CHANGE_CHARACTER,
+ "Oh, no... You really don't",
+ NEW_LINE,
+ "have to...",
+ CHANGE_CHARACTER,
+ "OK. Your wish.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "Well, on second thoughts...",
+ CHANGE_CHARACTER,
+ "I knew it. You boys always want",
+ NEW_LINE,
+ "something.",
+ DISPLAY_MESSAGE,
+ "You can't do anything for",
+ NEW_LINE,
+ "free.",
+ CHANGE_CHARACTER,
+ "I cleaned my room once.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "Well...",
+ DISPLAY_MESSAGE,
+ "Let's forget it.",
+ DISPLAY_MESSAGE,
+ "Here's my present for",
+ NEW_LINE,
+ "you.",
+ DISPLAY_MESSAGE,
+ "It's my ribbon. Think of me",
+ NEW_LINE,
+ "sometimes.",
+ END_DIALOG
+};
+
+const static char* dialog_62[] = {
+ "Thanks. I will never",
+ NEW_LINE,
+ "wash it.",
+ END_DIALOG
+};
+
+const static char* dialog_63[] = {
+ "I found your name on a banknote",
+ NEW_LINE,
+ "some fatso gave me. Do you know",
+ NEW_LINE,
+ "anything about it?",
+ CHANGE_CHARACTER,
+ "Show me the banknote.",
+ END_DIALOG
+};
+
+const static char* dialog_64[] = {
+ "Hey, what's up?!",
+ CHANGE_CHARACTER,
+ "Oh, poor me!...",
+ CHANGE_CHARACTER,
+ "Why are you crying?!",
+ CHANGE_CHARACTER,
+ "This... this...",
+ DISPLAY_MESSAGE,
+ "Oh, poor me!...",
+ DISPLAY_MESSAGE,
+ "Our... our neighbour, Mr.",
+ NEW_LINE,
+ "John Noty gave me some",
+ NEW_LINE,
+ "money one day...",
+ DISPLAY_MESSAGE,
+ "...and said that if I gave",
+ NEW_LINE,
+ "him a kiss he'd give",
+ NEW_LINE,
+ "me more...",
+ DISPLAY_MESSAGE,
+ "...but I thought it over",
+ NEW_LINE,
+ "and I gave him all the",
+ NEW_LINE,
+ "money back.",
+ CHANGE_CHARACTER,
+ "You mean, that pig tried",
+ NEW_LINE,
+ "to buy you?!",
+ CHANGE_CHARACTER,
+ "I'm so unhappy!",
+ CHANGE_CHARACTER,
+ "Oh, man! That",
+ NEW_LINE,
+ "does it!",
+ END_DIALOG
+};
+
+const static char* dialog_65[] = {
+ "Hey, you!",
+ DISPLAY_MESSAGE,
+ "Would you please give me that nut",
+ NEW_LINE,
+ "lying next to you?",
+ END_DIALOG
+};
+
+const static char* dialog_66[] = {
+ "Are you gonna give me that nut or not?!",
+ END_DIALOG
+};
+
+const static char* dialog_67[] = {
+ "All right.",
+ DISPLAY_MESSAGE,
+ "That's it.",
+ DISPLAY_MESSAGE,
+ "Now you'll get what you deserve.",
+ DISPLAY_MESSAGE,
+ "I'm gonna insult you until I get that nut.",
+ DISPLAY_MESSAGE,
+ "You ugly squirrel you.",
+ END_DIALOG
+};
+
+const static char* dialog_68[] = {
+ "Don't you know it's not politically",
+ NEW_LINE,
+ "correct to wear a fur?",
+ END_DIALOG
+};
+
+const static char* dialog_69[] = {
+ "Hey, thanks again for the nut.",
+ END_DIALOG
+};
+
+const static char* dialog_70[] = {
+ "I didn't ask if I could take the rope.",
+ DISPLAY_MESSAGE,
+ "It's really rude to take someone else's",
+ NEW_LINE,
+ "property without their permission.",
+ DISPLAY_MESSAGE,
+ "And I might get caught, of",
+ NEW_LINE,
+ "course.",
+ DISPLAY_MESSAGE,
+ "And they will put me in jail and",
+ NEW_LINE,
+ "nobody will respect me anymore.",
+ DISPLAY_MESSAGE,
+ "I could really ruin my life doing that.",
+ END_DIALOG
+};
+
+const static char* dialog_71[] = {
+ "No pain no gain.",
+ END_DIALOG
+};
+
+const static char* dialog_72[] = {
+ "Listen, guys. I want you to get",
+ NEW_LINE,
+ "outta here at once!",
+ DISPLAY_MESSAGE,
+ "Or I'll have to shoot.",
+ DISPLAY_MESSAGE,
+ "With a real gun.",
+ DISPLAY_MESSAGE,
+ "I think.",
+ END_DIALOG
+};
+
+const static char* dialog_73[] = {
+ "I can see...",
+ DISPLAY_MESSAGE,
+ "...there's a...",
+ DISPLAY_MESSAGE,
+ "SPIDER!!!",
+ END_DIALOG
+};
+
+const static char* dialog_74[] = {
+ "Not that I'm chicken.",
+ DISPLAY_MESSAGE,
+ "It's just that it could be",
+ NEW_LINE,
+ "a mutant spider and it",
+ NEW_LINE,
+ "could bite me...",
+ DISPLAY_MESSAGE,
+ "...and I'd get mutant too...",
+ DISPLAY_MESSAGE,
+ "...and I'd have to wear those",
+ NEW_LINE,
+ "funny gloves and stuff...",
+ DISPLAY_MESSAGE,
+ "...and I'd have a double life...",
+ DISPLAY_MESSAGE,
+ "...and I'd have to fight with Venom`",
+ NEW_LINE,
+ "and others and I might get hurt...",
+ DISPLAY_MESSAGE,
+ "...and everybody would be making",
+ NEW_LINE,
+ "money on me but me...",
+ DISPLAY_MESSAGE,
+ "I think I'll pass then.",
+ END_DIALOG
+};
+
+const static char* dialog_75[] = {
+ "This spider gives me thrills...",
+ END_DIALOG
+};
+
+const static char* dialog_76[] = {
+ "Hey, little buddy!",
+ DISPLAY_MESSAGE,
+ "I've got a DECENT PROPOSAL for you.",
+ DISPLAY_MESSAGE,
+ "A big, fresh and juicy apple for this old cone",
+ NEW_LINE,
+ "which presses your back.",
+ DISPLAY_MESSAGE,
+ "If you want to make a deal, stand here",
+ NEW_LINE,
+ "and shake your muzzle.",
+ END_DIALOG
+};
+
+const static char* dialog_77[] = {
+ "I should have know",
+ NEW_LINE,
+ "there's a catch.",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "The paddle is broken.",
+ END_DIALOG
+};
+
+const static char* dialog_78[] = {
+ "Hello there, big boy.",
+ END_DIALOG
+};
+
+const static char* dialog_79[] = {
+ "Don't ignore me, please.",
+ END_DIALOG
+};
+
+const static char* dialog_80[] = {
+ "You know, I'm a little bit dog-tired",
+ NEW_LINE,
+ "talking to you.",
+ END_DIALOG
+};
+
+const static char* dialog_81[] = {
+ "What's up?",
+ END_DIALOG
+};
+
+const static char* dialog_82[] = {
+ "Yes, I could take this...",
+ DISPLAY_MESSAGE,
+ "It's a quiet little village...",
+ DISPLAY_MESSAGE,
+ "No police...",
+ DISPLAY_MESSAGE,
+ "Noone will hear their screams...",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "But I don't have a hockey mask.",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "(sigh)",
+ END_DIALOG
+};
+
+const static char* dialog_83[] = {
+ "I don't want my fingerprints on it.",
+ DISPLAY_MESSAGE,
+ " Who knows what it was used for.",
+ END_DIALOG
+};
+
+const static char* dialog_84[] = {
+ "I'm afraid that it's too hard",
+ NEW_LINE,
+ "to catch a mouse just like",
+ NEW_LINE,
+ "that.",
+ DISPLAY_MESSAGE,
+ "And what challenge would it be?",
+ END_DIALOG
+};
+
+const static char* dialog_85[] = {
+ "I could try to scare these birds myself",
+ NEW_LINE,
+ "if I hadn't watched that Hitchcock",
+ NEW_LINE,
+ "movie when I was five.",
+ DISPLAY_MESSAGE,
+ "My mum should never let me watch that.",
+ DISPLAY_MESSAGE,
+ "Now I'm CHICKEN even when I eat eggs.",
+ END_DIALOG
+};
+
+const static char* dialog_86[] = {
+ "Great. Let's GET THE MESSAGE.",
+ DISPLAY_MESSAGE,
+ "\"Gold awaits at the end of the road.\"",
+ END_DIALOG
+};
+
+const static char* dialog_87[] = {
+ "Are you Mr. John Noty?",
+ CHANGE_CHARACTER,
+ "How do you do, my friend.",
+ DISPLAY_MESSAGE,
+ "My people told me you tried",
+ NEW_LINE,
+ "to get inside my mansion.",
+ NEW_LINE,
+ "Why?",
+ CHANGE_CHARACTER,
+ "Er... You see...",
+ DISPLAY_MESSAGE,
+ "I'm here to...",
+ NEW_LINE,
+ "To...",
+ DISPLAY_MESSAGE,
+ "I mean, I'm here on my vacations,",
+ NEW_LINE,
+ "but I got sick of all these green",
+ NEW_LINE,
+ "plants and trees around...",
+ DISPLAY_MESSAGE,
+ "...and I just wanted to lick some",
+ NEW_LINE,
+ "civilisation.",
+ CHANGE_CHARACTER,
+ "Well... I can understand you,",
+ NEW_LINE,
+ "my friend.",
+ DISPLAY_MESSAGE,
+ "I also think that the natural",
+ NEW_LINE,
+ "environment for us, people",
+ NEW_LINE,
+ "of 20th century...",
+ DISPLAY_MESSAGE,
+ "is TV and a bag of pop-corn.",
+ NEW_LINE,
+ "But talking about the green",
+ NEW_LINE,
+ "stuff...",
+ DISPLAY_MESSAGE,
+ "I can't allow you to enter",
+ NEW_LINE,
+ "my house, because... uhm...",
+ NEW_LINE,
+ "because it's ...being...",
+ DISPLAY_MESSAGE,
+ "...under renovation, but as",
+ NEW_LINE,
+ "a rich man I'll give you",
+ NEW_LINE,
+ "a hundred bucks...",
+ DISPLAY_MESSAGE,
+ "so you can buy yourself",
+ NEW_LINE,
+ "something that will help",
+ NEW_LINE,
+ "you survive here.",
+ DISPLAY_MESSAGE,
+ "A walkman for example.",
+ NEW_LINE,
+ "What do you say?",
+ CHANGE_CHARACTER,
+ "What do you take me for?!",
+ END_DIALOG
+};
+
+const static char* dialog_88[] = {
+ "I will NEVER take this!",
+ DISPLAY_MESSAGE,
+ "NEVER!",
+ CHANGE_CHARACTER,
+ "Don't get so excited.",
+ DISPLAY_MESSAGE,
+ "Pecunia non olet.",
+ DISPLAY_MESSAGE,
+ "I'll leave now. Don't be shy",
+ NEW_LINE,
+ "and pick up the banknote.",
+ DISPLAY_MESSAGE,
+ "Noone has to know...",
+ DISPLAY_MESSAGE,
+ "Good bye, my friend.",
+ END_DIALOG
+};
+
+const static char* dialog_89[] = {
+ "I can't believe he treated me",
+ NEW_LINE,
+ "like that.",
+ DISPLAY_MESSAGE,
+ "By the way...",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "Peculiar non omelette?...",
+ END_DIALOG
+};
+
+const static char* dialog_90[] = {
+ "Boy...",
+ DISPLAY_MESSAGE,
+ "It's all black...",
+ DISPLAY_MESSAGE,
+ "...and it looks like a man...",
+ DISPLAY_MESSAGE,
+ "...with some long pole...",
+ DISPLAY_MESSAGE,
+ "...and a pot on its head...",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "VGA artist shouldn't drink so much.",
+ END_DIALOG
+};
+
+const static char* dialog_91[] = {
+ "Searching trash cans again?",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "Oh, all right, there are only some",
+ NEW_LINE,
+ "papers.",
+ END_DIALOG
+};
+
+const static char* dialog_92[] = {
+ "The same as usual...",
+ DISPLAY_MESSAGE,
+ "Disasters...",
+ DISPLAY_MESSAGE,
+ "Corruption...",
+ DISPLAY_MESSAGE,
+ "Murders...",
+ DISPLAY_MESSAGE,
+ "Puzzle...",
+ DISPLAY_MESSAGE,
+ "Half-naked babes...",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "I gotta subscribe.",
+ END_DIALOG
+};
+
+const static char* dialog_93[] = {
+ ANIM_WAIT,
+ "Gee...",
+ CHANGE_CHARACTER,
+ "...I'm daaaancing...",
+ DISPLAY_MESSAGE,
+ "...and siiiinging...",
+ CHANGE_CHARACTER,
+ "It's John Noty...",
+ CHANGE_CHARACTER,
+ "...raaain!...",
+ CHANGE_CHARACTER,
+ "...singing to the camera!",
+ CHANGE_CHARACTER,
+ "...what a beaaaaautifuuuul...",
+ CHANGE_CHARACTER,
+ "Although he definitely shouldn't.",
+ CHANGE_CHARACTER,
+ "...feeeliiing...",
+ CHANGE_CHARACTER,
+ "I can't believe it.",
+ CHANGE_CHARACTER,
+ "...haaaappy agaaain!..",
+ CHANGE_CHARACTER,
+ "What a horror.",
+ CHANGE_CHARACTER,
+ "...just daaancing in the raaain...",
+ CHANGE_CHARACTER,
+ "My neighbour's dog will do it better.",
+ CHANGE_CHARACTER,
+ "...la, laaaaa!...",
+ CHANGE_CHARACTER,
+ "I've had enough.",
+ CHANGE_CHARACTER,
+ "...la, la! La, laaaa....",
+ END_DIALOG
+};
+
+const static char* dialog_94[] = {
+ "There's nothing intere...",
+ DISPLAY_MESSAGE,
+ "No, wait a minute...",
+ DISPLAY_MESSAGE,
+ "There's something under the couch!",
+ END_DIALOG
+};
+
+const static char* dialog_95[] = {
+ "Don't you think you",
+ NEW_LINE,
+ "should add a little",
+ NEW_LINE,
+ "bit of chilli?",
+ CHANGE_CHARACTER,
+ "Add?",
+ DISPLAY_MESSAGE,
+ "Why?",
+ CHANGE_CHARACTER,
+ "I see you're not happy",
+ NEW_LINE,
+ "with the stew you're",
+ NEW_LINE,
+ "cooking.",
+ DISPLAY_MESSAGE,
+ "Maybe you should try",
+ NEW_LINE,
+ "to spice it up a",
+ NEW_LINE,
+ "little?",
+ CHANGE_CHARACTER,
+ "Well...",
+ DISPLAY_MESSAGE,
+ "That's good idea.",
+ DISPLAY_MESSAGE,
+ "Luckily I've got something here.",
+ END_DIALOG
+};
+
+const static char* dialog_96[] = {
+ CHANGE_CHARACTER,
+ "This... hic!...",
+ DISPLAY_MESSAGE,
+ "This chilllllleeeeee... hep!",
+ DISPLAY_MESSAGE,
+ "...must have been...",
+ DISPLAY_MESSAGE,
+ "...fermented...",
+ DISPLAY_MESSAGE,
+ "The stew yyys spoiled aaand...",
+ DISPLAY_MESSAGE,
+ "...I'm fired!",
+ DISPLAY_MESSAGE,
+ "Hic!",
+ END_DIALOG
+};
+
+const static char* dialog_97[] = {
+ "I don't need this radio, but",
+ NEW_LINE,
+ "I can use its batteries.",
+ DISPLAY_MESSAGE,
+ "Unfortunately I never know",
+ NEW_LINE,
+ "where to open those Japanese",
+ NEW_LINE,
+ "babies.",
+ END_DIALOG
+};
+
+const static char* dialog_98[] = {
+ CHANGE_CHARACTER,
+ "Security test: voice, scent, view.",
+ DISPLAY_MESSAGE,
+ "Voice positively identified.",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "Nice song, man.",
+ END_DIALOG
+};
+
+const static char* dialog_99[] = {
+ CHANGE_CHARACTER,
+ "Security test: voice, scent, view.",
+ DISPLAY_MESSAGE,
+ "Scent positively identified.",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "I don't like water too, bro.",
+ END_DIALOG
+};
+
+const static char* dialog_100[] = {
+ CHANGE_CHARACTER,
+ "Security test: voice, scent, view.",
+ DISPLAY_MESSAGE,
+ "View positively identified.",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "Next time stand a bit closer, man.",
+ END_DIALOG
+};
+
+const static char* dialog_101[] = {
+ "May I talk with...",
+ CHANGE_CHARACTER,
+ "Go away.",
+ DISPLAY_MESSAGE,
+ "I'm busy.",
+ DISPLAY_MESSAGE,
+ "Working.",
+ DISPLAY_MESSAGE,
+ "Dinner soon.",
+ DISPLAY_MESSAGE,
+ "Gotta hurry.",
+ CHANGE_CHARACTER,
+ "Aye, captain.",
+ END_DIALOG
+};
+
+const static char* dialog_102[] = {
+ "Well, but maybe...",
+ CHANGE_CHARACTER,
+ "I...",
+ DISPLAY_MESSAGE,
+ "...AM...",
+ DISPLAY_MESSAGE,
+ "...BUSY.",
+ DISPLAY_MESSAGE,
+ "DON'T...",
+ DISPLAY_MESSAGE,
+ "...DISTURB...",
+ DISPLAY_MESSAGE,
+ "...ME.",
+ DISPLAY_MESSAGE,
+ "OK?",
+ CHANGE_CHARACTER,
+ "Okay, okay.",
+ END_DIALOG
+};
+
+const static char* dialog_103[] = {
+ "Last time I ask you...",
+ CHANGE_CHARACTER,
+ "BUSY.",
+ DISPLAY_MESSAGE,
+ "B like Bill.",
+ DISPLAY_MESSAGE,
+ "U like Ulrik.",
+ DISPLAY_MESSAGE,
+ "S like Sean.",
+ DISPLAY_MESSAGE,
+ "Y like...",
+ DISPLAY_MESSAGE,
+ "...like...",
+ CHANGE_CHARACTER,
+ "Yeti?",
+ CHANGE_CHARACTER,
+ "No. Like...",
+ CHANGE_CHARACTER,
+ "Yabbadabbadoo?",
+ CHANGE_CHARACTER,
+ "No, no. Like...",
+ CHANGE_CHARACTER,
+ "Yoko?",
+ CHANGE_CHARACTER,
+ "Yoko.",
+ DISPLAY_MESSAGE,
+ "Leave me alone now, PLEASE!",
+ CHANGE_CHARACTER,
+ "All right, all right.",
+ END_DIALOG
+};
+
+const static char* dialog_104[] = {
+ "Er...",
+ CHANGE_CHARACTER,
+ "Wrrrr...",
+ CHANGE_CHARACTER,
+ "Oh, nothing.",
+ END_DIALOG
+};
+
+const static char* dialog_105[] = {
+ "Good day, Mr. Robot.",
+ CHANGE_CHARACTER,
+ "Hey, yo, wassup my man,",
+ NEW_LINE,
+ "you know what I'm sayin'?",
+ DISPLAY_MESSAGE,
+ "Call me Mike, you know",
+ NEW_LINE,
+ "what I'm sayin'?",
+ CHANGE_CHARACTER,
+ "Er...",
+ DISPLAY_MESSAGE,
+ "Are you sure everything's",
+ NEW_LINE,
+ "all right with your...",
+ DISPLAY_MESSAGE,
+ "...program?...",
+ CHANGE_CHARACTER,
+ "What's da problem, man?!",
+ DISPLAY_MESSAGE,
+ "Neva seen da rappin' robo-safe,",
+ NEW_LINE,
+ "you know what I'm sayin'?",
+ CHANGE_CHARACTER,
+ "Actually, never.",
+ CHANGE_CHARACTER,
+ "I'm brand new, bro.",
+ DISPLAY_MESSAGE,
+ "Fresh stuff, you know what I mean?",
+ DISPLAY_MESSAGE,
+ "Smart people sez da robots",
+ NEW_LINE,
+ "should be for everybody,",
+ DISPLAY_MESSAGE,
+ "you know what I'm sayin',",
+ NEW_LINE,
+ "so they gave me human",
+ NEW_LINE,
+ "personality,",
+ DISPLAY_MESSAGE,
+ "you know what I mean?",
+ NEW_LINE,
+ "Cool, ain't that?",
+ CHANGE_CHARACTER,
+ "Khm... Yeah, great.",
+ DISPLAY_MESSAGE,
+ "So, you're some kind of safe?",
+ CHANGE_CHARACTER,
+ "That's right, man.",
+ DISPLAY_MESSAGE,
+ "Totally reliable, you know",
+ NEW_LINE,
+ "what I'm sayin'?",
+ DISPLAY_MESSAGE,
+ "If you wanna get me open, you",
+ NEW_LINE,
+ "gotta prove you're da owner.",
+ DISPLAY_MESSAGE,
+ "Now check diz (CENSORED) out:",
+ NEW_LINE,
+ "I can judge if it's the right",
+ NEW_LINE,
+ "homie by three things:",
+ DISPLAY_MESSAGE,
+ "...view, scent and da voice.",
+ NEW_LINE,
+ "You know what I'm sayin'?",
+ CHANGE_CHARACTER,
+ "But will you please open",
+ NEW_LINE,
+ "...yourself... just to let me see",
+ NEW_LINE,
+ "what you got inside?",
+ CHANGE_CHARACTER,
+ "Sorry, bro.",
+ DISPLAY_MESSAGE,
+ "You don't look like da owner...",
+ DISPLAY_MESSAGE,
+ "...you don't smell like him...",
+ DISPLAY_MESSAGE,
+ "...and your voice is kinda different.",
+ DISPLAY_MESSAGE,
+ "Now (CENSORED), you know what I mean?",
+ END_DIALOG
+};
+
+const static char* dialog_106[] = {
+ "Sesame, open...",
+ CHANGE_CHARACTER,
+ "(CENSORED), you (CENSORED).",
+ END_DIALOG
+};
+
+const static char* dialog_107[] = {
+ "Hi there!",
+ CHANGE_CHARACTER,
+ "(PARENTAL GUIDANCE: EXPLICIT LYRICS)",
+ END_DIALOG
+};
+
+const static char* dialog_108[] = {
+ "I'm telling you, it's something great.",
+ CHANGE_CHARACTER,
+ "I remember when you killed my",
+ NEW_LINE,
+ "servant, testing your bullet-proof",
+ NEW_LINE,
+ "T-shirt.",
+ CHANGE_CHARACTER,
+ "That was a long time ago...",
+ CHANGE_CHARACTER,
+ "Or like you made rapping",
+ NEW_LINE,
+ "robo-safe, which goes mad",
+ NEW_LINE,
+ "every time...",
+ DISPLAY_MESSAGE,
+ "...I ask it to open.",
+ CHANGE_CHARACTER,
+ "You got a bad attitude...",
+ CHANGE_CHARACTER,
+ "Or like you sold me",
+ NEW_LINE,
+ "the recipe for girls'",
+ NEW_LINE,
+ "heart-breaking.",
+ CHANGE_CHARACTER,
+ "Money didn't work?",
+ CHANGE_CHARACTER,
+ "Nope.",
+ CHANGE_CHARACTER,
+ "Strange. Usually it works.",
+ CHANGE_CHARACTER,
+ "Or when you...",
+ CHANGE_CHARACTER,
+ "ALL RIGHT, ALL RIGHT!",
+ DISPLAY_MESSAGE,
+ "Let's forget this!",
+ DISPLAY_MESSAGE,
+ "I already tested my new",
+ NEW_LINE,
+ "invention on myself!",
+ CHANGE_CHARACTER,
+ "Really?",
+ CHANGE_CHARACTER,
+ "Really.",
+ DISPLAY_MESSAGE,
+ "I can demonstrate it.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "Ok, I'll take my chance.",
+ END_DIALOG
+};
+
+const static char* dialog_109[] = {
+ ANIM_WAIT,
+ "Great.",
+ DISPLAY_MESSAGE,
+ "Ultimate gnome-maker.",
+ CHANGE_CHARACTER,
+ "Khm, it's just a side effect.",
+ DISPLAY_MESSAGE,
+ "Sometimes I can't control my",
+ NEW_LINE,
+ "inventions.",
+ DISPLAY_MESSAGE,
+ "But don't worry, it lasts only",
+ NEW_LINE,
+ "a second.",
+ CHANGE_CHARACTER,
+ "I hope so.",
+ END_DIALOG
+};
+
+const static char* dialog_110[] = {
+ "Here I am.",
+ DISPLAY_MESSAGE,
+ "Well, have you noticed anything",
+ NEW_LINE,
+ "else unusual?",
+ CHANGE_CHARACTER,
+ "Nope.",
+ CHANGE_CHARACTER,
+ "Great!",
+ DISPLAY_MESSAGE,
+ "So the pills still work!",
+ CHANGE_CHARACTER,
+ "Oh yeah?",
+ CHANGE_CHARACTER,
+ "Yes!",
+ DISPLAY_MESSAGE,
+ "Check out your wallet!",
+ CHANGE_CHARACTER,
+ "My wallet is still...",
+ END_DIALOG
+};
+
+const static char* dialog_111[] = {
+ "Where is my wallet?!",
+ DISPLAY_MESSAGE,
+ "You thief!",
+ DISPLAY_MESSAGE,
+ "Give it back!",
+ CHANGE_CHARACTER,
+ "Take it easy, here's your",
+ NEW_LINE,
+ "wallet.",
+ END_DIALOG
+};
+
+const static char* dialog_112[] = {
+ "I demand an explanation.",
+ CHANGE_CHARACTER,
+ "Hah!",
+ DISPLAY_MESSAGE,
+ "This is the best thing I have",
+ NEW_LINE,
+ "ever invented!",
+ CHANGE_CHARACTER,
+ "What's that?",
+ CHANGE_CHARACTER,
+ "You didn't see me steal",
+ NEW_LINE,
+ "your wallet,",
+ DISPLAY_MESSAGE,
+ "...because I have eaten...",
+ DISPLAY_MESSAGE,
+ "THE TIME PILL!",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "The time pill?",
+ CHANGE_CHARACTER,
+ "Yes!",
+ DISPLAY_MESSAGE,
+ "Anyone who eats it, lives",
+ NEW_LINE,
+ "1000 times faster than the",
+ NEW_LINE,
+ "rest of the world!",
+ CHANGE_CHARACTER,
+ "That means...",
+ CHANGE_CHARACTER,
+ "That means the world for",
+ NEW_LINE,
+ "this person moves 1000",
+ NEW_LINE,
+ "times slower!",
+ DISPLAY_MESSAGE,
+ "Only for a few seconds,",
+ NEW_LINE,
+ "though...",
+ CHANGE_CHARACTER,
+ "Well... That's interesting.",
+ NEW_LINE,
+ "But what's the use?",
+ CHANGE_CHARACTER,
+ "I don't care.",
+ DISPLAY_MESSAGE,
+ "Think about it.",
+ DISPLAY_MESSAGE,
+ "You could, for example, get in",
+ NEW_LINE,
+ "the cinema without a ticket,",
+ NEW_LINE,
+ "and nobody would notice you.",
+ CHANGE_CHARACTER,
+ "Of course!",
+ DISPLAY_MESSAGE,
+ "Great!",
+ DISPLAY_MESSAGE,
+ "I want to buy the patent!",
+ CHANGE_CHARACTER,
+ "That's the problem...",
+ DISPLAY_MESSAGE,
+ "As you know, my uncel Gallagher,",
+ NEW_LINE,
+ "used to invent the best things",
+ NEW_LINE,
+ "when he was ...let's say...",
+ CHANGE_CHARACTER,
+ "...drunk...",
+ CHANGE_CHARACTER,
+ "...intoxicated.",
+ DISPLAY_MESSAGE,
+ "And the same happened to me",
+ NEW_LINE,
+ "(sigh).",
+ DISPLAY_MESSAGE,
+ "So last night I woke up with",
+ NEW_LINE,
+ "a horrible headache and",
+ NEW_LINE,
+ "found those pills.",
+ DISPLAY_MESSAGE,
+ "I don't remember how I made them.",
+ CHANGE_CHARACTER,
+ "Oh no!",
+ CHANGE_CHARACTER,
+ "But I may try to work on them.",
+ DISPLAY_MESSAGE,
+ "I need your money for that.",
+ DISPLAY_MESSAGE,
+ "Let's make a deal.",
+ DISPLAY_MESSAGE,
+ "You build me a new",
+ NEW_LINE,
+ "laboratory and stuff...",
+ DISPLAY_MESSAGE,
+ "...and I'll give you my rights.",
+ CHANGE_CHARACTER,
+ "You'll give me the patent?!",
+ CHANGE_CHARACTER,
+ "Yes.",
+ DISPLAY_MESSAGE,
+ "All I care about is the",
+ NEW_LINE,
+ "respect of the science",
+ NEW_LINE,
+ "society respect.",
+ DISPLAY_MESSAGE,
+ "And Nobel.",
+ DISPLAY_MESSAGE,
+ "You know, honoris causa here",
+ NEW_LINE,
+ "and there, interviews...",
+ CHANGE_CHARACTER,
+ "All right. You got the deal.",
+ DISPLAY_MESSAGE,
+ "Prepare the list of necessary",
+ NEW_LINE,
+ "equipment.",
+ CHANGE_CHARACTER,
+ "Wonderful.",
+ END_DIALOG
+};
+
+const static char* dialog_113[] = {
+ "This fool trusts me.",
+ DISPLAY_MESSAGE,
+ "But I will use him...",
+ DISPLAY_MESSAGE,
+ "The time pills...",
+ DISPLAY_MESSAGE,
+ "I won't be selling them to",
+ NEW_LINE,
+ "those stupid people!",
+ DISPLAY_MESSAGE,
+ "I don't care about the",
+ NEW_LINE,
+ "patent!",
+ DISPLAY_MESSAGE,
+ "I could rob any bank",
+ NEW_LINE,
+ "without being seen!",
+ DISPLAY_MESSAGE,
+ "Faster than light!",
+ DISPLAY_MESSAGE,
+ "I need to steal some money",
+ NEW_LINE,
+ "or gold for this mad man's",
+ NEW_LINE,
+ "laboratory.",
+ END_DIALOG
+};
+
+const static char* dialog_114[] = {
+ "But soon...",
+ DISPLAY_MESSAGE,
+ "I'll get rich.",
+ DISPLAY_MESSAGE,
+ "Veeeery rich.",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "I feel like I could...",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "...like I could...",
+ END_DIALOG
+};
+
+const static char* dialog_115[] = {
+ ANIM_WAIT,
+ "TAKE ON THE WORLD!...",
+ END_DIALOG
+};
+
+const static char* dialog_116[] = {
+ ANIM_WAIT,
+ "I always wanted to say that.",
+ END_DIALOG
+};
+
+const static char* dialog_117[] = {
+ "It's me again.",
+ CHANGE_CHARACTER,
+ "Goodbye again.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "Let's say I haven't heard that.",
+ DISPLAY_MESSAGE,
+ "Is Mr. John Noty home?",
+ CHANGE_CHARACTER,
+ "Yeah, but he said you can't get in.",
+ CHANGE_CHARACTER,
+ "Me?! Why?!",
+ CHANGE_CHARACTER,
+ "Your last invention cost him",
+ NEW_LINE,
+ "two walls.",
+ CHANGE_CHARACTER,
+ "Oh, that time machine...",
+ DISPLAY_MESSAGE,
+ "But now I have some...",
+ CHANGE_CHARACTER,
+ "Not to mention the disapearance of his cat.",
+ CHANGE_CHARACTER,
+ "The cat is happier than",
+ NEW_LINE,
+ "any of us now!",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "If the world still exists in",
+ NEW_LINE,
+ "XXV century.",
+ DISPLAY_MESSAGE,
+ "Never mind.",
+ DISPLAY_MESSAGE,
+ "You just have to let me in.",
+ CHANGE_CHARACTER,
+ "Oh yeah?",
+ CHANGE_CHARACTER,
+ "Or I'll tell Mr. John Noty you drink on duty.",
+ CHANGE_CHARACTER,
+ "You're bluffing. You have no proof.",
+ CHANGE_CHARACTER,
+ "Yeah, but you never know.",
+ END_DIALOG
+};
+
+const static char* dialog_118[] = {
+ "Ok, get in, you filthy terrorist.",
+ DISPLAY_MESSAGE,
+ "Just don't tell anybody.",
+ CHANGE_CHARACTER,
+ "Of course. Thank you.",
+ END_DIALOG
+};
+
+const static char* dialog_119[] = {
+ "So...",
+ DISPLAY_MESSAGE,
+ "That's how it all happened...",
+ DISPLAY_MESSAGE,
+ "That's why nobody has seen",
+ NEW_LINE,
+ "how things were",
+ NEW_LINE,
+ "being stolen...",
+ DISPLAY_MESSAGE,
+ "It's a really dangerous",
+ NEW_LINE,
+ "invention!",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "I HAVE TO stop John Noty!",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "Somehow.",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "Boy! Those pills I took",
+ NEW_LINE,
+ "from Mike must be...",
+ DISPLAY_MESSAGE,
+ "Oh, no!",
+ DISPLAY_MESSAGE,
+ "I can hear somebody coming!",
+ END_DIALOG
+};
+
+const static char* dialog_120[] = {
+ "I have to hide somewhere!",
+ DISPLAY_MESSAGE,
+ "Now!",
+ END_DIALOG
+};
+
+const static char* dialog_121[] = {
+ "I have to buy an old-fashioned safe.",
+ DISPLAY_MESSAGE,
+ "That stupid robot went mad again.",
+ DISPLAY_MESSAGE,
+ "I hate it.",
+ DISPLAY_MESSAGE,
+ "CLOSE, YOU PIECE OF JUNK!",
+ END_DIALOG
+};
+
+const static char* dialog_122[] = {
+ "Third time this week.",
+ DISPLAY_MESSAGE,
+ "Oh, all right, all right!...",
+ DISPLAY_MESSAGE,
+ "I'm coming!...",
+ END_DIALOG
+};
+
+const static char* dialog_123[] = {
+ "...cover it all.",
+ DISPLAY_MESSAGE,
+ "I need more money for the security system.",
+ DISPLAY_MESSAGE,
+ "I've got only two men and...",
+ CHANGE_CHARACTER,
+ "More and more!",
+ DISPLAY_MESSAGE,
+ "It's all I hear!",
+ CHANGE_CHARACTER,
+ "All right, I'll explain again...",
+ END_DIALOG
+};
+
+const static char* dialog_124[] = {
+ "Mr. John Noty?",
+ DISPLAY_MESSAGE,
+ "I just received some information from",
+ NEW_LINE,
+ "the professor.",
+ DISPLAY_MESSAGE,
+ "He's asked you to come to the laboratory.",
+ DISPLAY_MESSAGE,
+ "He says he's found out the structure of",
+ NEW_LINE,
+ "the pills.",
+ END_DIALOG
+};
+
+const static char* dialog_125[] = {
+ "So this is it?!",
+ CHANGE_CHARACTER,
+ "Definitely ...hic!... yes.",
+ CHANGE_CHARACTER,
+ "Great!",
+ END_DIALOG
+};
+
+const static char* dialog_126[] = {
+ "I have to stop them!",
+ DISPLAY_MESSAGE,
+ "There's no time to waste!",
+ END_DIALOG
+};
+
+const static char* dialog_127[] = {
+ "Well, well, well...",
+ DISPLAY_MESSAGE,
+ "You really play on my nerves.",
+ DISPLAY_MESSAGE,
+ "It was a good idea not to save money",
+ NEW_LINE,
+ "on the security system...",
+ DISPLAY_MESSAGE,
+ "This force field is indestructible!",
+ DISPLAY_MESSAGE,
+ "Hah!",
+ END_DIALOG
+};
+
+const static char* dialog_128[] = {
+ "But I have to kill you anyway.",
+ CHANGE_CHARACTER,
+ "No, no!",
+ CHANGE_CHARACTER,
+ "Shut up!",
+ CHANGE_CHARACTER,
+ "It's not worth it!",
+ CHANGE_CHARACTER,
+ "Oh really?",
+ CHANGE_CHARACTER,
+ "I don't want to...",
+ END_DIALOG
+};
+
+const static char* dialog_129[] = {
+ CHANGE_CHARACTER,
+ "The poor professor has fainted...",
+ CHANGE_CHARACTER,
+ "But... How...",
+ DISPLAY_MESSAGE,
+ "I DON'T UNDERSTAND ANYTHING!!!",
+ CHANGE_CHARACTER,
+ "It's very easy.",
+ DISPLAY_MESSAGE,
+ "We attached a secret micro-camera",
+ NEW_LINE,
+ "to your cap.",
+ DISPLAY_MESSAGE,
+ "This way we knew all the time what was",
+ NEW_LINE,
+ "happening.",
+ CHANGE_CHARACTER,
+ "You have seen when I?...",
+ CHANGE_CHARACTER,
+ "I don't want to embarass you.",
+ DISPLAY_MESSAGE,
+ "You did a good job for the RGB.",
+ CHANGE_CHARACTER,
+ "But John Noty has escaped!",
+ CHANGE_CHARACTER,
+ "He's not important.",
+ DISPLAY_MESSAGE,
+ "We have the professor, you'll give us the pills.",
+ DISPLAY_MESSAGE,
+ "Sorry, but you can't keep them for yourself.",
+ CHANGE_CHARACTER,
+ "Okay, but...",
+ DISPLAY_MESSAGE,
+ "Could you please give me just a minute?",
+ DISPLAY_MESSAGE,
+ "I have some private business to do with",
+ NEW_LINE,
+ "this scum.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "All right. But hurry up.",
+ END_DIALOG
+};
+
+const static char* dialog_130[] = {
+ ANIM_WAIT,
+ "(gulp)",
+ DISPLAY_MESSAGE,
+ "This time-effect really doesn't last",
+ NEW_LINE,
+ "long...",
+ END_DIALOG
+};
+
+const static char* dialog_131[] = {
+ "You've lost, mister!",
+ DISPLAY_MESSAGE,
+ "The police are surrounding the building!",
+ CHANGE_CHARACTER,
+ "Don't be stupid.",
+ DISPLAY_MESSAGE,
+ "Didn't you think I'd have",
+ NEW_LINE,
+ "a secret way out?",
+ CHANGE_CHARACTER,
+ "Oh yeah?",
+ DISPLAY_MESSAGE,
+ "What's that?",
+ CHANGE_CHARACTER,
+ "Like I'm going to tell you...",
+ DISPLAY_MESSAGE,
+ "Get lost, you little creep.",
+ DISPLAY_MESSAGE,
+ "I'm busy.",
+ END_DIALOG
+};
+
+const static char* dialog_132[] = {
+ "I'll have to disarm you.",
+ DISPLAY_MESSAGE,
+ "Be nice and surrender without problems.",
+ CHANGE_CHARACTER,
+ "I don't have time for jokes.",
+ DISPLAY_MESSAGE,
+ "Get the hell out of here,",
+ NEW_LINE,
+ "before I point my gun at you",
+ NEW_LINE,
+ "again.",
+ CHANGE_CHARACTER,
+ "I warn you...",
+ CHANGE_CHARACTER,
+ "Where do they sell",
+ NEW_LINE,
+ "bores like you?",
+ END_DIALOG
+};
+
+const static char* dialog_133[] = {
+ "I won't give you any more chances...",
+ CHANGE_CHARACTER,
+ "Good.",
+ DISPLAY_MESSAGE,
+ "And bye.",
+ END_DIALOG
+};
+
+const static char* dialog_134[] = {
+ "Stop packing that money!",
+ END_DIALOG
+};
+
+const static char* dialog_135[] = {
+ "Hi, there!",
+ CHANGE_CHARACTER,
+ "Hi.",
+ DISPLAY_MESSAGE,
+ "What's your problem?",
+ CHANGE_CHARACTER,
+ "I was sent here for some training.",
+ CHANGE_CHARACTER,
+ "Another wanna-be secret agent, huh?",
+ CHANGE_CHARACTER,
+ "Yep.",
+ CHANGE_CHARACTER,
+ "Show me your documents and you'll get in.",
+ CHANGE_CHARACTER,
+ "Okey dokey.",
+ END_DIALOG
+};
+
+const static char* dialog_136[] = {
+ "Can't you let me in without all that",
+ NEW_LINE,
+ "bureaucracy?",
+ CHANGE_CHARACTER,
+ "Sorry, no.",
+ DISPLAY_MESSAGE,
+ "Rules are rules.",
+ CHANGE_CHARACTER,
+ "And morons are morons.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "And dead people are dead people.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "Have a good day, sir.",
+ END_DIALOG
+};
+
+const static char* dialog_137[] = {
+ "MAY I PASS, PLEASE?!",
+ CHANGE_CHARACTER,
+ "YES, YOU MAY!",
+ DISPLAY_MESSAGE,
+ "JUST SHOW ME YOUR DOCUMENTS!",
+ END_DIALOG
+};
+
+const static char* dialog_138[] = {
+ "Let me in!",
+ CHANGE_CHARACTER,
+ "Show your documents!",
+ CHANGE_CHARACTER,
+ "You take your job really seriously,",
+ NEW_LINE,
+ "don't you?",
+ CHANGE_CHARACTER,
+ "Are you blind or what?",
+ DISPLAY_MESSAGE,
+ "I'm reading a magazine on duty.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "Oh, yeah.",
+ DISPLAY_MESSAGE,
+ "Sorry.",
+ END_DIALOG
+};
+
+const static char* dialog_139[] = {
+ "I have to...",
+ CHANGE_CHARACTER,
+ "Documents!",
+ END_DIALOG
+};
+
+const static char* dialog_140[] = {
+ "What are you reading?",
+ CHANGE_CHARACTER,
+ "'Soldier News', of course.",
+ CHANGE_CHARACTER,
+ "You love all that military stuff,",
+ NEW_LINE,
+ "don't you?",
+ CHANGE_CHARACTER,
+ "Are you crazy?",
+ DISPLAY_MESSAGE,
+ "I like pictures of cool babes...",
+ DISPLAY_MESSAGE,
+ "...crosswords...",
+ DISPLAY_MESSAGE,
+ "...the humor page...",
+ DISPLAY_MESSAGE,
+ "...rumors...",
+ DISPLAY_MESSAGE,
+ "...recipes...",
+ CHANGE_CHARACTER,
+ "COOKING?!",
+ CHANGE_CHARACTER,
+ "Yes, they try to raise their profile.",
+ DISPLAY_MESSAGE,
+ "Gain new readers, you know.",
+ CHANGE_CHARACTER,
+ "Oh yeah.",
+ DISPLAY_MESSAGE,
+ "Great idea.",
+ DISPLAY_MESSAGE,
+ "Is there a knitting page too?",
+ CHANGE_CHARACTER,
+ "I get the feeling you're",
+ NEW_LINE,
+ "trying to be funny.",
+ CHANGE_CHARACTER,
+ "Nah, me?",
+ DISPLAY_MESSAGE,
+ "Never.",
+ CHANGE_CHARACTER,
+ "Good.",
+ END_DIALOG
+};
+
+const static char* dialog_141[] = {
+ "Would you lend me the magazine?",
+ CHANGE_CHARACTER,
+ "And what am I supposed",
+ NEW_LINE,
+ "to kill the time with",
+ NEW_LINE,
+ "then?",
+ CHANGE_CHARACTER,
+ "Erm...",
+ DISPLAY_MESSAGE,
+ "You could count the leaves.",
+ CHANGE_CHARACTER,
+ "There're 11034 leaves here.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "Wow.",
+ END_DIALOG
+};
+
+const static char* dialog_142[] = {
+ "What's up?",
+ CHANGE_CHARACTER,
+ "The sky, I hope.",
+ END_DIALOG
+};
+
+const static char* dialog_143[] = {
+ "Keep up the good work.",
+ END_DIALOG
+};
+
+const static char* dialog_144[] = {
+ CHANGE_CHARACTER,
+ "Hey, get back!",
+ END_DIALOG
+};
+
+const static char* dialog_145[] = {
+ "What's the matter?",
+ CHANGE_CHARACTER,
+ "You must show me your pass",
+ NEW_LINE,
+ "before I let you enter the",
+ NEW_LINE,
+ "camp.",
+ CHANGE_CHARACTER,
+ "What if I don't?",
+ CHANGE_CHARACTER,
+ "I'll have to shoot you.",
+ CHANGE_CHARACTER,
+ "(gulp)",
+ END_DIALOG
+};
+
+const static char* dialog_146[] = {
+ CHANGE_CHARACTER,
+ "I warn you...",
+ DISPLAY_MESSAGE,
+ "My bullets are faster than you...",
+ END_DIALOG
+};
+
+const static char* dialog_147[] = {
+ CHANGE_CHARACTER,
+ "All right.",
+ DISPLAY_MESSAGE,
+ "Report to the captain.",
+ DISPLAY_MESSAGE,
+ "He should be around somewhere.",
+ CHANGE_CHARACTER,
+ "Thanks, man.",
+ END_DIALOG
+};
+
+const static char* dialog_148[] = {
+ CHANGE_CHARACTER,
+ "We're gonna turn you into a real man,",
+ NEW_LINE,
+ "right, son?!",
+ CHANGE_CHARACTER,
+ "Erm...",
+ CHANGE_CHARACTER,
+ "Best of the best!...",
+ CHANGE_CHARACTER,
+ "Uh...",
+ CHANGE_CHARACTER,
+ "By sweat, blood and tears!",
+ CHANGE_CHARACTER,
+ "I'd rather...",
+ CHANGE_CHARACTER,
+ "I'm glad to see your enthusiasm, son!",
+ DISPLAY_MESSAGE,
+ "Let's not waste time!",
+ DISPLAY_MESSAGE,
+ "I was told to give you some express training.",
+ DISPLAY_MESSAGE,
+ "All right, son!",
+ DISPLAY_MESSAGE,
+ "You'll have to pass three trials!",
+ DISPLAY_MESSAGE,
+ "Let's begin with the easy one!...",
+ END_DIALOG
+};
+
+const static char* dialog_149[] = {
+ CHANGE_CHARACTER,
+ "The task is simple.",
+ DISPLAY_MESSAGE,
+ "I'll lock up you here...",
+ DISPLAY_MESSAGE,
+ "...and you must escape.",
+ DISPLAY_MESSAGE,
+ "Is it clear?!",
+ CHANGE_CHARACTER,
+ "Sir, I...",
+ CHANGE_CHARACTER,
+ "GOOD!!!",
+ END_DIALOG
+};
+
+const static char* dialog_150[] = {
+ ANIM_WAIT,
+ "Hello?",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "Great.",
+ END_DIALOG
+};
+
+const static char* dialog_151[] = {
+ "OK, that was funny.",
+ DISPLAY_MESSAGE,
+ "Now let me out!",
+ END_DIALOG
+};
+
+const static char* dialog_152[] = {
+ "Hey! Is there anybody out",
+ NEW_LINE,
+ "there?!",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "HELP!!!",
+ END_DIALOG
+};
+
+const static char* dialog_153[] = {
+ "Have mercy!",
+ DISPLAY_MESSAGE,
+ "I'm gonna die here!",
+ END_DIALOG
+};
+
+const static char* dialog_154[] = {
+ "I'm getting hungry!",
+ END_DIALOG
+};
+
+const static char* dialog_155[] = {
+ "I don't know what to say now...",
+ END_DIALOG
+};
+
+const static char* dialog_156[] = {
+ "I think...",
+ DISPLAY_MESSAGE,
+ "...you've passed...",
+ DISPLAY_MESSAGE,
+ "...the first test...",
+ DISPLAY_MESSAGE,
+ "...Let's get...",
+ DISPLAY_MESSAGE,
+ "...to the next one...",
+ END_DIALOG
+};
+
+const static char* dialog_157[] = {
+ CHANGE_CHARACTER,
+ "Ok, soldier.",
+ DISPLAY_MESSAGE,
+ "Let's assume I'm your captive...",
+ DISPLAY_MESSAGE,
+ "...and I know some secret password.",
+ DISPLAY_MESSAGE,
+ "Your task is to get it from me.",
+ DISPLAY_MESSAGE,
+ "CLEAR?!?",
+ CHANGE_CHARACTER,
+ "Am I restricted?",
+ CHANGE_CHARACTER,
+ "No.",
+ DISPLAY_MESSAGE,
+ "Do anything you want.",
+ CHANGE_CHARACTER,
+ "May I even spit in your eye?",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "Yes.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "Thanks, just checking.",
+ END_DIALOG
+};
+
+const static char* dialog_158[] = {
+ "Please tell me the password",
+ NEW_LINE,
+ "and let's get over it all.",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "OK, think about it.",
+ END_DIALOG
+};
+
+const static char* dialog_159[] = {
+ "Hey, talk to me.",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "Do you hear me?",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "EARTH TO CAPTAIN, EARTH TO CAPTAIN!",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "You're hopeless.",
+ END_DIALOG
+};
+
+const static char* dialog_160[] = {
+ "Are you ready to talk?",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "OK, I'll give you some more time.",
+ END_DIALOG
+};
+
+const static char* dialog_161[] = {
+ "Now, what is the password?",
+ CHANGE_CHARACTER,
+ "Get lost, you pathetic wimp.",
+ CHANGE_CHARACTER,
+ "Be nice, or I'll tickle you again.",
+ CHANGE_CHARACTER,
+ "Go on, that'll be a pleasure.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "You enjoyed that, didn't you?",
+ CHANGE_CHARACTER,
+ "Well, you know...",
+ CHANGE_CHARACTER,
+ "Ok, I'll find some other way.",
+ END_DIALOG
+};
+
+const static char* dialog_162[] = {
+ "I brought you something...",
+ CHANGE_CHARACTER,
+ "You can't bribe me.",
+ CHANGE_CHARACTER,
+ "Oh, yeah?",
+ END_DIALOG
+};
+
+// Note:
+// 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[] = {
+ NEW_LINE,
+ "OH GIMMIE GIMMIE GIMMIE!!!",
+ DISPLAY_MESSAGE,
+ "I'LL DO ANYTHING!!!",
+ CHANGE_CHARACTER,
+ "Password...",
+ CHANGE_CHARACTER,
+ "The password is 'COFFEE'.",
+ DISPLAY_MESSAGE,
+ "Tell it to the barman and",
+ NEW_LINE,
+ "he'll give you something.",
+ DISPLAY_MESSAGE,
+ "Then he'll tell you about the third task.",
+ DISPLAY_MESSAGE,
+ "NOW FREE ME!!!",
+ CHANGE_CHARACTER,
+ "I'll think about it.",
+ END_DIALOG
+};
+
+const static char* dialog_164[] = {
+ "You...",
+ DISPLAY_MESSAGE,
+ "...you...",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "...have passed, sir!",
+ END_DIALOG
+};
+
+const static char* dialog_165[] = {
+ "Would you care for a wonderful kaleidoscope?",
+ CHANGE_CHARACTER,
+ "I had one once, but captain saw me",
+ NEW_LINE,
+ "playing with it and took it from me.",
+ DISPLAY_MESSAGE,
+ "I think he uses it himself,",
+ NEW_LINE,
+ "you know.",
+ CHANGE_CHARACTER,
+ "If you give me the gazette,",
+ NEW_LINE,
+ "I'll give you that kaleidoscope.",
+ CHANGE_CHARACTER,
+ "I don't want to know how you got it...",
+ CHANGE_CHARACTER,
+ "Good.",
+ CHANGE_CHARACTER,
+ "...but what if the captain sees me again?",
+ CHANGE_CHARACTER,
+ "Don't worry, he's tied up.",
+ CHANGE_CHARACTER,
+ "Oh, test number two, I guess?...",
+ CHANGE_CHARACTER,
+ "Yep.",
+ CHANGE_CHARACTER,
+ "OK, let's have some fun here.",
+ END_DIALOG
+};
+
+const static char* dialog_166[] = {
+ "'COFFEE'.",
+ END_DIALOG
+};
+
+const static char* dialog_167[] = {
+ CHANGE_CHARACTER,
+ "Hot, wasn't it?",
+ CHANGE_CHARACTER,
+ "Uh-huh.",
+ DISPLAY_MESSAGE,
+ "The captain says you're gonna tell me",
+ NEW_LINE,
+ "about the third task.",
+ CHANGE_CHARACTER,
+ "Again...",
+ DISPLAY_MESSAGE,
+ "Well, it's kinda hide'n'seek.",
+ DISPLAY_MESSAGE,
+ "The captain hides, you seek.",
+ CHANGE_CHARACTER,
+ "But I left him tied to a chair!",
+ CHANGE_CHARACTER,
+ "That man and his sick games...",
+ DISPLAY_MESSAGE,
+ "He enjoys it more than he should!...",
+ DISPLAY_MESSAGE,
+ "He cheated you.",
+ DISPLAY_MESSAGE,
+ "Go and check.",
+ DISPLAY_MESSAGE,
+ "I'm sure he's already free.",
+ CHANGE_CHARACTER,
+ "But I took his knife!",
+ DISPLAY_MESSAGE,
+ "How could he cut the ties?!",
+ CHANGE_CHARACTER,
+ "Maybe he walked away with the chair",
+ NEW_LINE,
+ "tied to his...",
+ CHANGE_CHARACTER,
+ "Never mind.",
+ DISPLAY_MESSAGE,
+ "Any hints about where he might hide?",
+ CHANGE_CHARACTER,
+ "None.",
+ CHANGE_CHARACTER,
+ "Oh, c'mon.",
+ CHANGE_CHARACTER,
+ "No, boy. Play fair.",
+ END_DIALOG
+};
+
+const static char* dialog_168[] = {
+ "Time for a little hint?",
+ CHANGE_CHARACTER,
+ "No.",
+ END_DIALOG
+};
+
+const static char* dialog_169[] = {
+ "Hello, sir. I'm Mark.",
+ CHANGE_CHARACTER,
+ "What a pity you're not a dollar.",
+ DISPLAY_MESSAGE,
+ "What can I do for you?",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "You can give me a lot of money...",
+ DISPLAY_MESSAGE,
+ "...or you can do a headstand...",
+ DISPLAY_MESSAGE,
+ "...or...",
+ CHANGE_CHARACTER,
+ "Okay, okay. It's a tie.",
+ DISPLAY_MESSAGE,
+ "So?...",
+ CHANGE_CHARACTER,
+ "Who's else is in the camp?",
+ CHANGE_CHARACTER,
+ "You're a journalist?",
+ CHANGE_CHARACTER,
+ "No, I'm a secret agent.",
+ CHANGE_CHARACTER,
+ "You too?",
+ DISPLAY_MESSAGE,
+ "Anyway, there are only three men.",
+ DISPLAY_MESSAGE,
+ "Me, the captain and the guard.",
+ CHANGE_CHARACTER,
+ "No women?",
+ CHANGE_CHARACTER,
+ "No cry.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "Erm, well...",
+ END_DIALOG
+};
+
+const static char* dialog_170[] = {
+ "Not much of a rush on, is there?",
+ CHANGE_CHARACTER,
+ "Do you want to order something or not?",
+ CHANGE_CHARACTER,
+ "I don't have money.",
+ CHANGE_CHARACTER,
+ "Today's free.",
+ CHANGE_CHARACTER,
+ "Really?",
+ CHANGE_CHARACTER,
+ "Really.",
+ CHANGE_CHARACTER,
+ "I want a hot-dog.",
+ CHANGE_CHARACTER,
+ "Miss.",
+ CHANGE_CHARACTER,
+ "Pizza?",
+ CHANGE_CHARACTER,
+ "Miss.",
+ CHANGE_CHARACTER,
+ "Toast?",
+ CHANGE_CHARACTER,
+ "Miss.",
+ CHANGE_CHARACTER,
+ "Anything?",
+ CHANGE_CHARACTER,
+ "Miss.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "No, thank you.",
+ DISPLAY_MESSAGE,
+ "I'm not hungry.",
+ END_DIALOG
+};
+
+const static char* dialog_171[] = {
+ "What are you drinking?",
+ CHANGE_CHARACTER,
+ "Tea.",
+ CHANGE_CHARACTER,
+ "Sure.",
+ END_DIALOG
+};
+
+const static char* dialog_172[] = {
+ "Nice weather.",
+ CHANGE_CHARACTER,
+ "Mhmmm...",
+ END_DIALOG
+};
+
+const static char* dialog_173[] = {
+ "Sometimes I feel tired.",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "Very tired.",
+ END_DIALOG
+};
+
+const static char* dialog_174[] = {
+ "Hey, Woodstock's over!",
+ END_DIALOG
+};
+
+const static char* dialog_175[] = {
+ "Thanks.",
+ END_DIALOG
+};
+
+const static char* dialog_176[] = {
+ CHANGE_CHARACTER,
+ "What the...",
+ END_DIALOG
+};
+
+const static char* dialog_177[] = {
+ "Hey, aren't you thirsty?",
+ DISPLAY_MESSAGE,
+ "Have you forgotten about your cup?",
+ END_DIALOG
+};
+
+const static char* dialog_178[] = {
+ "Sir, we have been informed that...",
+ CHANGE_CHARACTER,
+ "Later!",
+ DISPLAY_MESSAGE,
+ "I'm busy right now!",
+ CHANGE_CHARACTER,
+ "As you wish, sir.",
+ END_DIALOG
+};
+
+const static char* dialog_179[] = {
+ "Sir, some young boy tried to get inside",
+ NEW_LINE,
+ "the mansion.",
+ END_DIALOG
+};
+
+const static char* dialog_180[] = {
+ "Don't worry.",
+ DISPLAY_MESSAGE,
+ "Young boys are curious...",
+ DISPLAY_MESSAGE,
+ "...and my house plays on their imaginations.",
+ DISPLAY_MESSAGE,
+ "But keep an eye on him.",
+ CHANGE_CHARACTER,
+ "Yes, sir!",
+ END_DIALOG
+};
+
+const static char* dialog_181[] = {
+ "Sir, that boy tried to get in again.",
+ END_DIALOG
+};
+
+const static char* dialog_182[] = {
+ "Do you think it's serious?",
+ CHANGE_CHARACTER,
+ "Hmmm... No...",
+ DISPLAY_MESSAGE,
+ "He doesn't look dangerously.",
+ DISPLAY_MESSAGE,
+ "But maybe we should...",
+ CHANGE_CHARACTER,
+ "Nah.",
+ DISPLAY_MESSAGE,
+ "Just keep him out of the mansion.",
+ DISPLAY_MESSAGE,
+ "But tell me if he appears again.",
+ DISPLAY_MESSAGE,
+ "Now get back to your job.",
+ END_DIALOG
+};
+
+const static char* dialog_183[] = {
+ "Don't tell me it's that boy again...",
+ CHANGE_CHARACTER,
+ "I'm afraid so.",
+ DISPLAY_MESSAGE,
+ "The guard says the boy's really desperate.",
+ END_DIALOG
+};
+
+const static char* dialog_184[] = {
+ "He's starting to get on my nerves.",
+ DISPLAY_MESSAGE,
+ "And what am I paying you for?",
+ CHANGE_CHARACTER,
+ "Should I...",
+ CHANGE_CHARACTER,
+ "Not yet.",
+ DISPLAY_MESSAGE,
+ "Let's give him a last chance.",
+ END_DIALOG
+};
+
+const static char* dialog_185[] = {
+ "Sir...",
+ CHANGE_CHARACTER,
+ "Let me guess...",
+ DISPLAY_MESSAGE,
+ "THE BOY?!?...",
+ CHANGE_CHARACTER,
+ "Bingo.",
+ CHANGE_CHARACTER,
+ "Why do I have to do everything?!",
+ DISPLAY_MESSAGE,
+ "Can't you do anything yourself?",
+ CHANGE_CHARACTER,
+ "Shall I kill him or just beat him to pieces?",
+ CHANGE_CHARACTER,
+ "You're stupid.",
+ DISPLAY_MESSAGE,
+ "There are ...better ways...",
+ END_DIALOG
+};
+
+const static char* dialog_186[] = {
+ "I'll handle it myself.",
+ DISPLAY_MESSAGE,
+ "Now get out!",
+ DISPLAY_MESSAGE,
+ "I have to change my clothes.",
+ END_DIALOG
+};
+
+const static char* dialog_187[] = {
+ "Hey, you up there!",
+ DISPLAY_MESSAGE,
+ "Get down at once!",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "Zero reaction.",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "Is it deaf or something?",
+ END_DIALOG
+};
+
+const static char* dialog_188[] = {
+ "Hey, birdy, don't be shy.",
+ DISPLAY_MESSAGE,
+ "Come to me...",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "(sigh)",
+ END_DIALOG
+};
+
+const static char* dialog_189[] = {
+ "Come here, little bird...",
+ END_DIALOG
+};
+
+const static char* dialog_190[] = {
+ NEW_LINE,
+ "Hey, keep away from this door!",
+ CHANGE_CHARACTER,
+ "Why?",
+ CHANGE_CHARACTER,
+ "None of your business.",
+ DISPLAY_MESSAGE,
+ "Just keep away.",
+ END_DIALOG
+};
+
+const static char* dialog_191[] = {
+ CHANGE_CHARACTER,
+ "I told you to keep away, didn't I?",
+ CHANGE_CHARACTER,
+ "OK, OK...",
+ END_DIALOG
+};
+
+const static char* dialog_192[] = {
+ "I've got a new delivery of gold.",
+ CHANGE_CHARACTER,
+ "Yeah, I know.",
+ DISPLAY_MESSAGE,
+ "Password?",
+ CHANGE_CHARACTER,
+ "Bimbo.",
+ CHANGE_CHARACTER,
+ "All right.",
+ DISPLAY_MESSAGE,
+ "You can bring the gold in.",
+ CHANGE_CHARACTER,
+ "Okey dokey.",
+ END_DIALOG
+};
+
+const static char* dialog_193[] = {
+ "As I told you, our organisation",
+ NEW_LINE,
+ "takes care of unusual problems.",
+ DISPLAY_MESSAGE,
+ "Last time we solved the problem of a UFO",
+ NEW_LINE,
+ "over the White House.",
+ CHANGE_CHARACTER,
+ "Oh, heally?",
+ DISPLAY_MESSAGE,
+ "How?",
+ CHANGE_CHARACTER,
+ "We shot the thing down.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "I undehstand.",
+ DISPLAY_MESSAGE,
+ "And who oh ...what was inside?",
+ CHANGE_CHARACTER,
+ "You want to know?",
+ CHANGE_CHARACTER,
+ "Oh, yes! As a fohtune-telleh",
+ NEW_LINE,
+ "I'm a cuhious pehson.",
+ CHANGE_CHARACTER,
+ "Do you REALLY want to know?",
+ CHANGE_CHARACTER,
+ "YES!",
+ CHANGE_CHARACTER,
+ "But...",
+ DISPLAY_MESSAGE,
+ "...REALLY REALLY?",
+ CHANGE_CHARACTER,
+ "YES!",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "Sorry, I can't tell you.",
+ DISPLAY_MESSAGE,
+ "Anyway, we need your help.",
+ CHANGE_CHARACTER,
+ "I'm not a sechet agent, I'm a fohtune-tell...",
+ CHANGE_CHARACTER,
+ "I know.",
+ DISPLAY_MESSAGE,
+ "We have a very difficult case,",
+ NEW_LINE,
+ "which we haven't been able",
+ NEW_LINE,
+ "to solve for 6 months.",
+ DISPLAY_MESSAGE,
+ "We're in a hopeless situation.",
+ DISPLAY_MESSAGE,
+ "I thought to myself, if we handle",
+ NEW_LINE,
+ "strange cases...",
+ DISPLAY_MESSAGE,
+ "...then why not use",
+ NEW_LINE,
+ "strange means?",
+ CHANGE_CHARACTER,
+ "And?...",
+ CHANGE_CHARACTER,
+ "Let me show you the phone-book.",
+ DISPLAY_MESSAGE,
+ "Use your powers and select a name.",
+ DISPLAY_MESSAGE,
+ "Maybe a fresh mind will solve the case.",
+ CHANGE_CHARACTER,
+ "You don't believe it will wohk, do you?",
+ CHANGE_CHARACTER,
+ "No, I don't.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "This is stupid.",
+ CHANGE_CHARACTER,
+ "I know.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "Okay. Show me the book.",
+ END_DIALOG
+};
+
+const static char* dialog_194[] = {
+ ANIM_WAIT,
+ "The name is...",
+ DISPLAY_MESSAGE,
+ "...Hoppeh...",
+ DISPLAY_MESSAGE,
+ "...Mahk Hoppeh...",
+ DISPLAY_MESSAGE,
+ "Hm...",
+ END_DIALOG
+};
+
+const static char* dialog_195[] = {
+ "He's coming.",
+ END_DIALOG
+};
+
+const static char* dialog_196[] = {
+ "Oh, I'm sorry about my men.",
+ DISPLAY_MESSAGE,
+ "Sometimes they get a bit too nervous...",
+ DISPLAY_MESSAGE,
+ "But, please...",
+ DISPLAY_MESSAGE,
+ "Let's talk...",
+ END_DIALOG
+};
+
+const static char* dialog_197[] = {
+ "Listen, mister...",
+ CHANGE_CHARACTER,
+ "I know, I know.",
+ DISPLAY_MESSAGE,
+ "Please, give me five minutes and",
+ NEW_LINE,
+ "everything will become clear.",
+ CHANGE_CHARACTER,
+ "Go on, I always liked that conspiracy stuff.",
+ CHANGE_CHARACTER,
+ "Well...",
+ DISPLAY_MESSAGE,
+ "I'm head of a secret government organization",
+ NEW_LINE,
+ "called the RGB.",
+ CHANGE_CHARACTER,
+ "Why RGB?",
+ CHANGE_CHARACTER,
+ "Even I don't know.",
+ DISPLAY_MESSAGE,
+ "It's so secret.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "Cool.",
+ CHANGE_CHARACTER,
+ "The aim of my organization is to solve",
+ NEW_LINE,
+ "all the extraordinary problems around",
+ NEW_LINE,
+ "the world.",
+ CHANGE_CHARACTER,
+ "Like taxes?",
+ CHANGE_CHARACTER,
+ "No, like UFOs, strange inventions,",
+ NEW_LINE,
+ "spirits...",
+ CHANGE_CHARACTER,
+ "Wow!",
+ CHANGE_CHARACTER,
+ "Yes, when the police, the secret service and so on",
+ NEW_LINE,
+ "can't solve the problem...",
+ DISPLAY_MESSAGE,
+ "...it's delivered to us. But...",
+ DISPLAY_MESSAGE,
+ "You see, six months ago gold and cash",
+ NEW_LINE,
+ "deposited in bank safes started to",
+ NEW_LINE,
+ "disappear.",
+ DISPLAY_MESSAGE,
+ "Literally. Pum! And it's gone!",
+ CHANGE_CHARACTER,
+ "And?...",
+ CHANGE_CHARACTER,
+ "Gone - without a trace.",
+ DISPLAY_MESSAGE,
+ "The whole thing happens in a few seconds.",
+ DISPLAY_MESSAGE,
+ "We have video recordings but they don't",
+ NEW_LINE,
+ "show anything.",
+ DISPLAY_MESSAGE,
+ "That's why we hired the fortune-teller",
+ NEW_LINE,
+ "to show us someone who could be our",
+ NEW_LINE,
+ "salvation.",
+ DISPLAY_MESSAGE,
+ "She has chosen you.",
+ CHANGE_CHARACTER,
+ "I beg your pardon...",
+ DISPLAY_MESSAGE,
+ "You said you have hired...",
+ DISPLAY_MESSAGE,
+ "...A FORTUNE TELLER?!?",
+ CHANGE_CHARACTER,
+ "Yes, we're desperate and",
+ NEW_LINE,
+ "we'll try everything once.",
+ CHANGE_CHARACTER,
+ "This is crazy. Mum, wake me up!",
+ CHANGE_CHARACTER,
+ "Relax.",
+ DISPLAY_MESSAGE,
+ "We have a proposal for you.",
+ DISPLAY_MESSAGE,
+ "Try to help us and you will be rewarded.",
+ CHANGE_CHARACTER,
+ "What's in it for me?",
+ CHANGE_CHARACTER,
+ "Self-satisfaction?",
+ END_DIALOG
+};
+
+const static char* dialog_198[] = {
+ CHANGE_CHARACTER,
+ "Our respect?",
+ END_DIALOG
+};
+
+const static char* dialog_199[] = {
+ CHANGE_CHARACTER,
+ "Patriotism?",
+ END_DIALOG
+};
+
+const static char* dialog_200[] = {
+ CHANGE_CHARACTER,
+ "Girls?",
+ CHANGE_CHARACTER,
+ "What do you mean?",
+ CHANGE_CHARACTER,
+ "Every girl loves a secret agent.",
+ END_DIALOG
+};
+
+const static char* dialog_201[] = {
+ "Ok, I agree. What am I supposed to do?",
+ CHANGE_CHARACTER,
+ "Before you start, I suggest that first",
+ NEW_LINE,
+ "you get some training in our special",
+ NEW_LINE,
+ "secret camp.",
+ DISPLAY_MESSAGE,
+ "I'll issue a pass for you.",
+ DISPLAY_MESSAGE,
+ "Deal?",
+ CHANGE_CHARACTER,
+ "Deal!",
+ END_DIALOG
+};
+
+const static char* dialog_202[] = {
+ "...and it was even fun.",
+ CHANGE_CHARACTER,
+ "I'm glad you liked our training methods.",
+ DISPLAY_MESSAGE,
+ "But let's get to the point.",
+ DISPLAY_MESSAGE,
+ "I must admit I didn't believe you could",
+ NEW_LINE,
+ "actually help.",
+ DISPLAY_MESSAGE,
+ "Nothing personal.",
+ CHANGE_CHARACTER,
+ "I hope so.",
+ CHANGE_CHARACTER,
+ "But you brought us luck.",
+ DISPLAY_MESSAGE,
+ "Our people found out that some",
+ NEW_LINE,
+ "businessman is spending his",
+ NEW_LINE,
+ "money like crazy...",
+ DISPLAY_MESSAGE,
+ "...for some strange materials.",
+ DISPLAY_MESSAGE,
+ "There are three very suspicious things",
+ NEW_LINE,
+ "about him:",
+ DISPLAY_MESSAGE,
+ "...He pays in cash, which is very strange",
+ NEW_LINE,
+ "in a plastic card century...",
+ DISPLAY_MESSAGE,
+ "...Second, half a year ago he wasn't nearly",
+ NEW_LINE,
+ "as rich as he is now...",
+ DISPLAY_MESSAGE,
+ "...Third, what the hell does he need",
+ NEW_LINE,
+ "100 kg of borax for?",
+ CHANGE_CHARACTER,
+ "Maybe he's just a weirdo.",
+ CHANGE_CHARACTER,
+ "Maybe.",
+ DISPLAY_MESSAGE,
+ "But I want you to fly to the place",
+ NEW_LINE,
+ "and try to sneak inside his mansion...",
+ DISPLAY_MESSAGE,
+ "...to find out some more information.",
+ DISPLAY_MESSAGE,
+ "What do you say?",
+ CHANGE_CHARACTER,
+ "Well...",
+ CHANGE_CHARACTER,
+ "I promise you'll be an official secret",
+ NEW_LINE,
+ "agent after this mission.",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "Promise?",
+ CHANGE_CHARACTER,
+ "My word of honour.",
+ CHANGE_CHARACTER,
+ "Okay. I'm ready.",
+ DISPLAY_MESSAGE,
+ "Where am I supposed to go?",
+ CHANGE_CHARACTER,
+ "It's a little village.",
+ DISPLAY_MESSAGE,
+ "You won't find it on many maps...",
+ DISPLAY_MESSAGE,
+ "But before you go, let me give you some special",
+ NEW_LINE,
+ "agent equipment.",
+ DISPLAY_MESSAGE,
+ "I would give you some boots to make you fly,",
+ NEW_LINE,
+ "but I've lent them to somebody.",
+ DISPLAY_MESSAGE,
+ "The mega-power gauntlets are also",
+ NEW_LINE,
+ "out of stock.",
+ DISPLAY_MESSAGE,
+ "As a matter of act I only have special",
+ NEW_LINE,
+ "super glue.",
+ DISPLAY_MESSAGE,
+ "Well, that's better than nothing...",
+ DISPLAY_MESSAGE,
+ "Good luck!",
+ END_DIALOG
+};
+
+const static char* dialog_203[] = {
+ CHANGE_CHARACTER,
+ "Don't worry.",
+ DISPLAY_MESSAGE,
+ "He'll be okay.",
+ DISPLAY_MESSAGE,
+ "Just... oh, look, here he goes...",
+ END_DIALOG
+};
+
+const static char* dialog_204[] = {
+ CHANGE_CHARACTER,
+ "He got what he deserved.",
+ DISPLAY_MESSAGE,
+ "But we've wasted enough time. Let's go!",
+ CHANGE_CHARACTER,
+ "No! Wait!",
+ DISPLAY_MESSAGE,
+ "I have to see Anne!",
+ CHANGE_CHARACTER,
+ "Ermm... You can't.",
+ CHANGE_CHARACTER,
+ "And why is that?!",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "You see... Anne was our man.",
+ DISPLAY_MESSAGE,
+ "She was ordered to keep an eye on you",
+ NEW_LINE,
+ "in case the microcamera got out of",
+ NEW_LINE,
+ "order.",
+ DISPLAY_MESSAGE,
+ "And she was also your motivation...",
+ CHANGE_CHARACTER,
+ "I don't believe you!",
+ CHANGE_CHARACTER,
+ "She has already gone off on",
+ NEW_LINE,
+ "her next mission.",
+ DISPLAY_MESSAGE,
+ "Sorry.",
+ CHANGE_CHARACTER,
+ "I guess grandma was involved too?",
+ CHANGE_CHARACTER,
+ "No, she's from here. We payed her.",
+ CHANGE_CHARACTER,
+ "Now that's interesting.",
+ DISPLAY_MESSAGE,
+ "Because if so, why did I have so",
+ NEW_LINE,
+ "many problems?...",
+ CHANGE_CHARACTER,
+ "We were pumping up your determination.",
+ DISPLAY_MESSAGE,
+ "We counted on you to have some strong will.",
+ DISPLAY_MESSAGE,
+ "We were not wrong, were we?",
+ CHANGE_CHARACTER,
+ "You treat people like animals in",
+ NEW_LINE,
+ "an experiment.",
+ DISPLAY_MESSAGE,
+ "You're ruthless...",
+ CHANGE_CHARACTER,
+ "It worked, didn't it?",
+ CHANGE_CHARACTER,
+ "This is all so unbelievable.",
+ DISPLAY_MESSAGE,
+ "Maybe you're gonna tell me that the dog is",
+ NEW_LINE,
+ "a masked agent...",
+ DISPLAY_MESSAGE,
+ "...the old man was my guard...",
+ DISPLAY_MESSAGE,
+ "...and you are from Mars?!",
+ END_DIALOG
+};
+
+const static char* dialog_205[] = {
+ CHANGE_CHARACTER,
+ "It's not a soap opera, it's",
+ NEW_LINE,
+ "just usual agent work.",
+ DISPLAY_MESSAGE,
+ "But hey, join the RGB and you could",
+ NEW_LINE,
+ "work with Anne there!",
+ CHANGE_CHARACTER,
+ ANIM_WAIT,
+ "Well...",
+ DISPLAY_MESSAGE,
+ "I'll think about it...",
+ CHANGE_CHARACTER,
+ "Great.",
+ DISPLAY_MESSAGE,
+ "It was a pleasure to see you in action!",
+ END_DIALOG
+};
+
+const static char* dialog_206[] = {
+ CHANGE_CHARACTER,
+ "You don't have to tell me.",
+ DISPLAY_MESSAGE,
+ "I have already read a very detailed report.",
+ CHANGE_CHARACTER,
+ "But what happened to the professor?",
+ CHANGE_CHARACTER,
+ "Oh, that poor man has forgotten the pill recipe",
+ NEW_LINE,
+ "again.",
+ DISPLAY_MESSAGE,
+ "We'll give him the best laboratory we can.",
+ DISPLAY_MESSAGE,
+ "Right now we have only those few pills",
+ NEW_LINE,
+ "you gave us.",
+ CHANGE_CHARACTER,
+ "And John Noty?",
+ CHANGE_CHARACTER,
+ "Don't worry, his greediness will be punished.",
+ CHANGE_CHARACTER,
+ "I hope so...",
+ DISPLAY_MESSAGE,
+ "And one more little thing...",
+ DISPLAY_MESSAGE,
+ "You have promised me something...",
+ END_DIALOG
+};
+
+const static char* dialog_207[] = {
+ CHANGE_CHARACTER,
+ "Me?...",
+ DISPLAY_MESSAGE,
+ "I don't remember...",
+ CHANGE_CHARACTER,
+ "You said you'll make me an official agent...",
+ DISPLAY_MESSAGE,
+ "'Girls love secret agents'. Remember?",
+ END_DIALOG
+};
+
+const static char* dialog_208[] = {
+ CHANGE_CHARACTER,
+ "(sigh)",
+ DISPLAY_MESSAGE,
+ "A promise is a promise...",
+ DISPLAY_MESSAGE,
+ "Let me think.",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "All right. Come here.",
+ END_DIALOG
+};
+
+const static char* dialog_209[] = {
+ "In the name of...",
+ DISPLAY_MESSAGE,
+ "...blah...blah...blah...",
+ DISPLAY_MESSAGE,
+ "...blah...blah...",
+ DISPLAY_MESSAGE,
+ "...for our country.",
+ END_DIALOG
+};
+
+const static char* dialog_210[] = {
+ " Well... ",
+ DISPLAY_MESSAGE,
+ "That's all, folks!",
+ END_DIALOG
+};
+
+const static char* dialog_211[] = {
+ "I found the time pill!",
+ DISPLAY_MESSAGE,
+ "It must have fallen out of the jar!...",
+ DISPLAY_MESSAGE,
+ ANIM_WAIT,
+ "Cool.",
+ END_DIALOG
+};
+
+const static char* dialog_212[] = {
+ "Wow!",
+ DISPLAY_MESSAGE,
+ "This is charming!...",
+ END_DIALOG
+};
+
+const static char** dialogs[] = {
+ dialog_0,
+ dialog_1,
+ dialog_2,
+ dialog_3,
+ dialog_4,
+ dialog_5,
+ dialog_6,
+ dialog_7,
+ dialog_8,
+ dialog_9,
+ dialog_10,
+ dialog_11,
+ dialog_12,
+ dialog_13,
+ dialog_14,
+ dialog_15,
+ dialog_16,
+ dialog_17,
+ dialog_18,
+ dialog_19,
+ dialog_20,
+ dialog_21,
+ dialog_22,
+ dialog_23,
+ dialog_24,
+ dialog_25,
+ dialog_26,
+ dialog_27,
+ dialog_28,
+ dialog_29,
+ dialog_30,
+ dialog_31,
+ dialog_32,
+ dialog_33,
+ dialog_34,
+ dialog_35,
+ dialog_36,
+ dialog_37,
+ dialog_38,
+ dialog_39,
+ dialog_40,
+ dialog_41,
+ dialog_42,
+ dialog_43,
+ dialog_44,
+ dialog_45,
+ dialog_46,
+ dialog_47,
+ dialog_48,
+ dialog_49,
+ dialog_50,
+ dialog_51,
+ dialog_52,
+ dialog_53,
+ dialog_54,
+ dialog_55,
+ dialog_56,
+ dialog_57,
+ dialog_58,
+ dialog_59,
+ dialog_60,
+ dialog_61,
+ dialog_62,
+ dialog_63,
+ dialog_64,
+ dialog_65,
+ dialog_66,
+ dialog_67,
+ dialog_68,
+ dialog_69,
+ dialog_70,
+ dialog_71,
+ dialog_72,
+ dialog_73,
+ dialog_74,
+ dialog_75,
+ dialog_76,
+ dialog_77,
+ dialog_78,
+ dialog_79,
+ dialog_80,
+ dialog_81,
+ dialog_82,
+ dialog_83,
+ dialog_84,
+ dialog_85,
+ dialog_86,
+ dialog_87,
+ dialog_88,
+ dialog_89,
+ dialog_90,
+ dialog_91,
+ dialog_92,
+ dialog_93,
+ dialog_94,
+ dialog_95,
+ dialog_96,
+ dialog_97,
+ dialog_98,
+ dialog_99,
+ dialog_100,
+ dialog_101,
+ dialog_102,
+ dialog_103,
+ dialog_104,
+ dialog_105,
+ dialog_106,
+ dialog_107,
+ dialog_108,
+ dialog_109,
+ dialog_110,
+ dialog_111,
+ dialog_112,
+ dialog_113,
+ dialog_114,
+ dialog_115,
+ dialog_116,
+ dialog_117,
+ dialog_118,
+ dialog_119,
+ dialog_120,
+ dialog_121,
+ dialog_122,
+ dialog_123,
+ dialog_124,
+ dialog_125,
+ dialog_126,
+ dialog_127,
+ dialog_128,
+ dialog_129,
+ dialog_130,
+ dialog_131,
+ dialog_132,
+ dialog_133,
+ dialog_134,
+ dialog_135,
+ dialog_136,
+ dialog_137,
+ dialog_138,
+ dialog_139,
+ dialog_140,
+ dialog_141,
+ dialog_142,
+ dialog_143,
+ dialog_144,
+ dialog_145,
+ dialog_146,
+ dialog_147,
+ dialog_148,
+ dialog_149,
+ dialog_150,
+ dialog_151,
+ dialog_152,
+ dialog_153,
+ dialog_154,
+ dialog_155,
+ dialog_156,
+ dialog_157,
+ dialog_158,
+ dialog_159,
+ dialog_160,
+ dialog_161,
+ dialog_162,
+ dialog_163,
+ dialog_164,
+ dialog_165,
+ dialog_166,
+ dialog_167,
+ dialog_168,
+ dialog_169,
+ dialog_170,
+ dialog_171,
+ dialog_172,
+ dialog_173,
+ dialog_174,
+ dialog_175,
+ dialog_176,
+ dialog_177,
+ dialog_178,
+ dialog_179,
+ dialog_180,
+ dialog_181,
+ dialog_182,
+ dialog_183,
+ dialog_184,
+ dialog_185,
+ dialog_186,
+ dialog_187,
+ dialog_188,
+ dialog_189,
+ dialog_190,
+ dialog_191,
+ dialog_192,
+ dialog_193,
+ dialog_194,
+ dialog_195,
+ dialog_196,
+ dialog_197,
+ dialog_198,
+ dialog_199,
+ dialog_200,
+ dialog_201,
+ dialog_202,
+ dialog_203,
+ dialog_204,
+ dialog_205,
+ dialog_206,
+ dialog_207,
+ dialog_208,
+ dialog_209,
+ dialog_210,
+ dialog_211,
+ dialog_212
+};
+
+#endif
diff --git a/devtools/create_teenagent/util.cpp b/devtools/create_teenagent/util.cpp
new file mode 100644
index 0000000000..5ce8237b85
--- /dev/null
+++ b/devtools/create_teenagent/util.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.
+ *
+ */
+
+// Disable symbol overrides so that we can use system headers.
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "util.h"
+#include <stdarg.h>
+
+#ifdef _MSC_VER
+ #define vsnprintf _vsnprintf
+#endif
+
+void error(const char *s, ...) {
+ char buf[1024];
+ va_list va;
+
+ va_start(va, s);
+ vsnprintf(buf, 1024, s, va);
+ va_end(va);
+
+ fprintf(stderr, "ERROR: %s!\n", buf);
+
+ exit(1);
+}
+
+void warning(const char *s, ...) {
+ char buf[1024];
+ va_list va;
+
+ va_start(va, s);
+ vsnprintf(buf, 1024, s, va);
+ va_end(va);
+
+ fprintf(stderr, "WARNING: %s!\n", buf);
+}
+
+int scumm_stricmp(const char *s1, const char *s2) {
+ byte l1, l2;
+ do {
+ // Don't use ++ inside tolower, in case the macro uses its
+ // arguments more than once.
+ l1 = (byte)*s1++;
+ l1 = tolower(l1);
+ l2 = (byte)*s2++;
+ l2 = tolower(l2);
+ } while (l1 == l2 && l1 != 0);
+ return l1 - l2;
+}
+
+void debug(int level, const char *s, ...) {
+ char buf[1024];
+ va_list va;
+
+ va_start(va, s);
+ vsnprintf(buf, 1024, s, va);
+ va_end(va);
+
+ fprintf(stderr, "DEBUG: %s!\n", buf);
+}
+
+uint8 readByte(FILE *fp) {
+ return fgetc(fp);
+}
+
+uint16 readUint16BE(FILE *fp) {
+ uint16 ret = 0;
+ ret |= fgetc(fp) << 8;
+ ret |= fgetc(fp);
+ return ret;
+}
+
+uint16 readUint16LE(FILE *fp) {
+ uint16 ret = 0;
+ ret |= fgetc(fp);
+ ret |= fgetc(fp) << 8;
+ return ret;
+}
+
+uint32 readUint32BE(FILE *fp) {
+ uint32 ret = 0;
+ ret |= fgetc(fp) << 24;
+ ret |= fgetc(fp) << 16;
+ ret |= fgetc(fp) << 8;
+ ret |= fgetc(fp);
+ return ret;
+}
+
+uint32 readUint32LE(FILE *fp) {
+ uint32 ret = 0;
+ ret |= fgetc(fp);
+ ret |= fgetc(fp) << 8;
+ ret |= fgetc(fp) << 16;
+ ret |= fgetc(fp) << 24;
+ return ret;
+}
+
+void writeByte(FILE *fp, uint8 b) {
+ fwrite(&b, 1, 1, fp);
+}
+
+void writeUint16BE(FILE *fp, uint16 value) {
+ writeByte(fp, (uint8)(value >> 8));
+ writeByte(fp, (uint8)(value));
+}
+
+void writeUint16LE(FILE *fp, uint16 value) {
+ writeByte(fp, (uint8)(value));
+ writeByte(fp, (uint8)(value >> 8));
+}
+
+void writeUint32BE(FILE *fp, uint32 value) {
+ writeByte(fp, (uint8)(value >> 24));
+ writeByte(fp, (uint8)(value >> 16));
+ writeByte(fp, (uint8)(value >> 8));
+ writeByte(fp, (uint8)(value));
+}
+
+void writeUint32LE(FILE *fp, uint32 value) {
+ writeByte(fp, (uint8)(value));
+ writeByte(fp, (uint8)(value >> 8));
+ writeByte(fp, (uint8)(value >> 16));
+ writeByte(fp, (uint8)(value >> 24));
+}
+
+uint32 fileSize(FILE *fp) {
+ uint32 sz;
+ uint32 pos = ftell(fp);
+ fseek(fp, 0, SEEK_END);
+ sz = ftell(fp);
+ fseek(fp, pos, SEEK_SET);
+ return sz;
+}
diff --git a/devtools/create_teenagent/util.h b/devtools/create_teenagent/util.h
index 0d8e15cc37..a2783cca71 100644
--- a/devtools/create_teenagent/util.h
+++ b/devtools/create_teenagent/util.h
@@ -50,6 +50,7 @@ uint32 fileSize(FILE *fp);
void NORETURN_PRE error(const char *s, ...) NORETURN_POST;
void warning(const char *s, ...);
void debug(int level, const char *s, ...);
+int scumm_stricmp(const char *s1, const char *s2);
using namespace Common;
diff --git a/devtools/create_tony/create_tony.h b/devtools/create_tony/create_tony.h
index cc23eca1b7..3075835bd9 100644
--- a/devtools/create_tony/create_tony.h
+++ b/devtools/create_tony/create_tony.h
@@ -28,7 +28,7 @@
#define DATAALIGNMENT 4
#define TONY_DAT_VER_MAJ 0 // 1 byte
-#define TONY_DAT_VER_MIN 1 // 1 byte
+#define TONY_DAT_VER_MIN 3 // 1 byte
// Number of variants of the game. For the moment, it's the same
// as the number of languages
diff --git a/devtools/create_tony/staticdata.h b/devtools/create_tony/staticdata.h
index 793f897aba..fff977d8dc 100644
--- a/devtools/create_tony/staticdata.h
+++ b/devtools/create_tony/staticdata.h
@@ -1046,17 +1046,17 @@ const int _cTableObjIta[] = {
13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, -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, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 52, -1, -1, -1, -1, -1, 67,
- -1, 60, -1, -1, 66, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 61, -1, -1,
- -1, -1, -1, 69, -1, -1, 70, 71, 68, -1,
- 72, -1, -1, 73, 75, -1, -1, 76, -1, 65,
- 78, -1, -1, -1, 79, -1, -1, 81, -1, -1,
+ 91, -1, -1, 93, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 91, -1, -1, 93,
+ -1, -1, -1, 88, -1, 85, -1, -1, -1, 67,
+ -1, 60, -1, -1, 66, 92, -1, -1, -1, 88,
+ -1, -1, -1, -1, -1, 85, -1, 61, -1, -1,
+ -1, 92, -1, 69, -1, -1, 70, 71, 86, -1,
+ 72, -1, 87, 73, 75, -1, -1, 76, -1, 89,
+ 78, 90, -1, -1, 79, -1, -1, 81, -1, -1,
82, -1, -1, -1, -1, -1, -1, -1, 70, -1,
- -1, 63, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 79, -1, 62, -1,
+ 86, 63, -1, -1, 87, -1, -1, -1, -1, -1,
+ -1, 89, -1, 90, -1, -1, 79, -1, 62, -1,
-1, -1, 82, -1, -1, -1};
const int _lTableObjIta[] = {
@@ -1074,18 +1074,18 @@ const int _lTableObjIta[] = {
17, 19, 17, 19, 14, 13, 15, 15, 13, 19,
15, 13, 20, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 17,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26};
+ 15, 26, 26, 21, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 15, 26, 26, 21,
+ 26, 26, 26, 19, 26, 20, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 21, 26, 26, 26, 19,
+ 26, 26, 26, 26, 26, 20, 26, 26, 26, 26,
+ 26, 21, 26, 26, 26, 26, 17, 26, 22, 26,
+ 26, 26, 17, 26, 26, 26, 26, 26, 26, 17,
+ 26, 22, 26, 26, 19, 26, 26, 26, 26, 26,
+ 15, 26, 26, 26, 26, 26, 26, 26, 17, 26,
+ 22, 26, 26, 26, 17, 26, 26, 26, 26, 26,
+ 26, 17, 26, 22, 26, 26, 19, 26, 26, 26,
+ 26, 26, 15, 26, 26, 26};
const int _cTableObjPol[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
@@ -1135,13 +1135,13 @@ const int _lTableObjPol[] = {
26, 26, 26, 19, 26, 20, 26, 26, 26, 26,
26, 26, 26, 26, 26, 21, 26, 26, 26, 19,
26, 26, 26, 26, 26, 20, 26, 26, 26, 26,
- 26, 21, 26, 26, 26, 26, 26, 26, 22, 26,
+ 26, 21, 26, 26, 26, 26, 17, 26, 22, 26,
26, 26, 17, 26, 26, 26, 26, 26, 26, 17,
- 26, 22, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 22, 26, 26, 19, 26, 26, 26, 26, 26,
+ 15, 26, 26, 26, 26, 26, 26, 26, 17, 26,
22, 26, 26, 26, 17, 26, 26, 26, 26, 26,
- 26, 17, 26, 22, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26};
+ 26, 17, 26, 22, 26, 26, 19, 26, 26, 26,
+ 26, 26, 15, 26, 26, 26};
const int _cTableObjRus[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
@@ -1158,12 +1158,12 @@ const int _cTableObjRus[] = {
13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, -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, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 52, -1, 85, -1, -1, 100, 67,
- -1, 60, -1, -1, 66, -1, -1, -1, -1, -1,
+ 91, -1, -1, 93, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 91, -1, -1, 93,
+ -1, -1, -1, 88, -1, 85, -1, -1, 100, 67,
+ -1, 60, -1, -1, 66, 92, -1, -1, -1, 88,
-1, -1, -1, -1, 100, 85, -1, 61, -1, -1,
- -1, -1, 94, 95, 96, 97, 98, 99, 101, 102,
+ -1, 92, 94, 95, 96, 97, 98, 99, 101, 102,
103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
113, 114, 115, 116, 117, 118, 119, 120, 122, 123,
121, 124, 125, 126, 94, 95, 96, 97, 98, 99,
@@ -1186,12 +1186,12 @@ const int _lTableObjRus[] = {
17, 19, 17, 19, 14, 13, 15, 15, 13, 19,
15, 13, 20, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 20, 26, 26, 18, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 15, 26, 26, 21, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 15, 26, 26, 21,
+ 26, 26, 26, 19, 26, 20, 26, 26, 18, 26,
+ 26, 26, 26, 26, 26, 21, 26, 26, 26, 19,
26, 26, 26, 26, 18, 20, 26, 26, 26, 26,
- 26, 26, 18, 18, 18, 17, 16, 18, 20, 18,
+ 26, 21, 18, 18, 18, 17, 16, 18, 20, 18,
18, 18, 18, 16, 18, 15, 22, 15, 18, 22,
19, 16, 21, 20, 16, 16, 19, 22, 19, 19,
18, 15, 18, 18, 18, 18, 18, 17, 16, 18,
@@ -1214,17 +1214,17 @@ const int _cTableObjCze[] = {
13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, 128, -1,
- -1, 137, 131, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 128, -1, -1, 137, 131, -1,
- -1, -1, -1, 52, -1, -1, -1, -1, -1, 67,
- -1, 60, -1, -1, 66, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 61, -1, -1,
- -1, -1, -1, 133, -1, -1, 70, 71, 68, -1,
- 129, 135, -1, 73, 127, 134, -1, 136, -1, 65,
+ 91, 137, 131, 93, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 128, -1, 91, 137, 131, 93,
+ -1, -1, -1, 88, -1, 85, -1, -1, -1, 67,
+ -1, 60, -1, -1, 66, 92, -1, -1, -1, 88,
+ -1, -1, -1, -1, -1, 85, -1, 61, -1, -1,
+ -1, 92, -1, 133, -1, -1, 70, 71, 86, -1,
+ 129, 135, 87, 73, 127, 134, -1, 136, -1, 89,
138, 139, -1, -1, 79, -1, 130, 140, 141, -1,
82, 132, -1, -1, -1, 133, -1, -1, 70, -1,
- -1, 63, 129, 135, -1, -1, 127, 134, -1, 136,
- -1, -1, 138, 139, -1, -1, 79, -1, 130, 140,
+ 86, 63, 129, 135, 87, -1, 127, 134, -1, 136,
+ -1, 89, 138, 139, -1, -1, 79, -1, 130, 140,
141, -1, 82, 132, -1, -1};
const int _lTableObjCze[] = {
@@ -1242,18 +1242,18 @@ const int _lTableObjCze[] = {
17, 19, 17, 19, 14, 13, 15, 15, 13, 19,
15, 13, 20, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 15, 26,
- 26, 24, 21, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 15, 26, 26, 24, 21, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 18, 26, 26, 26, 26, 26, 26,
- 22, 17, 26, 26, 17, 19, 26, 23, 26, 17,
- 17, 22, 26, 26, 26, 26, 18, 16, 16, 26,
- 26, 16, 26, 26, 26, 18, 26, 26, 26, 26,
- 26, 26, 22, 17, 26, 26, 17, 19, 26, 23,
- 26, 26, 17, 22, 26, 26, 26, 26, 18, 16,
- 16, 26, 26, 16, 26, 26};
+ 15, 24, 21, 21, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 15, 26, 15, 24, 21, 21,
+ 26, 26, 26, 19, 26, 20, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 21, 26, 26, 26, 19,
+ 26, 26, 26, 26, 26, 20, 26, 26, 26, 26,
+ 26, 21, 26, 18, 26, 26, 17, 26, 22, 26,
+ 22, 17, 17, 26, 17, 19, 26, 23, 26, 17,
+ 17, 22, 26, 26, 19, 26, 18, 16, 16, 26,
+ 15, 16, 26, 26, 26, 18, 26, 26, 17, 26,
+ 22, 26, 22, 17, 17, 26, 17, 19, 26, 23,
+ 26, 17, 17, 22, 26, 26, 19, 26, 18, 16,
+ 16, 26, 15, 16, 26, 26};
const int _cTableObjFra[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
@@ -1270,17 +1270,17 @@ const int _cTableObjFra[] = {
13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, -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, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 52, -1, -1, -1, -1, -1, 67,
- -1, 60, -1, -1, 66, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 61, -1, -1,
- -1, -1, -1, 69, -1, -1, 70, 71, 68, -1,
- 72, -1, -1, 73, 75, -1, -1, 76, -1, 65,
- 78, -1, -1, -1, 79, -1, -1, 81, -1, -1,
+ 91, -1, -1, 93, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 91, -1, -1, 93,
+ -1, -1, -1, 88, -1, 85, -1, -1, -1, 67,
+ -1, 60, -1, -1, 66, 92, -1, -1, -1, 88,
+ -1, -1, -1, -1, -1, 85, -1, 61, -1, -1,
+ -1, 92, -1, 69, -1, -1, 70, 71, 86, -1,
+ 72, -1, 87, 73, 75, -1, -1, 76, -1, 89,
+ 78, 90, -1, -1, 79, -1, -1, 81, -1, -1,
82, -1, -1, -1, 0, 0, 0, -1, 70, -1,
- -1, 63, 4, 4, -1, -1, 8, 8, 8, -1,
- -1, -1, 14, 14, 14, -1, 14, -1, 62, 20,
+ 86, 63, 4, 4, 87, -1, 8, 8, 8, -1,
+ -1, 89, 14, 14, 14, -1, 14, -1, 62, 20,
-1, 20, 82, -1, -1, -1};
const int _lTableObjFra[] = {
@@ -1298,18 +1298,18 @@ const int _lTableObjFra[] = {
17, 19, 17, 19, 14, 13, 15, 15, 13, 19,
15, 13, 20, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 17,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 17, 17, 17, 26, 26, 26,
- 26, 26, 15, 15, 26, 26, 16, 16, 16, 26,
- 26, 26, 19, 19, 19, 26, 19, 26, 26, 15,
- 26, 15, 26, 26, 26, 26};
+ 15, 26, 26, 21, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 15, 26, 26, 21,
+ 26, 26, 26, 19, 26, 20, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 21, 26, 26, 26, 19,
+ 26, 26, 26, 26, 26, 20, 26, 26, 26, 26,
+ 26, 21, 26, 26, 26, 26, 17, 26, 22, 26,
+ 26, 26, 17, 26, 26, 26, 26, 26, 26, 17,
+ 26, 22, 26, 26, 19, 26, 26, 26, 26, 26,
+ 15, 26, 26, 26, 17, 17, 17, 26, 17, 26,
+ 22, 26, 15, 15, 17, 26, 16, 16, 16, 26,
+ 26, 17, 19, 19, 19, 26, 19, 26, 26, 15,
+ 26, 15, 15, 26, 26, 26};
const int _cTableObjDeu[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
@@ -1326,45 +1326,45 @@ const int _cTableObjDeu[] = {
13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, -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, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 52, -1, -1, -1, -1, -1, 67,
- -1, 60, -1, -1, 66, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 61, -1, -1,
- -1, -1, -1, 69, -1, -1, 70, 71, 68, -1,
- 72, -1, -1, 73, 75, -1, -1, 76, -1, 65,
- 78, -1, -1, -1, 79, -1, -1, 81, -1, -1,
- 82, -1, -1, -1, -1, -1, -1, -1, 70, -1,
- -1, 63, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 79, -1, 62, -1,
+ 91, -1, -1, 93, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 91, -1, -1, 93,
+ -1, -1, -1, 88, -1, 85, -1, -1, -1, 67,
+ -1, 60, -1, -1, 66, 92, -1, -1, -1, 88,
+ -1, -1, -1, -1, -1, 85, -1, 61, -1, -1,
+ -1, 92, -1, 69, -1, -1, 70, 71, 86, -1,
+ 72, -1, 87, 73, 75, -1, -1, 76, -1, 89,
+ 78, 90, -1, -1, 79, -1, -1, 81, -1, -1,
+ 82, -1, -1, 142, -1, -1, -1, -1, 70, -1,
+ 86, 63, -1, -1, 87, -1, -1, -1, -1, -1,
+ -1, 89, -1, 90, -1, -1, 79, -1, 62, -1,
-1, -1, 82, -1, -1, -1};
const int _lTableObjDeu[] = {
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 11, 26, 26, 26, 26, 26, 26, 8,
- 26, 26, 26, 26, 26, 12, 8, 26, 20, 20,
- 15, 20, 20, 20, 20, 20, 20, 20, 26, 26,
- 26, 26, 26, 26, 26, 17, 17, 19, 17, 15,
- 17, 19, 17, 16, 26, 17, 14, 19, 17, 19,
- 17, 19, 14, 13, 15, 15, 13, 19, 15, 13,
- 20, 26, 26, 26, 26, 26, 26, 17, 17, 19,
- 17, 15, 17, 19, 17, 16, 26, 17, 14, 19,
- 17, 19, 17, 19, 14, 13, 15, 15, 13, 19,
- 15, 13, 20, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 17,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 142, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26};
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 11, 26, 26, 26, 26, 26, 26, 8,
+ 26, 26, 26, 26, 26, 12, 8, 26, 20, 20,
+ 15, 20, 20, 20, 20, 20, 20, 20, 26, 26,
+ 26, 26, 26, 26, 26, 17, 17, 19, 17, 15,
+ 17, 19, 17, 16, 26, 17, 14, 19, 17, 19,
+ 17, 19, 14, 13, 15, 15, 13, 19, 15, 13,
+ 20, 26, 26, 26, 26, 26, 26, 17, 17, 19,
+ 17, 15, 17, 19, 17, 16, 26, 17, 14, 19,
+ 17, 19, 17, 19, 14, 13, 15, 15, 13, 19,
+ 15, 13, 20, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 15, 26, 26, 21, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 15, 26, 26, 21,
+ 26, 26, 26, 19, 26, 20, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 21, 26, 26, 26, 19,
+ 26, 26, 26, 26, 26, 20, 26, 26, 26, 26,
+ 26, 21, 26, 26, 26, 26, 17, 26, 22, 26,
+ 26, 26, 17, 26, 26, 26, 26, 26, 26, 17,
+ 26, 22, 26, 26, 19, 26, 26, 26, 26, 26,
+ 15, 26, 26, 24, 26, 26, 26, 26, 17, 26,
+ 22, 26, 26, 26, 17, 26, 26, 26, 26, 26,
+ 26, 17, 26, 22, 26, 26, 19, 26, 26, 26,
+ 26, 26, 15, 26, 26, 26};
#endif
diff --git a/devtools/credits.pl b/devtools/credits.pl
index 7ce17a9df6..e04e35d3be 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 = 21; # The maximal width of a name.
+ $max_name_width = 23; # The maximal width of a name.
} elsif ($mode eq "CPP") {
$Text::Wrap::columns = 48; # Approx.
}
@@ -359,6 +359,9 @@ sub add_person {
my $min_name_width = length $desc > 0 ? $max_name_width : 0;
$name = $nick if $name eq "";
$name = html_entities_to_ascii($name);
+ if (length $name > $max_name_width) {
+ print STDERR "Warning: max_name_width is too small (" . $max_name_width . " < " . (length $name) . " for \"" . $name. "\")\n";
+ }
$desc = html_entities_to_ascii($desc);
$tab = " " x ($section_level * 2 + 1);
@@ -613,6 +616,10 @@ begin_credits("Credits");
add_person("", "peres", "");
end_section();
+ begin_section("Pegasus");
+ add_person("Matthew Hoops", "clone2727", "");
+ end_section();
+
begin_section("Queen");
add_person("David Eriksson", "twogood", "(retired)");
add_person("Gregory Montoir", "cyx", "(retired)");
@@ -680,6 +687,12 @@ begin_credits("Credits");
add_person("Joost Peters", "joostp", "");
end_section();
+ begin_section("Tony");
+ add_person("Arnaud Boutonn&eacute;", "Strangerke", "");
+ add_person("Paul Gilbert", "dreammaster", "");
+ add_person("Alyssa Milburn", "fuzzie", "");
+ end_section();
+
begin_section("Toon");
add_person("Sylvain Dupont", "SylvainTV", "");
end_section();
@@ -697,6 +710,10 @@ begin_credits("Credits");
add_person("Gregory Montoir", "cyx", "(retired)");
end_section();
+ begin_section("Wintermute");
+ add_person("Einar Johan T. S&oslash;m&aring;en", "somaen", "");
+ end_section();
+
end_section();
@@ -940,7 +957,7 @@ begin_credits("Credits");
end_section();
begin_section("German");
add_person("Simon Sawatzki", "SimSaw", "");
- add_person("Lothar Serra Mari", "Lothar93", "");
+ add_person("Lothar Serra Mari", "Lothar93", "(retired)");
end_section();
begin_section("Hungarian");
add_person("Alex Bevilacqua", "", "");
@@ -1067,7 +1084,7 @@ begin_credits("Credits");
# HACK!
- $max_name_width = 16;
+ $max_name_width = 17;
begin_section("Special thanks to");
begin_persons();
@@ -1080,6 +1097,7 @@ begin_credits("Credits");
add_person("Ivan Dubrov", "", "For contributing the initial version of the Gobliiins engine");
add_person("Henrik Engqvist", "qvist", "For generously providing hosting for our buildbot, SVN repository, planet and doxygen sites as well as tons of HD space");
add_person("DOSBox Team", "", "For their awesome OPL2 and OPL3 emulator");
+ add_person("Yusuke Kamiyamane", "", "For contributing some GUI icons ");
add_person("Till Kresslein", "Krest", "For design of modern ScummVM GUI");
add_person("", "Jezar", "For his freeverb filter implementation");
add_person("Jim Leiterman", "", "Various info on his FM-TOWNS/Marty SCUMM ports");
@@ -1090,8 +1108,6 @@ begin_credits("Credits");
add_person("James Woodcock", "", "Soundtrack enhancements");
end_persons();
- add_paragraph("Some icons by Yusuke Kamiyamane");
-
add_paragraph(
"Tony Warriner and everyone at Revolution Software Ltd. for sharing ".
"with us the source of some of their brilliant games, allowing us to ".
@@ -1141,7 +1157,15 @@ begin_credits("Credits");
add_paragraph(
"Janusz Wi&#347;niewski and Miroslaw Liminowicz from Laboratorium Komputerowe Avalon ".
- "for providing full source code for So&#322;tys and letting us to redistribute the game.");
+ "for providing full source code for So&#322;tys and letting us redistribute the game.");
+
+ add_paragraph(
+ "Jan Nedoma for providing the sources to the Wintermute-engine, and for his ".
+ "support while porting the engine to ScummVM.");
+
+ add_paragraph(
+ "Bob Bell, Michel Kripalani, Tommy Yune, from Presto Studios for ".
+ "providing the source code of The Journeyman Project: Pegasus Prime.");
end_section();
diff --git a/devtools/module.mk b/devtools/module.mk
index 95eca50d18..1d682cdf05 100644
--- a/devtools/module.mk
+++ b/devtools/module.mk
@@ -56,7 +56,7 @@ credits:
$(srcdir)/devtools/credits.pl --text > $(srcdir)/AUTHORS
# $(srcdir)/devtools/credits.pl --rtf > $(srcdir)/Credits.rtf
$(srcdir)/devtools/credits.pl --cpp > $(srcdir)/gui/credits.h
- $(srcdir)/devtools/credits.pl --xml-website > $(srcdir)/../../web/trunk/data/credits.xml
+ $(srcdir)/devtools/credits.pl --xml-website > $(srcdir)/../scummvm-web/data/credits.xml
# $(srcdir)/devtools/credits.pl --xml-docbook > $(srcdir)/../../docs/trunk/docbook/credits.xml
md5scumm: devtools/md5table$(EXEEXT)
diff --git a/dists/engine-data/README b/dists/engine-data/README
index ce74d590d9..c9c4bd4817 100644
--- a/dists/engine-data/README
+++ b/dists/engine-data/README
@@ -1,6 +1,9 @@
engine-data README
-------------------------------------------------------------------------------
+drascula.dat
+TODO
+
hugo.dat:
This file contains all the hardcoded logic, strings and fonts used by Hugo
engine. Those information were stored in the original executables.
@@ -10,6 +13,9 @@ The 'kyra.dat' file is created by extracting hardcoded data, like the
roomtable, inventory names, various strings, tables for shapes and sequence
scripts, from.
+lure.dat
+TODO
+
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
@@ -20,5 +26,11 @@ mp3/ogg/flac encoded need the datafile.
sky.cpt:
TODO
+teenagent.dat
+TODO
+
+tony.dat:
+This file contains the font table used by the different versions of the game.
+
toon.dat:
'toon.dat' contains all the strings hardcoded in the original executables.
diff --git a/dists/engine-data/tony.dat b/dists/engine-data/tony.dat
index 70a9ac8776..5ea53c6752 100644
--- a/dists/engine-data/tony.dat
+++ b/dists/engine-data/tony.dat
Binary files differ
diff --git a/dists/scummvm.rc b/dists/scummvm.rc
index 4a67100f9f..8527c668c8 100644
--- a/dists/scummvm.rc
+++ b/dists/scummvm.rc
@@ -44,6 +44,9 @@ teenagent.dat FILE "dists/engine-data/teenagent.dat"
#if ENABLE_TOON == STATIC_PLUGIN
toon.dat FILE "dists/engine-data/toon.dat"
#endif
+#if ENABLE_TONY == STATIC_PLUGIN
+tony.dat FILE "dists/engine-data/tony.dat"
+#endif
#if ENABLE_AGI == STATIC_PLUGIN
pred.dic FILE "dists/pred.dic"
#endif
diff --git a/dists/win32/ScummVM.iss b/dists/win32/ScummVM.iss
index c07b0ae64f..adea759110 100644
--- a/dists/win32/ScummVM.iss
+++ b/dists/win32/ScummVM.iss
@@ -108,18 +108,6 @@ Source: doc/se/LasMig.txt; DestDir: {app}; Flags: ignoreversion isreadme; Langua
Source: README-SDL.txt; DestDir: {app}; Flags: ignoreversion
Source: scummvm.exe; DestDir: {app}; Flags: ignoreversion
Source: SDL.dll; DestDir: {app}
-Source: scummclassic.zip; DestDir: {app}; Flags: ignoreversion
-Source: scummmodern.zip; DestDir: {app}; Flags: ignoreversion
-Source: drascula.dat; DestDir: {app}; Flags: ignoreversion
-Source: hugo.dat; DestDir: {app}; Flags: ignoreversion
-Source: kyra.dat; DestDir: {app}; Flags: ignoreversion
-Source: lure.dat; DestDir: {app}; Flags: ignoreversion
-Source: pred.dic; DestDir: {app}; Flags: ignoreversion
-Source: queen.tbl; DestDir: {app}; Flags: ignoreversion
-Source: sky.cpt; DestDir: {app}; Flags: ignoreversion
-Source: teenagent.dat; DestDir: {app}; Flags: ignoreversion
-Source: toon.dat; DestDir: {app}; Flags: ignoreversion
-Source: translations.dat; DestDir: {app}; Flags: ignoreversion
;Mirgration script for saved games in Windows NT4 onwards
Source: migration.bat; DestDir: {app}; Flags: ignoreversion; MinVersion: 0, 1
Source: migration.txt; DestDir: {app}; Flags: ignoreversion; MinVersion: 0, 1
diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h
index 8c19d03691..3eec33abe5 100644
--- a/engines/advancedDetector.h
+++ b/engines/advancedDetector.h
@@ -194,7 +194,7 @@ protected:
/**
* A map containing all the extra game GUI options the engine supports.
- */
+ */
const ADExtraGuiOptionsMap * const _extraGuiOptions;
/**
@@ -212,7 +212,7 @@ protected:
*
* Used to override gameid.
* This is a recommended setting to prevent global gameid pollution.
- * With this option set, the gameid effectively turns into engineid.
+ * With this option set, the gameid effectively turns into engineid.
*
* FIXME: This field actually removes a feature (gameid) in order to
* address a more generic problem. We should find a better way to
diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp
index 45c00a76ac..98ffca22ed 100644
--- a/engines/agi/agi.cpp
+++ b/engines/agi/agi.cpp
@@ -219,7 +219,7 @@ void AgiEngine::processEvents() {
case Common::KEYCODE_F6:
key = 0x4000;
break;
- case Common::KEYCODE_F7:
+ case Common::KEYCODE_F7:
key = 0x4100;
break;
case Common::KEYCODE_F8:
diff --git a/engines/agi/detection_tables.h b/engines/agi/detection_tables.h
index ab0e9a1fe4..9d67b15adb 100644
--- a/engines/agi/detection_tables.h
+++ b/engines/agi/detection_tables.h
@@ -706,10 +706,10 @@ static const AGIGameDescription gameDescriptions[] = {
FANMADE("Go West, Young Hippie", "ff31484ea465441cb5f3a0f8e956b716"),
FANMADE("Good Man (demo v3.41)", "3facd8a8f856b7b6e0f6c3200274d88c"),
- GAME_LVFPNF("agi-fanmade", "Groza (russian) [AGDS sample]", "logdir", "421da3a18004122a966d64ab6bd86d2e", -1,
+ GAME_LVFPNF("agi-fanmade", "Groza (russian) [AGDS sample]", "logdir", "421da3a18004122a966d64ab6bd86d2e", -1,
Common::RU_RUS, 0x2440, GF_AGDS, GID_FANMADE, Common::kPlatformPC,GType_V2),
- GAME_LVFPNF("agi-fanmade", "Get Outta Space Quest", "logdir", "aaea5b4a348acb669d13b0e6f22d4dc9", -1,
+ GAME_LVFPNF("agi-fanmade", "Get Outta Space Quest", "logdir", "aaea5b4a348acb669d13b0e6f22d4dc9", -1,
Common::EN_ANY, 0x2440, GF_FANMADE, GID_GETOUTTASQ, Common::kPlatformPC,GType_V2),
FANMADE_F("Half-Death - Terror At White-Mesa", "b62c05d0ace878261392073f57ae788c", GF_AGIMOUSE),
diff --git a/engines/agi/loader_v1.cpp b/engines/agi/loader_v1.cpp
index c6a3e66705..189c98ee98 100644
--- a/engines/agi/loader_v1.cpp
+++ b/engines/agi/loader_v1.cpp
@@ -64,7 +64,7 @@ int AgiLoader_v1::detectGame() {
int AgiLoader_v1::loadDir_DDP(AgiDir *agid, int offset, int max) {
Common::File fp;
-
+
if (!fp.open(_filenameDisk0))
return errBadFileOpen;
@@ -73,13 +73,13 @@ int AgiLoader_v1::loadDir_DDP(AgiDir *agid, int offset, int max) {
agid[i].volume = 0xFF;
agid[i].offset = _EMPTY;
}
-
+
fp.seek(offset, SEEK_SET);
for (int i = 0; i <= max; i++) {
int b0 = fp.readByte();
int b1 = fp.readByte();
int b2 = fp.readByte();
-
+
if (b0 == 0xFF && b1 == 0xFF && b2 == 0xFF) {
agid[i].volume = 0xFF;
agid[i].offset = _EMPTY;
@@ -98,7 +98,7 @@ int AgiLoader_v1::loadDir_DDP(AgiDir *agid, int offset, int max) {
int AgiLoader_v1::loadDir_BC(AgiDir *agid, int offset, int max) {
Common::File fp;
-
+
if (!fp.open(_filenameDisk0))
return errBadFileOpen;
@@ -107,13 +107,13 @@ int AgiLoader_v1::loadDir_BC(AgiDir *agid, int offset, int max) {
agid[i].volume = 0xFF;
agid[i].offset = _EMPTY;
}
-
+
fp.seek(offset, SEEK_SET);
for (int i = 0; i <= max; i++) {
int b0 = fp.readByte();
int b1 = fp.readByte();
int b2 = fp.readByte();
-
+
if (b0 == 0xFF && b1 == 0xFF && b2 == 0xFF) {
agid[i].volume = 0xFF;
agid[i].offset = _EMPTY;
@@ -171,7 +171,7 @@ uint8 *AgiLoader_v1::loadVolRes(struct AgiDir *agid) {
if (offset == _EMPTY)
return NULL;
-
+
if (offset > IMAGE_SIZE) {
fp.open(_filenameDisk1);
offset -= IMAGE_SIZE;
@@ -191,7 +191,7 @@ uint8 *AgiLoader_v1::loadVolRes(struct AgiDir *agid) {
agid->len = fp.readUint16LE();
data = (uint8 *)calloc(1, agid->len + 32);
fp.read(data, agid->len);
-
+
fp.close();
return data;
diff --git a/engines/agi/menu.cpp b/engines/agi/menu.cpp
index cac1701596..d23a5a2e27 100644
--- a/engines/agi/menu.cpp
+++ b/engines/agi/menu.cpp
@@ -289,7 +289,7 @@ bool Menu::keyhandler(int key) {
_vm->_game.clockEnabled = false;
drawMenuBar();
}
-
+
// Mouse handling
if (_vm->_mouse.button) {
int hmenu, vmenu;
diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp
index 7e04328a67..5334407eb8 100644
--- a/engines/agi/op_cmd.cpp
+++ b/engines/agi/op_cmd.cpp
@@ -1146,7 +1146,7 @@ void cmdFollowEgo(AgiGame *state, uint8 *p) {
vt.parm1 = p1 > vt.stepSize ? p1 : vt.stepSize;
vt.parm2 = p2;
vt.parm3 = 0xff;
-
+
if (getVersion() < 0x2000) {
_v[p2] = 0;
vt.flags |= fUpdate | fAnimated;
@@ -1270,7 +1270,7 @@ void cmdVersion(AgiGame *state, uint8 *p) {
// no Sierra as it wraps textbox
Common::String verMsg = TITLE " v%s";
-
+
int ver = getVersion();
int maj = (ver >> 12) & 0xf;
int min = ver & 0xfff;
@@ -1839,7 +1839,7 @@ int AgiEngine::runLogic(int n) {
// ip = 2;
// warning("running logic %d\n", n);
// }
-
+
if (_game.exitAllLogics)
break;
}
diff --git a/engines/agi/op_test.cpp b/engines/agi/op_test.cpp
index a44c68e0fc..4d5e6fffe1 100644
--- a/engines/agi/op_test.cpp
+++ b/engines/agi/op_test.cpp
@@ -403,7 +403,7 @@ int AgiEngine::testIfCode(int lognum) {
case 0xFF:
endTest = true;
continue;
-
+
default:
// Evaluate the command and skip the rest of the instruction
_agiCondCommands[op](state, p);
diff --git a/engines/agi/opcodes.cpp b/engines/agi/opcodes.cpp
index 29fb860635..7a427bd94f 100644
--- a/engines/agi/opcodes.cpp
+++ b/engines/agi/opcodes.cpp
@@ -130,7 +130,7 @@ AgiInstruction insV1[] = {
{ "...", "", &cmdUnknown }, // 4E # show.obj
{ "load.logics", "n", &cmdLoadLogic }, // 4F # load.global.logics
{ "display", "nnns", &cmdDisplay }, // 50 TODO: 4 vs 3 args
- { "prevent.input???", "", &cmdUnknown }, // 51
+ { "prevent.input???", "", &cmdUnknown }, // 51
{ "...", "", &cmdUnknown }, // 52 # nop
{ "...", "n", &cmdUnknown }, // 53 # text.screen
{ "...", "", &cmdUnknown }, // 54 ???
diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp
index 3e63da756d..d451a799a0 100644
--- a/engines/agi/saveload.cpp
+++ b/engines/agi/saveload.cpp
@@ -821,7 +821,7 @@ int AgiEngine::scummVMSaveLoadDialog(bool isSave) {
if (slot < 0)
return true;
-
+
if (isSave)
return doSave(slot, desc);
else
diff --git a/engines/agi/sound_pcjr.cpp b/engines/agi/sound_pcjr.cpp
index d21baa450f..5bffca5765 100644
--- a/engines/agi/sound_pcjr.cpp
+++ b/engines/agi/sound_pcjr.cpp
@@ -234,7 +234,7 @@ int SoundGenPCJr::getNextNote(int ch)
// if tone isn't touched.. it should be inited so it just plays silence
// return 0 if it's passing more data
// return -1 if it's passing nothing (end of data)
-int SoundGenPCJr::getNextNote_v2(int ch) {
+int SoundGenPCJr::getNextNote_v2(int ch) {
ToneChan *tpcm;
SndGenChan *chan;
const byte *data;
@@ -308,7 +308,7 @@ int SoundGenPCJr::getNextNote_v1(int ch) {
_channel[ch].attenuationCopy = 0x0F;
return -1;
}
-
+
// In the V1 player the default duration for a row is 3 ticks
if (duration > 0) {
duration--;
diff --git a/engines/agi/text.cpp b/engines/agi/text.cpp
index 1886a74ab1..4877be2647 100644
--- a/engines/agi/text.cpp
+++ b/engines/agi/text.cpp
@@ -64,7 +64,7 @@ void AgiEngine::printText2(int l, const char *msg, int foff, int xoff, int yoff,
// Note: there were extra checks for *m being a cursor character
// here (1, 2 or 3), which have been removed, as the cursor
- // character is no longer printed via this function.
+ // character is no longer printed via this function.
if (*m >= 0x20) {
int ypos = (y1 * CHAR_LINES) + yoff;
@@ -73,7 +73,7 @@ void AgiEngine::printText2(int l, const char *msg, int foff, int xoff, int yoff,
if (xpos >= GFX_WIDTH)
continue;
-
+
_gfx->putTextCharacter(l, xpos, ypos, *m, fg, bg, checkerboard);
if (x1 > maxx)
diff --git a/engines/agi/words.cpp b/engines/agi/words.cpp
index 4400112247..9c5b3d349a 100644
--- a/engines/agi/words.cpp
+++ b/engines/agi/words.cpp
@@ -41,7 +41,7 @@ int AgiEngine::loadWords_v1(Common::File &f) {
int k;
debug(0, "Loading dictionary");
-
+
// Loop through alphabet, as words in the dictionary file are sorted by
// first character
f.seek(f.pos() + 26 * 2, SEEK_SET);
@@ -131,7 +131,7 @@ int AgiEngine::findWord(const char *word, int *flen) {
*flen = 0;
Common::Array<AgiWord *> &a = _game.words[c];
-
+
for (int i = 0; i < (int)a.size(); i++) {
int wlen = strlen(a[i]->word);
// Keep looking till we find the word itself, or the whole phrase.
diff --git a/engines/agos/midiparser_s1d.cpp b/engines/agos/midiparser_s1d.cpp
index 9ca87436fc..bef7199a98 100644
--- a/engines/agos/midiparser_s1d.cpp
+++ b/engines/agos/midiparser_s1d.cpp
@@ -35,7 +35,7 @@ namespace AGOS {
class MidiParser_S1D : public MidiParser {
private:
byte *_data;
- bool _no_delta;
+ bool _noDelta;
struct Loop {
uint16 timer;
@@ -49,7 +49,7 @@ protected:
void resetTracking();
public:
- MidiParser_S1D() : _data(0), _no_delta(false) {}
+ MidiParser_S1D() : _data(0), _noDelta(false) {}
bool loadMusic(byte *data, uint32 size);
};
@@ -75,14 +75,14 @@ void MidiParser_S1D::chainEvent(EventInfo &info) {
}
void MidiParser_S1D::parseNextEvent(EventInfo &info) {
- info.start = _position._play_pos;
+ info.start = _position._playPos;
info.length = 0;
- info.delta = _no_delta ? 0 : readVLQ2(_position._play_pos);
- _no_delta = false;
+ info.delta = _noDelta ? 0 : readVLQ2(_position._playPos);
+ _noDelta = false;
- info.event = *_position._play_pos++;
+ info.event = *_position._playPos++;
if (!(info.event & 0x80)) {
- _no_delta = true;
+ _noDelta = true;
info.event |= 0x80;
}
@@ -94,34 +94,43 @@ void MidiParser_S1D::parseNextEvent(EventInfo &info) {
} else {
switch (info.command()) {
case 0x8: // note off
- info.basic.param1 = *_position._play_pos++;
+ info.basic.param1 = *_position._playPos++;
info.basic.param2 = 0;
break;
case 0x9: // note on
- info.basic.param1 = *_position._play_pos++;
- info.basic.param2 = *_position._play_pos++;
+ info.basic.param1 = *_position._playPos++;
+ info.basic.param2 = *_position._playPos++;
+ // Rewrite note on events with velocity 0 as note off events.
+ // This is the actual meaning of this, but theoretically this
+ // should not need to be rewritten, since all MIDI devices should
+ // interpret it like that. On the other hand all our MidiParser
+ // implementations do it and there seems to be code in MidiParser
+ // which relies on this for tracking active notes.
+ if (info.basic.param2 == 0) {
+ info.event = info.channel() | 0x80;
+ }
break;
case 0xA: { // loop control
// In case the stop mode(?) is set to 0x80 this will stop the
// track over here.
- const int16 loopIterations = int8(*_position._play_pos++);
+ const int16 loopIterations = int8(*_position._playPos++);
if (!loopIterations) {
- _loops[info.channel()].start = _position._play_pos;
+ _loops[info.channel()].start = _position._playPos;
} else {
if (!_loops[info.channel()].timer) {
if (_loops[info.channel()].start) {
_loops[info.channel()].timer = uint16(loopIterations);
- _loops[info.channel()].end = _position._play_pos;
+ _loops[info.channel()].end = _position._playPos;
// Go to the start of the loop
- _position._play_pos = _loops[info.channel()].start;
+ _position._playPos = _loops[info.channel()].start;
}
} else {
if (_loops[info.channel()].timer)
- _position._play_pos = _loops[info.channel()].start;
+ _position._playPos = _loops[info.channel()].start;
--_loops[info.channel()].timer;
}
}
@@ -141,13 +150,13 @@ void MidiParser_S1D::parseNextEvent(EventInfo &info) {
break;
case 0xC: // program change
- info.basic.param1 = *_position._play_pos++;
+ info.basic.param1 = *_position._playPos++;
info.basic.param2 = 0;
break;
case 0xD: // jump to loop end
if (_loops[info.channel()].end)
- _position._play_pos = _loops[info.channel()].end;
+ _position._playPos = _loops[info.channel()].end;
// We need to read the next midi event here. Since we can not
// safely pass this event to the MIDI event processing.
@@ -178,7 +187,7 @@ bool MidiParser_S1D::loadMusic(byte *data, uint32 size) {
pos += 1;
// And now we're at the actual data. Only one track.
- _num_tracks = 1;
+ _numTracks = 1;
_data = pos;
_tracks[0] = pos;
@@ -194,7 +203,7 @@ bool MidiParser_S1D::loadMusic(byte *data, uint32 size) {
void MidiParser_S1D::resetTracking() {
MidiParser::resetTracking();
// The first event never contains any delta.
- _no_delta = true;
+ _noDelta = true;
memset(_loops, 0, sizeof(_loops));
}
diff --git a/engines/agos/saveload.cpp b/engines/agos/saveload.cpp
index c6bca1a6e6..e13fa214d1 100644
--- a/engines/agos/saveload.cpp
+++ b/engines/agos/saveload.cpp
@@ -142,7 +142,7 @@ void AGOSEngine_Feeble::quickLoadOrSave() {
}
#endif
-// The function uses segments of code from the original game scripts
+// The function uses segments of code from the original game scripts
// to allow quick loading and saving, but isn't perfect.
//
// Unfortuntely this allows loading and saving in locations,
@@ -1424,7 +1424,7 @@ bool AGOSEngine_Elvira2::loadGame(const char *filename, bool restartMode) {
// The floppy disk versions of Simon the Sorcerer 2 block changing
// to scrolling rooms, if the copy protection fails. But the copy
// protection flags are never set in the CD version.
- // Setting this copy protection flag, allows saved games to be shared
+ // Setting this copy protection flag, allows saved games to be shared
// between all versions of Simon the Sorcerer 2.
if (getGameType() == GType_SIMON2) {
setBitFlag(135, 1);
diff --git a/engines/agos/sound.cpp b/engines/agos/sound.cpp
index 85c449eafc..bec41bbbd3 100644
--- a/engines/agos/sound.cpp
+++ b/engines/agos/sound.cpp
@@ -297,7 +297,7 @@ Audio::AudioStream *RawSound::makeAudioStream(uint sound) {
warning("RawSound::makeAudioStream: Could not open file \"%s\"", _filename.c_str());
return NULL;
}
-
+
file->seek(_offsets[sound], SEEK_SET);
uint size = file->readUint32BE();
return Audio::makeRawStream(new Common::SeekableSubReadStream(file, _offsets[sound] + 4, _offsets[sound] + 4 + size, DisposeAfterUse::YES), 22050, _flags, DisposeAfterUse::YES);
diff --git a/engines/cge/bitmap.cpp b/engines/cge/bitmap.cpp
index 4f85957b3d..7089c8e0d1 100644
--- a/engines/cge/bitmap.cpp
+++ b/engines/cge/bitmap.cpp
@@ -94,7 +94,7 @@ Bitmap::Bitmap(CGEEngine *vm, uint16 w, uint16 h, uint8 fill)
// Replicate across the entire table
for (HideDesc *hdP = b + 1; hdP < (b + _h); hdP++)
*hdP = *b;
-
+
b->_skip = 0; // fix the first entry
_v = v;
_b = b;
@@ -357,7 +357,7 @@ bool Bitmap::loadVBM(EncryptedStream *f) {
// Read in the palette
byte palData[kPalSize];
f->read(palData, kPalSize);
-
+
const byte *srcP = palData;
for (int idx = 0; idx < kPalCount; idx++, srcP += 3) {
_vm->_bitmapPalette[idx]._r = *srcP;
diff --git a/engines/cge/cge_main.cpp b/engines/cge/cge_main.cpp
index ecbfba2502..f4f1cd3e0b 100644
--- a/engines/cge/cge_main.cpp
+++ b/engines/cge/cge_main.cpp
@@ -280,7 +280,7 @@ Common::Error CGEEngine::loadGameState(int slot) {
sceneDown();
_hero->park();
resetGame();
-
+
// If music is playing, kill it.
if (_music)
_midiPlayer->killMidi();
@@ -508,7 +508,7 @@ void CGEEngine::loadMapping() {
if (!cf.err()) {
// Move to the data for the given room
cf.seek((_now - 1) * kMapArrSize);
-
+
// Read in the data
for (int z = 0; z < kMapZCnt; ++z) {
cf.read(&_clusterMap[z][0], kMapXCnt);
@@ -772,7 +772,7 @@ void System::touch(uint16 mask, int x, int y, Common::KeyCode keyCode) {
if (mask & kEventKeyb) {
if (keyCode == Common::KEYCODE_ESCAPE) {
- // The original was calling keyClick()
+ // The original was calling keyClick()
// The sound is uselessly annoying and noisy, so it has been removed
_vm->killText();
if (_vm->_startupMode == 1) {
@@ -1044,7 +1044,7 @@ void CGEEngine::loadSprite(const char *fname, int ref, int scene, int col = 0, i
uint16 len;
for (line = sprf.readLine(); !sprf.eos(); line = sprf.readLine()) {
- len = line.size();
+ len = line.size();
lcnt++;
strcpy(tmpStr, line.c_str());
if (len == 0 || *tmpStr == '.')
diff --git a/engines/cge/detection.cpp b/engines/cge/detection.cpp
index 2e04b82026..3d6c24d68b 100644
--- a/engines/cge/detection.cpp
+++ b/engines/cge/detection.cpp
@@ -198,7 +198,7 @@ SaveStateList CGEMetaEngine::listSaves(const char *target) const {
SaveStateDescriptor CGEMetaEngine::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) {
CGE::SavegameHeader header;
@@ -229,7 +229,7 @@ SaveStateDescriptor CGEMetaEngine::querySaveMetaInfos(const char *target, int sl
return desc;
}
}
-
+
return SaveStateDescriptor();
}
diff --git a/engines/cge/events.h b/engines/cge/events.h
index 522aa67905..ab8d87212d 100644
--- a/engines/cge/events.h
+++ b/engines/cge/events.h
@@ -105,7 +105,7 @@ private:
void handleEvents();
public:
EventManager(CGEEngine *vm);
- void poll();
+ void poll();
void clearEvent(Sprite *spr);
CGEEvent &getNextEvent();
diff --git a/engines/cge/fileio.cpp b/engines/cge/fileio.cpp
index f23105d823..609d5e86aa 100644
--- a/engines/cge/fileio.cpp
+++ b/engines/cge/fileio.cpp
@@ -98,7 +98,7 @@ uint16 ResourceManager::XCrypt(void *buf, uint16 length) {
for (uint16 i = 0; i < length; i++)
*b++ ^= kCryptSeed;
-
+
return kCryptSeed;
}
diff --git a/engines/cge/text.cpp b/engines/cge/text.cpp
index fd4120d49d..a8ce8777c5 100644
--- a/engines/cge/text.cpp
+++ b/engines/cge/text.cpp
@@ -63,7 +63,7 @@ int16 Text::count() {
Common::String line;
char tmpStr[kLineMax + 1];
-
+
int counter = 0;
for (line = tf.readLine(); !tf.eos(); line = tf.readLine()) {
diff --git a/engines/cine/anim.cpp b/engines/cine/anim.cpp
index 60168831a1..075a59cfb6 100644
--- a/engines/cine/anim.cpp
+++ b/engines/cine/anim.cpp
@@ -202,13 +202,13 @@ AnimData::AnimData(const AnimData &src) : _width(src._width),
if (src._data) {
_data = new byte[_size];
assert(_data);
- memcpy(_data, src._data, _size*sizeof(byte));
+ memcpy(_data, src._data, _size * sizeof(byte));
}
if (src._mask) {
_mask = new byte[_size];
assert(_mask);
- memcpy(_mask, src._mask, _size*sizeof(byte));
+ memcpy(_mask, src._mask, _size * sizeof(byte));
}
memset(_name, 0, sizeof(_name));
@@ -272,8 +272,7 @@ byte AnimData::getColor(int x, int y) {
* @param transparent Transparent color (for ANIM_MASKSPRITE)
*/
void AnimData::load(byte *d, int type, uint16 w, uint16 h, int16 file,
- int16 frame, const char *n, byte transparent) {
-
+ int16 frame, const char *n, byte transparent) {
assert(d);
if (_data) {
@@ -299,7 +298,7 @@ void AnimData::load(byte *d, int type, uint16 w, uint16 h, int16 file,
_size = w * h;
_data = new byte[_size];
assert(_data);
- memcpy(_data, d, _size*sizeof(byte));
+ memcpy(_data, d, _size * sizeof(byte));
break;
case ANIM_MASK:
@@ -536,7 +535,7 @@ int loadSpl(const char *resourceName, int16 idx) {
entry = idx < 0 ? emptyAnimSpace() : idx;
assert(entry >= 0);
- g_cine->_animDataTable[entry].load(dataPtr, ANIM_RAW, g_cine->_partBuffer[foundFileIdx].unpackedSize, 1, foundFileIdx, 0, currentPartName);
+ g_cine->_animDataTable[entry].load(dataPtr + 0x16, ANIM_RAW, g_cine->_partBuffer[foundFileIdx].unpackedSize - 0x16, 1, foundFileIdx, 0, currentPartName);
free(dataPtr);
return entry + 1;
@@ -546,9 +545,10 @@ int loadSpl(const char *resourceName, int16 idx) {
* Load 1bpp mask
* @param resourceName Mask filename
* @param idx Target index in animDataTable (-1 if any empty space will do)
+ * @param frameIndex frame of animation to load (-1 for all frames)
* @return The number of the animDataTable entry after the loaded mask (-1 if error)
*/
-int loadMsk(const char *resourceName, int16 idx) {
+int loadMsk(const char *resourceName, int16 idx, int16 frameIndex) {
int16 foundFileIdx = findFileInBundle(resourceName);
if (foundFileIdx < 0) {
return -1;
@@ -563,9 +563,18 @@ int loadMsk(const char *resourceName, int16 idx) {
loadAnimHeader(animHeader, readS);
ptr = dataPtr + 0x16;
+ int16 startFrame = 0;
+ int16 endFrame = animHeader.numFrames;
+
+ if (frameIndex >= 0) {
+ startFrame = frameIndex;
+ endFrame = frameIndex + 1;
+ ptr += frameIndex * animHeader.frameWidth * animHeader.frameHeight;
+ }
+
entry = idx < 0 ? emptyAnimSpace() : idx;
assert(entry >= 0);
- for (int16 i = 0; i < animHeader.numFrames; i++, entry++) {
+ for (int16 i = startFrame; i < endFrame; i++, entry++) {
g_cine->_animDataTable[entry].load(ptr, ANIM_MASK, animHeader.frameWidth, animHeader.frameHeight, foundFileIdx, i, currentPartName);
ptr += animHeader.frameWidth * animHeader.frameHeight;
}
@@ -578,9 +587,10 @@ int loadMsk(const char *resourceName, int16 idx) {
* Load animation
* @param resourceName Animation filename
* @param idx Target index in animDataTable (-1 if any empty space will do)
+ * @param frameIndex frame of animation to load (-1 for all frames)
* @return The number of the animDataTable entry after the loaded animation (-1 if error)
*/
-int loadAni(const char *resourceName, int16 idx) {
+int loadAni(const char *resourceName, int16 idx, int16 frameIndex) {
int16 foundFileIdx = findFileInBundle(resourceName);
if (foundFileIdx < 0) {
return -1;
@@ -596,6 +606,15 @@ int loadAni(const char *resourceName, int16 idx) {
loadAnimHeader(animHeader, readS);
ptr = dataPtr + 0x16;
+ int16 startFrame = 0;
+ int16 endFrame = animHeader.numFrames;
+
+ if (frameIndex >= 0) {
+ startFrame = frameIndex;
+ endFrame = frameIndex + 1;
+ ptr += frameIndex * animHeader.frameWidth * animHeader.frameHeight;
+ }
+
transparentColor = getAnimTransparentColor(resourceName);
// TODO: Merge this special case hack into getAnimTransparentColor somehow.
@@ -609,7 +628,7 @@ int loadAni(const char *resourceName, int16 idx) {
entry = idx < 0 ? emptyAnimSpace() : idx;
assert(entry >= 0);
- for (int16 i = 0; i < animHeader.numFrames; i++, entry++) {
+ for (int16 i = startFrame; i < endFrame; i++, entry++) {
// special case transparency handling
if (!strcmp(resourceName, "L2202.ANI")) {
transparentColor = i < 2 ? 0 : 7;
@@ -669,13 +688,13 @@ void convert8BBP2(byte *dest, byte *source, int16 width, int16 height) {
*(source + k) <<= 1;
if (k > 0 + m)
color <<= 1;
- } // end k
+ } // end k
*(dest++) = color;
- } // end i
- } // end m
+ } // end i
+ } // end m
source += 0x10;
- } // end j
+ } // end j
}
/**
@@ -685,7 +704,7 @@ void convert8BBP2(byte *dest, byte *source, int16 width, int16 height) {
* @param frameIndex frame of animation to load (-1 for all frames)
* @return The number of the animDataTable entry after the loaded image set (-1 if error)
*/
-int loadSet(const char *resourceName, int16 idx, int16 frameIndex =-1 ) {
+int loadSet(const char *resourceName, int16 idx, int16 frameIndex = -1) {
AnimHeader2Struct header2;
uint16 numSpriteInAnim;
int16 foundFileIdx = findFileInBundle(resourceName);
@@ -712,10 +731,9 @@ int loadSet(const char *resourceName, int16 idx, int16 frameIndex =-1 ) {
int16 startFrame = 0;
int16 endFrame = numSpriteInAnim;
- if(frameIndex>=0)
- {
+ if (frameIndex >= 0) {
startFrame = frameIndex;
- endFrame = frameIndex+1;
+ endFrame = frameIndex + 1;
ptr += 0x10 * frameIndex;
}
@@ -766,7 +784,7 @@ int loadSeq(const char *resourceName, int16 idx) {
byte *dataPtr = readBundleFile(foundFileIdx);
int entry = idx < 0 ? emptyAnimSpace() : idx;
- g_cine->_animDataTable[entry].load(dataPtr+0x16, ANIM_RAW, g_cine->_partBuffer[foundFileIdx].unpackedSize-0x16, 1, foundFileIdx, 0, currentPartName);
+ g_cine->_animDataTable[entry].load(dataPtr + 0x16, ANIM_RAW, g_cine->_partBuffer[foundFileIdx].unpackedSize - 0x16, 1, foundFileIdx, 0, currentPartName);
free(dataPtr);
return entry + 1;
}
@@ -783,11 +801,11 @@ int loadResource(const char *resourceName, int16 idx, int16 frameIndex) {
if (strstr(resourceName, ".SPL")) {
result = loadSpl(resourceName, idx);
} else if (strstr(resourceName, ".MSK")) {
- result = loadMsk(resourceName, idx);
+ result = loadMsk(resourceName, idx, frameIndex);
} else if (strstr(resourceName, ".ANI")) {
- result = loadAni(resourceName, idx);
+ result = loadAni(resourceName, idx, frameIndex);
} else if (strstr(resourceName, ".ANM")) {
- result = loadAni(resourceName, idx);
+ result = loadAni(resourceName, idx, frameIndex);
} else if (strstr(resourceName, ".SET")) {
result = loadSet(resourceName, idx, frameIndex);
} else if (strstr(resourceName, ".SEQ")) {
diff --git a/engines/cine/cine.cpp b/engines/cine/cine.cpp
index bbe2cd4896..aa7221f733 100644
--- a/engines/cine/cine.cpp
+++ b/engines/cine/cine.cpp
@@ -189,7 +189,18 @@ void CineEngine::initialize() {
g_cine->_messageTable.clear();
resetObjectTable();
- disableSystemMenu = 1;
+ if (getGameType() == Cine::GType_OS) {
+ disableSystemMenu = 1;
+ } else {
+ // WORKAROUND: We do not save this variable in FW's savegames.
+ // Initializing this to 1, like we do it in the OS case, will
+ // cause the menu disabled when loading from the launcher or
+ // command line.
+ // A proper fix here would be to save this variable in FW's saves.
+ // Since it seems these are unversioned so far, there would be need
+ // to properly add versioning to them first.
+ disableSystemMenu = 0;
+ }
var8 = 0;
diff --git a/engines/cine/cine.h b/engines/cine/cine.h
index 55376dce29..47edf51c30 100644
--- a/engines/cine/cine.h
+++ b/engines/cine/cine.h
@@ -159,7 +159,7 @@ private:
bool _preLoad;
int _timerDelayMultiplier;
- public:
+public:
// TODO: These are pseudo-global vars
// They better belong to appropriate classes
Common::Array<AnimData> _animDataTable;
diff --git a/engines/cine/console.cpp b/engines/cine/console.cpp
index 0a24b2408a..4af28592e7 100644
--- a/engines/cine/console.cpp
+++ b/engines/cine/console.cpp
@@ -28,7 +28,7 @@ namespace Cine {
bool labyrinthCheat;
CineConsole::CineConsole(CineEngine *vm) : GUI::Debugger(), _vm(vm) {
- DCmd_Register("labyrinthCheat", WRAP_METHOD(CineConsole, Cmd_LabyrinthCheat));
+ DCmd_Register("labyrinthCheat", WRAP_METHOD(CineConsole, Cmd_LabyrinthCheat));
labyrinthCheat = false;
}
diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp
index 7a988227f6..636c0cf8d9 100644
--- a/engines/cine/gfx.cpp
+++ b/engines/cine/gfx.cpp
@@ -113,7 +113,7 @@ FWRenderer::FWRenderer() : _background(NULL), _backupPal(), _cmd(""),
assert(_backBuffer);
memset(_backBuffer, 0, _screenSize);
- memset(_bgName, 0, sizeof (_bgName));
+ memset(_bgName, 0, sizeof(_bgName));
}
@@ -249,7 +249,7 @@ void FWRenderer::drawCommand() {
unsigned int i;
int x = 10, y = _cmdY;
- if(disableSystemMenu == 0) {
+ if (disableSystemMenu == 0) {
drawPlainBox(x, y, 301, 11, 0);
drawBorder(x - 1, y - 1, 302, 12, 2);
@@ -307,7 +307,7 @@ void FWRenderer::drawMessage(const char *str, int x, int y, int width, int color
i++;
line = fitLine(str + i, tw, words, cw);
- if ( str[i + line] != '\0' && str[i + line] != 0x7C && words) {
+ if (str[i + line] != '\0' && str[i + line] != 0x7C && words) {
space = (tw - cw) / words;
extraSpace = (tw - cw) % words;
} else {
@@ -471,6 +471,41 @@ int FWRenderer::drawChar(char character, int x, int y) {
return x;
}
+/**
+ * Clears the character glyph to black
+ * This function is called "undrawChar", because the original only applies
+ * this drawing after the original glyph has been drawn.
+ * Possible TODO: Find a better name.
+ * @param character Character to undraw
+ * @param x Character coordinate
+ * @param y Character coordinate
+ */
+int FWRenderer::undrawChar(char character, int x, int y) {
+ int width, idx;
+
+ if (character == ' ') {
+ x += 5;
+ } else if ((width = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterWidth)) {
+ idx = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterIdx;
+ const byte *sprite = g_cine->_textHandler.textTable[idx][FONT_DATA];
+ for (uint i = 0; i < FONT_HEIGHT; ++i) {
+ byte *dst = _backBuffer + (y + i) * 320 + x;
+ for (uint j = 0; j < FONT_WIDTH; ++j, ++dst) {
+ // The original does this based on whether bit 1 of the pixel
+ // is set. Since that's the only bit ever set in (FW) this
+ // check should be fine.
+ // TODO: Check how Operation Stealth Amiga works
+ if (*sprite++) {
+ *dst = 0;
+ }
+ }
+ }
+ x += width + 1;
+ }
+
+ return x;
+}
+
int FWRenderer::getStringWidth(const char *str) {
const char *p = str;
int width = 0;
@@ -969,20 +1004,29 @@ void SelectionMenu::drawMenu(FWRenderer &r, bool top) {
charX = x + 4;
if (i == _selection) {
+ int color;
+
if (isAmiga) {
- // The original Amiga version is using a different highlight color here,
- // but with our current code it is not possible to change the text color,
- // thus we can not use the Amiga's color, since otherwise the text
- // wouldn't be visible anymore.
- r.drawPlainBox(charX, lineY, _width - 8, FONT_HEIGHT, top ? r._messageBg/*2*/ : 18);
+ if (top) {
+ color = 2;
+ } else {
+ color = 18;
+ }
} else {
- r.drawPlainBox(charX, lineY, _width - 8, 9, 0);
+ color = 0;
}
+
+ r.drawPlainBox(x + 2, lineY - 1, _width - 3, 9, color);
}
const int size = _elements[i].size();
- for (int j = 0; j < size; ++j)
- charX = r.drawChar(_elements[i][j], charX, lineY);
+ for (int j = 0; j < size; ++j) {
+ if (isAmiga && i == _selection) {
+ charX = r.undrawChar(_elements[i][j], charX, lineY);
+ } else {
+ charX = r.drawChar(_elements[i][j], charX, lineY);
+ }
+ }
}
}
@@ -1244,6 +1288,7 @@ void OSRenderer::renderOverlay(const Common::List<overlay>::iterator &it) {
sprite = &g_cine->_animDataTable[g_cine->_objectTable[it->objIdx].frame];
drawSprite(&(*it), sprite->data(), sprite->_realWidth, sprite->_height, _backBuffer, g_cine->_objectTable[it->objIdx].x, g_cine->_objectTable[it->objIdx].y, g_cine->_objectTable[it->objIdx].part, sprite->_bpp);
break;
+
// game message
case 2:
if (it->objIdx >= g_cine->_messageTable.size()) {
@@ -1300,7 +1345,7 @@ void OSRenderer::renderOverlay(const Common::List<overlay>::iterator &it) {
height = obj->costume;
drawPlainBox(obj->x, obj->y, width, height, color);
debug(5, "renderOverlay: type=%d, x=%d, y=%d, width=%d, height=%d, color=%d",
- it->type, obj->x, obj->y, width, height, color);
+ it->type, obj->x, obj->y, width, height, color);
break;
// something else
@@ -1424,7 +1469,7 @@ void OSRenderer::selectBg(unsigned int idx) {
if (_bgTable[idx].bg) {
assert(_bgTable[idx].pal.isValid() && !(_bgTable[idx].pal.empty()));
- _currentBg = idx;
+ _currentBg = idx;
} else
warning("OSRenderer::selectBg(%d) - attempt to select null background", idx);
reloadPalette();
@@ -1750,23 +1795,23 @@ void OSRenderer::drawSprite(overlay *overlayPtr, const byte *spritePtr, int16 wi
// draw the mask based on next objects in the list
Common::List<overlay>::iterator it;
- for (it = g_cine->_overlayList.begin(); it != g_cine->_overlayList.end(); ++it) {
- if(&(*it) == overlayPtr) {
+ for (it = g_cine->_overlayList.begin(); it != g_cine->_overlayList.end(); ++it) {
+ if (&(*it) == overlayPtr) {
break;
}
}
- while(it != g_cine->_overlayList.end()) {
+ while (it != g_cine->_overlayList.end()) {
overlay *pCurrentOverlay = &(*it);
if ((pCurrentOverlay->type == 5) || ((pCurrentOverlay->type == 21) && (pCurrentOverlay->x == overlayPtr->objIdx))) {
AnimData *sprite = &g_cine->_animDataTable[g_cine->_objectTable[it->objIdx].frame];
if (pMask == NULL) {
- pMask = new byte[width*height];
+ pMask = new byte[width * height];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
- byte spriteColor= spritePtr[width * i + j];
+ byte spriteColor = spritePtr[width * i + j];
pMask[width * i + j] = spriteColor;
}
}
@@ -1777,7 +1822,7 @@ void OSRenderer::drawSprite(overlay *overlayPtr, const byte *spritePtr, int16 wi
int inMaskX = (g_cine->_objectTable[it->objIdx].x + i) - x;
int inMaskY = (g_cine->_objectTable[it->objIdx].y + j) - y;
- if (inMaskX >=0 && inMaskX < width) {
+ if (inMaskX >= 0 && inMaskX < width) {
if (inMaskY >= 0 && inMaskY < height) {
if (sprite->_bpp == 1) {
if (!sprite->getColor(i, j)) {
@@ -1793,7 +1838,7 @@ void OSRenderer::drawSprite(overlay *overlayPtr, const byte *spritePtr, int16 wi
}
// now, draw with the mask we created
- if(pMask) {
+ if (pMask) {
spritePtr = pMask;
}
@@ -1808,7 +1853,7 @@ void OSRenderer::drawSprite(overlay *overlayPtr, const byte *spritePtr, int16 wi
destPtr += i * 320;
for (int j = 0; j < width; j++) {
- byte color= *(spritePtr++);
+ byte color = *(spritePtr++);
if ((transparentColor != color) && x + j >= 0 && x + j < 320 && i + y >= 0 && i + y < 200) {
*(destPtr++) = color;
} else {
diff --git a/engines/cine/gfx.h b/engines/cine/gfx.h
index 3434cf9fc2..8b8843fd72 100644
--- a/engines/cine/gfx.h
+++ b/engines/cine/gfx.h
@@ -152,6 +152,7 @@ protected:
void drawBorder(int x, int y, int width, int height, byte color);
void drawDoubleBorder(int x, int y, int width, int height, byte color);
virtual int drawChar(char character, int x, int y);
+ virtual int undrawChar(char character, int x, int y);
void drawLine(int x, int y, int width, int height, byte color);
void remaskSprite(byte *mask, Common::List<overlay>::iterator it);
virtual void drawBackground();
@@ -287,7 +288,7 @@ byte gfxGetColor(int16 x, int16 y, const byte *ptr, int16 width);
void gfxResetRawPage(byte *pageRaw);
void gfxConvertSpriteToRaw(byte *dst, const byte *src, uint16 w, uint16 h);
-void gfxCopyRawPage(byte *source, byte * dest);
+void gfxCopyRawPage(byte *source, byte *dest);
void gfxFlipRawPage(byte *frontBuffer);
void drawSpriteRaw(const byte *spritePtr, const byte *maskPtr, int16 width, int16 height, byte *page, int16 x, int16 y);
void gfxDrawPlainBoxRaw(int16 x1, int16 y1, int16 x2, int16 y2, byte color, byte *page);
diff --git a/engines/cine/main_loop.cpp b/engines/cine/main_loop.cpp
index f13f38a45e..c822f1cabd 100644
--- a/engines/cine/main_loop.cpp
+++ b/engines/cine/main_loop.cpp
@@ -180,19 +180,19 @@ static void processEvent(Common::Event &event) {
case Common::KEYCODE_F11:
renderer->showCollisionPage(false);
break;
- case Common::KEYCODE_KP5: // Emulated left mouse button click
- case Common::KEYCODE_LEFT: // Left
- case Common::KEYCODE_KP4: // Left
+ case Common::KEYCODE_KP5: // Emulated left mouse button click
+ case Common::KEYCODE_LEFT: // Left
+ case Common::KEYCODE_KP4: // Left
case Common::KEYCODE_RIGHT: // Right
- case Common::KEYCODE_KP6: // Right
- case Common::KEYCODE_UP: // Up
- case Common::KEYCODE_KP8: // Up
- case Common::KEYCODE_DOWN: // Down
- case Common::KEYCODE_KP2: // Down
- case Common::KEYCODE_KP9: // Up & Right
- case Common::KEYCODE_KP7: // Up & Left
- case Common::KEYCODE_KP1: // Down & Left
- case Common::KEYCODE_KP3: // Down & Right
+ case Common::KEYCODE_KP6: // Right
+ case Common::KEYCODE_UP: // Up
+ case Common::KEYCODE_KP8: // Up
+ case Common::KEYCODE_DOWN: // Down
+ case Common::KEYCODE_KP2: // Down
+ case Common::KEYCODE_KP9: // Up & Right
+ case Common::KEYCODE_KP7: // Up & Left
+ case Common::KEYCODE_KP1: // Down & Left
+ case Common::KEYCODE_KP3: // Down & Right
// Stop ego movement made with keyboard when releasing a known key
moveUsingKeyboard(0, 0);
break;
@@ -217,7 +217,6 @@ void manageEvents() {
g_system->delayMillis(20);
} while (g_system->getMillis() < nextFrame);
- g_sound->update();
mouseData.left = mouseLeft;
mouseData.right = mouseRight;
}
@@ -434,9 +433,9 @@ void CineEngine::mainLoop(int bootScriptIdx) {
hideMouse();
g_sound->stopMusic();
- // if (g_cine->getGameType() == Cine::GType_OS) {
+ //if (g_cine->getGameType() == Cine::GType_OS) {
// freeUnkList();
- // }
+ //}
closePart();
}
diff --git a/engines/cine/object.cpp b/engines/cine/object.cpp
index afd95c04b0..a75828abb1 100644
--- a/engines/cine/object.cpp
+++ b/engines/cine/object.cpp
@@ -59,7 +59,7 @@ void loadObject(char *pObjectName) {
assert(numEntry <= NUM_MAX_OBJECT);
for (i = 0; i < numEntry; i++) {
- if (g_cine->_objectTable[i].costume != -2 && g_cine->_objectTable[i].costume != -3) { // flag is keep ?
+ if (g_cine->_objectTable[i].costume != -2 && g_cine->_objectTable[i].costume != -3) { // flag is keep?
Common::MemoryReadStream readS(ptr, entrySize);
g_cine->_objectTable[i].x = readS.readSint16BE();
diff --git a/engines/cine/pal.cpp b/engines/cine/pal.cpp
index 779c279ea1..10077ecdc9 100644
--- a/engines/cine/pal.cpp
+++ b/engines/cine/pal.cpp
@@ -92,7 +92,8 @@ void loadRelatedPalette(const char *fileName) {
paletteIndex = findPaletteFromName(localName);
if (paletteIndex == -1) {
- for (i = 0; i < 16; i++) { // generate default palette
+ // generate default palette
+ for (i = 0; i < 16; i++) {
paletteBuffer1[i] = paletteBuffer2[i] = (i << 4) + i;
}
} else {
diff --git a/engines/cine/part.cpp b/engines/cine/part.cpp
index 03cb743b46..813cbe50af 100644
--- a/engines/cine/part.cpp
+++ b/engines/cine/part.cpp
@@ -263,7 +263,7 @@ byte *readBundleSoundFile(const char *entryName, uint32 *size) {
/** Rotate byte value to the left by n bits */
byte rolByte(byte value, uint n) {
n %= 8;
- return (byte) ((value << n) | (value >> (8 - n)));
+ return (byte)((value << n) | (value >> (8 - n)));
}
byte *readFile(const char *filename, bool crypted) {
diff --git a/engines/cine/saveload.cpp b/engines/cine/saveload.cpp
index 20952eea52..51d2c1f6be 100644
--- a/engines/cine/saveload.cpp
+++ b/engines/cine/saveload.cpp
@@ -1002,7 +1002,7 @@ void loadResourcesFromSave(Common::SeekableReadStream &fHandle, enum CineSaveGam
const int entrySize = ((saveGameFormat == ANIMSIZE_23) ? 23 : 30);
const int fileStartPos = fHandle.pos();
- for(int resourceIndex=0; resourceIndex<NUM_MAX_ANIMDATA; resourceIndex++) {
+ for (int resourceIndex = 0; resourceIndex < NUM_MAX_ANIMDATA; resourceIndex++) {
// Seek to the start of the current animation's entry
fHandle.seek(fileStartPos + resourceIndex * entrySize);
// Read in the current animation entry
diff --git a/engines/cine/saveload.h b/engines/cine/saveload.h
index 49c9c0cef7..fd661904af 100644
--- a/engines/cine/saveload.h
+++ b/engines/cine/saveload.h
@@ -68,7 +68,7 @@ enum CineSaveGameFormat {
};
/** Identifier for the temporary Operation Stealth savegame format. */
-static const uint32 TEMP_OS_FORMAT_ID = MKTAG('T','E','M','P');
+static const uint32 TEMP_OS_FORMAT_ID = MKTAG('T', 'E', 'M', 'P');
/** The current version number of Operation Stealth's savegame format. */
static const uint32 CURRENT_OS_SAVE_VER = 1;
diff --git a/engines/cine/script.h b/engines/cine/script.h
index 3fc86c585b..a07c8d6cfc 100644
--- a/engines/cine/script.h
+++ b/engines/cine/script.h
@@ -227,6 +227,7 @@ protected:
int o1_op72();
int o1_op73();
int o1_playSample();
+ int o1_playSampleSwapped();
int o1_disableSystemMenu();
int o1_loadMask5();
int o1_unloadMask5();
diff --git a/engines/cine/script_fw.cpp b/engines/cine/script_fw.cpp
index 9cbe3c3fab..b4fe68c343 100644
--- a/engines/cine/script_fw.cpp
+++ b/engines/cine/script_fw.cpp
@@ -196,7 +196,7 @@ void FWScript::setupTable() {
{ 0, 0 },
{ &FWScript::o1_playSample, "bbwbww" },
/* 78 */
- { &FWScript::o1_playSample, "bbwbww" },
+ { &FWScript::o1_playSampleSwapped, "bbwbww" },
{ &FWScript::o1_disableSystemMenu, "b" },
{ &FWScript::o1_loadMask5, "b" },
{ &FWScript::o1_unloadMask5, "b" }
@@ -352,7 +352,7 @@ void ScriptVars::load(Common::SeekableReadStream &fHandle, unsigned int len) {
* Reset all values to 0
*/
void ScriptVars::reset() {
- memset( _vars, 0, _size * sizeof(int16));
+ memset(_vars, 0, _size * sizeof(int16));
}
/**
@@ -380,10 +380,10 @@ 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[_size + 1]), _labels(src._labels) {
assert(_data);
- memcpy(_data, src._data, _size+1);
+ memcpy(_data, src._data, _size + 1);
}
/**
@@ -398,7 +398,7 @@ RawScript::~RawScript() {
*/
RawScript &RawScript::operator=(const RawScript &src) {
assert(src._data);
- byte *tmp = new byte[src._size+1];
+ byte *tmp = new byte[src._size + 1];
assert(tmp);
_labels = src._labels;
@@ -443,14 +443,14 @@ int RawScript::getNextLabel(const FWScriptInfo &info, int offset) const {
pos += 2;
break;
case 'c': { // byte != 0 ? byte : word
- uint8 test = _data[pos];
+ uint8 test = _data[pos];
+ pos++;
+ if (test) {
pos++;
- if (test) {
- pos++;
- } else {
- pos += 2;
- }
+ } else {
+ pos += 2;
}
+ }
break;
case 'l': // label
return pos;
@@ -459,7 +459,7 @@ int RawScript::getNextLabel(const FWScriptInfo &info, int offset) const {
;
break;
case 'x': // exit script
- return -pos-1;
+ return -pos - 1;
}
}
}
@@ -498,9 +498,7 @@ void RawScript::computeLabels(const FWScriptInfo &info) {
*
* computeScriptStackFromScript replacement
*/
-uint16 RawScript::getLabel(const FWScriptInfo &info, byte index, uint16 offset)
- const {
-
+uint16 RawScript::getLabel(const FWScriptInfo &info, byte index, uint16 offset) const {
assert(_data);
int pos = offset;
@@ -519,7 +517,7 @@ uint16 RawScript::getLabel(const FWScriptInfo &info, byte index, uint16 offset)
*/
void RawScript::setData(const FWScriptInfo &info, const byte *data) {
assert(!_data); // this function should be called only once per instance
- _data = new byte[_size+1];
+ _data = new byte[_size + 1];
assert(data && _data);
memcpy(_data, data, _size * sizeof(byte));
@@ -553,7 +551,7 @@ byte RawScript::getByte(unsigned int pos) const {
* @return Word of bytecode
*/
uint16 RawScript::getWord(unsigned int pos) const {
- assert(_data && pos+1 < _size);
+ assert(_data && pos + 1 < _size);
return READ_BE_UINT16(_data + pos);
}
@@ -566,7 +564,7 @@ uint16 RawScript::getWord(unsigned int pos) const {
const char *RawScript::getString(unsigned int pos) const {
assert(_data && pos < _size);
- return (const char*)(_data+pos);
+ return (const char *)(_data + pos);
}
/**
@@ -580,8 +578,8 @@ const char *RawScript::getString(unsigned int pos) const {
* instance can be used. It leaves the instance in partially invalid state.
*/
RawObjectScript::RawObjectScript(uint16 s, uint16 p1, uint16 p2, uint16 p3)
- : RawScript(s), _runCount(0), _param1(p1), _param2(p2), _param3(p3)
-{ }
+ : RawScript(s), _runCount(0), _param1(p1), _param2(p2), _param3(p3) {
+}
/**
* Complete constructor
@@ -592,8 +590,9 @@ RawObjectScript::RawObjectScript(uint16 s, uint16 p1, uint16 p2, uint16 p3)
* @param p3 Third object script parameter
*/
RawObjectScript::RawObjectScript(const FWScriptInfo &info, const byte *data,
- uint16 s, uint16 p1, uint16 p2, uint16 p3) : RawScript(info, data, s),
- _runCount(0), _param1(p1), _param2(p2), _param3(p3) { }
+ uint16 s, uint16 p1, uint16 p2, uint16 p3)
+ : RawScript(info, data, s), _runCount(0), _param1(p1), _param2(p2), _param3(p3) {
+}
/**
* Contructor for global scripts
@@ -603,7 +602,8 @@ RawObjectScript::RawObjectScript(const FWScriptInfo &info, const byte *data,
FWScript::FWScript(const RawScript &script, int16 idx) : _script(script),
_pos(0), _line(0), _compare(0), _index(idx),
_labels(script.labels()), _localVars(LOCAL_VARS_SIZE),
- _globalVars(g_cine->_globalVars), _info(new FWScriptInfo) { }
+ _globalVars(g_cine->_globalVars), _info(new FWScriptInfo) {
+}
/**
* Copy constructor
@@ -611,25 +611,27 @@ FWScript::FWScript(const RawScript &script, int16 idx) : _script(script),
FWScript::FWScript(const FWScript &src) : _script(src._script), _pos(src._pos),
_line(src._line), _compare(src._compare), _index(src._index),
_labels(src._labels), _localVars(src._localVars),
- _globalVars(src._globalVars), _info(new FWScriptInfo) { }
+ _globalVars(src._globalVars), _info(new FWScriptInfo) {
+}
/**
* Contructor for global scripts in derived classes
* @param script Script bytecode reference
* @param idx Script bytecode index
*/
-FWScript::FWScript(const RawScript &script, int16 idx, FWScriptInfo *info) :
- _script(script), _pos(0), _line(0), _compare(0), _index(idx),
+FWScript::FWScript(const RawScript &script, int16 idx, FWScriptInfo *info)
+ : _script(script), _pos(0), _line(0), _compare(0), _index(idx),
_labels(script.labels()), _localVars(LOCAL_VARS_SIZE),
- _globalVars(g_cine->_globalVars), _info(info) { }
+ _globalVars(g_cine->_globalVars), _info(info) {
+}
/**
* Constructor for object scripts in derived classes
* @param script Script bytecode reference
* @param idx Script bytecode index
*/
-FWScript::FWScript(RawObjectScript &script, int16 idx, FWScriptInfo *info) :
- _script(script), _pos(0), _line(0), _compare(0), _index(idx),
+FWScript::FWScript(RawObjectScript &script, int16 idx, FWScriptInfo *info)
+ : _script(script), _pos(0), _line(0), _compare(0), _index(idx),
_labels(script.labels()), _localVars(LOCAL_VARS_SIZE),
_globalVars(g_cine->_globalVars), _info(info) {
@@ -639,8 +641,8 @@ FWScript::FWScript(RawObjectScript &script, int16 idx, FWScriptInfo *info) :
/**
* Copy constructor for derived classes
*/
-FWScript::FWScript(const FWScript &src, FWScriptInfo *info) :
- _script(src._script), _pos(src._pos), _line(src._line),
+FWScript::FWScript(const FWScript &src, FWScriptInfo *info)
+ : _script(src._script), _pos(src._pos), _line(src._line),
_compare(src._compare), _index(src._index), _labels(src._labels),
_localVars(src._localVars), _globalVars(src._globalVars), _info(info) { }
@@ -704,7 +706,7 @@ void FWScript::load(const ScriptVars &labels, const ScriptVars &local, uint16 co
int FWScript::execute() {
int ret = 0;
- if(_script._size) {
+ if (_script._size) {
while (!ret) {
_line = _pos;
byte opcode = getNextByte();
@@ -1816,6 +1818,9 @@ int FWScript::o1_playSample() {
if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) {
if (size == 0xFFFF) {
size = g_cine->_animDataTable[anim]._width * g_cine->_animDataTable[anim]._height;
+ } else if (size > g_cine->_animDataTable[anim]._width * g_cine->_animDataTable[anim]._height) {
+ warning("o1_playSample: Got invalid sample size %d for sample %d", size, anim);
+ size = g_cine->_animDataTable[anim]._width * g_cine->_animDataTable[anim]._height;
}
if (channel < 10) { // || _currentOpcode == 0x78
int channel1, channel2;
@@ -1823,8 +1828,8 @@ int FWScript::o1_playSample() {
channel1 = 0;
channel2 = 1;
} else {
- channel1 = 2;
- channel2 = 3;
+ channel1 = 3;
+ channel2 = 2;
}
g_sound->playSound(channel1, freq, data, size, -1, volume, 63, repeat);
g_sound->playSound(channel2, freq, data, size, 1, volume, 0, repeat);
@@ -1858,6 +1863,53 @@ int FWScript::o1_playSample() {
return 0;
}
+int FWScript::o1_playSampleSwapped() {
+ // TODO: The DOS version probably does not have any stereo support here
+ // since the only stereo output it supports should be the Roland MT-32.
+ // So it probably does the same as o1_playSample here. Checking this will
+ // be a good idea never the less.
+ if (g_cine->getPlatform() == Common::kPlatformPC) {
+ return o1_playSample();
+ }
+
+ debugC(5, kCineDebugScript, "Line: %d: playSampleInversed()", _line);
+
+ byte anim = getNextByte();
+ byte channel = getNextByte();
+
+ uint16 freq = getNextWord();
+ byte repeat = getNextByte();
+
+ int16 volume = getNextWord();
+ uint16 size = getNextWord();
+
+ const byte *data = g_cine->_animDataTable[anim].data();
+
+ if (!data) {
+ return 0;
+ }
+
+ if (size == 0xFFFF) {
+ size = g_cine->_animDataTable[anim]._width * g_cine->_animDataTable[anim]._height;
+ } else if (size > g_cine->_animDataTable[anim]._width * g_cine->_animDataTable[anim]._height) {
+ warning("o1_playSampleSwapped: Got invalid sample size %d for sample %d", size, anim);
+ size = g_cine->_animDataTable[anim]._width * g_cine->_animDataTable[anim]._height;
+ }
+
+ int channel1, channel2;
+ if (channel == 0) {
+ channel1 = 1;
+ channel2 = 0;
+ } else {
+ channel1 = 2;
+ channel2 = 3;
+ }
+
+ g_sound->playSound(channel1, freq, data, size, -1, volume, 63, repeat);
+ g_sound->playSound(channel2, freq, data, size, 1, volume, 0, repeat);
+ return 0;
+}
+
int FWScript::o1_disableSystemMenu() {
byte param = getNextByte();
@@ -2074,1034 +2126,970 @@ void decompileScript(const byte *scriptPtr, uint16 scriptSize, uint16 scriptIdx)
strcpy(lineBuffer, "");
switch (opcode - 1) {
- case -1:
- {
- break;
- }
- case 0x0:
- {
- byte param1;
- byte param2;
- int16 param3;
+ case -1: {
+ break;
+ }
+ case 0x0: {
+ byte param1;
+ byte param2;
+ int16 param3;
- param1 = *(localScriptPtr + position);
- position++;
+ param1 = *(localScriptPtr + position);
+ position++;
- param2 = *(localScriptPtr + position);
- position++;
+ param2 = *(localScriptPtr + position);
+ position++;
- param3 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- sprintf(lineBuffer, "obj[%d]%s = %d\n", param1, getObjPramName(param2), param3);
+ sprintf(lineBuffer, "obj[%d]%s = %d\n", param1, getObjPramName(param2), param3);
- break;
- }
- case 0x1:
- {
- byte param1;
- byte param2;
- byte param3;
+ break;
+ }
+ case 0x1: {
+ byte param1;
+ byte param2;
+ byte param3;
- param1 = *(localScriptPtr + position);
- position++;
+ param1 = *(localScriptPtr + position);
+ position++;
- param2 = *(localScriptPtr + position);
- position++;
+ param2 = *(localScriptPtr + position);
+ position++;
- param3 = *(localScriptPtr + position);
- position++;
+ param3 = *(localScriptPtr + position);
+ position++;
- sprintf(lineBuffer, "var[%d]=obj[%d]%s\n", param3, param1, getObjPramName(param2));
- break;
- }
+ sprintf(lineBuffer, "var[%d]=obj[%d]%s\n", param3, param1, getObjPramName(param2));
+ break;
+ }
case 0x2:
case 0x3:
case 0x4:
case 0x5:
- case 0x6:
- {
- byte param1;
- byte param2;
- int16 param3;
-
- param1 = *(localScriptPtr + position);
- position++;
-
- param2 = *(localScriptPtr + position);
- position++;
-
- param3 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
-
- if (opcode - 1 == 0x2) {
- sprintf(lineBuffer, "obj[%d]%s+=%d\n", param1, getObjPramName(param2), param3);
- } else if (opcode - 1 == 0x3) {
- sprintf(lineBuffer, "obj[%d]%s-=%d\n", param1, getObjPramName(param2), param3);
- } else if (opcode - 1 == 0x4) {
- sprintf(lineBuffer, "obj[%d]%s+=obj[%d]%s\n", param1, getObjPramName(param2), param3, getObjPramName(param2));
- } else if (opcode - 1 == 0x5) {
- sprintf(lineBuffer, "obj[%d]%s-=obj[%d]%s\n", param1, getObjPramName(param2), param3, getObjPramName(param2));
- } else if (opcode - 1 == 0x6) {
- sprintf(compareString1, "obj[%d]%s", param1, getObjPramName(param2));
- sprintf(compareString2, "%d", param3);
- }
- break;
+ case 0x6: {
+ byte param1;
+ byte param2;
+ int16 param3;
+
+ param1 = *(localScriptPtr + position);
+ position++;
+
+ param2 = *(localScriptPtr + position);
+ position++;
+
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ if (opcode - 1 == 0x2) {
+ sprintf(lineBuffer, "obj[%d]%s+=%d\n", param1, getObjPramName(param2), param3);
+ } else if (opcode - 1 == 0x3) {
+ sprintf(lineBuffer, "obj[%d]%s-=%d\n", param1, getObjPramName(param2), param3);
+ } else if (opcode - 1 == 0x4) {
+ sprintf(lineBuffer, "obj[%d]%s+=obj[%d]%s\n", param1, getObjPramName(param2), param3, getObjPramName(param2));
+ } else if (opcode - 1 == 0x5) {
+ sprintf(lineBuffer, "obj[%d]%s-=obj[%d]%s\n", param1, getObjPramName(param2), param3, getObjPramName(param2));
+ } else if (opcode - 1 == 0x6) {
+ sprintf(compareString1, "obj[%d]%s", param1, getObjPramName(param2));
+ sprintf(compareString2, "%d", param3);
}
+ break;
+ }
case 0x7:
- case 0x8:
- {
- byte param1;
- int16 param2;
- int16 param3;
- int16 param4;
- int16 param5;
+ case 0x8: {
+ byte param1;
+ int16 param2;
+ int16 param3;
+ int16 param4;
+ int16 param5;
- param1 = *(localScriptPtr + position);
- position++;
+ param1 = *(localScriptPtr + position);
+ position++;
- param2 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param2 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- param3 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- param4 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param4 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- param5 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param5 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- if (opcode - 1 == 0x7) {
- sprintf(lineBuffer, "setupObject(Idx:%d,X:%d,Y:%d,mask:%d,frame:%d)\n", param1, param2, param3, param4, param5);
- } else if (opcode - 1 == 0x8) {
- sprintf(lineBuffer, "checkCollision(%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5);
- }
- break;
+ if (opcode - 1 == 0x7) {
+ sprintf(lineBuffer, "setupObject(Idx:%d,X:%d,Y:%d,mask:%d,frame:%d)\n", param1, param2, param3, param4, param5);
+ } else if (opcode - 1 == 0x8) {
+ sprintf(lineBuffer, "checkCollision(%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5);
}
- case 0x9:
- {
- byte param1;
- int16 param2;
+ break;
+ }
+ case 0x9: {
+ byte param1;
+ int16 param2;
- param1 = *(localScriptPtr + position);
- position++;
+ param1 = *(localScriptPtr + position);
+ position++;
- param2 = *(localScriptPtr + position);
- position++;
+ param2 = *(localScriptPtr + position);
+ position++;
- if (param2) {
- byte param3;
-
- param3 = *(localScriptPtr + position);
- position++;
-
- if (param2 == 1) {
- sprintf(lineBuffer, "var[%d]=var[%d]\n", param1, param3);
- } else if (param2 == 2) {
- sprintf(lineBuffer, "var[%d]=globalVar[%d]\n", param1, param3);
- } else if (param2 == 3) {
- sprintf(lineBuffer, "var[%d]=mouse.X\n", param1);
- } else if (param2 == 4) {
- sprintf(lineBuffer, "var[%d]=mouse.Y\n", param1);
- } else if (param2 == 5) {
- sprintf(lineBuffer, "var[%d]=rand() mod %d\n", param1, param3);
- } else if (param2 == 8) {
- sprintf(lineBuffer, "var[%d]=file[%d].packedSize\n", param1, param3);
- } else if (param2 == 9) {
- sprintf(lineBuffer, "var[%d]=file[%d].unpackedSize\n", param1, param3);
- } else {
- error("decompileScript: 0x09: param2 = %d", param2);
- }
- } else {
- int16 param3;
+ if (param2) {
+ byte param3;
- param3 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param3 = *(localScriptPtr + position);
+ position++;
- sprintf(lineBuffer, "var[%d]=%d\n", param1, param3);
+ if (param2 == 1) {
+ sprintf(lineBuffer, "var[%d]=var[%d]\n", param1, param3);
+ } else if (param2 == 2) {
+ sprintf(lineBuffer, "var[%d]=globalVar[%d]\n", param1, param3);
+ } else if (param2 == 3) {
+ sprintf(lineBuffer, "var[%d]=mouse.X\n", param1);
+ } else if (param2 == 4) {
+ sprintf(lineBuffer, "var[%d]=mouse.Y\n", param1);
+ } else if (param2 == 5) {
+ sprintf(lineBuffer, "var[%d]=rand() mod %d\n", param1, param3);
+ } else if (param2 == 8) {
+ sprintf(lineBuffer, "var[%d]=file[%d].packedSize\n", param1, param3);
+ } else if (param2 == 9) {
+ sprintf(lineBuffer, "var[%d]=file[%d].unpackedSize\n", param1, param3);
+ } else {
+ error("decompileScript: 0x09: param2 = %d", param2);
}
+ } else {
+ int16 param3;
- break;
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ sprintf(lineBuffer, "var[%d]=%d\n", param1, param3);
}
+
+ break;
+ }
case 0xA:
case 0xB:
case 0xC:
- case 0xD:
- {
- byte param1;
- byte param2;
+ case 0xD: {
+ byte param1;
+ byte param2;
- param1 = *(localScriptPtr + position);
- position++;
+ param1 = *(localScriptPtr + position);
+ position++;
- param2 = *(localScriptPtr + position);
+ param2 = *(localScriptPtr + position);
+ position++;
+
+ if (param2) {
+ byte param3;
+
+ param3 = *(localScriptPtr + position);
position++;
- if (param2) {
- byte param3;
+ if (opcode - 1 == 0xA) {
+ sprintf(lineBuffer, "var[%d]+=var[%d]\n", param1, param3);
+ } else if (opcode - 1 == 0xB) {
+ sprintf(lineBuffer, "var[%d]-=var[%d]\n", param1, param3);
+ } else if (opcode - 1 == 0xC) {
+ sprintf(lineBuffer, "var[%d]*=var[%d]\n", param1, param3);
+ } else if (opcode - 1 == 0xD) {
+ sprintf(lineBuffer, "var[%d]/=var[%d]\n", param1, param3);
+ }
+ } else {
+ int16 param3;
- param3 = *(localScriptPtr + position);
- position++;
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- if (opcode - 1 == 0xA) {
- sprintf(lineBuffer, "var[%d]+=var[%d]\n", param1, param3);
- } else if (opcode - 1 == 0xB) {
- sprintf(lineBuffer, "var[%d]-=var[%d]\n", param1, param3);
- } else if (opcode - 1 == 0xC) {
- sprintf(lineBuffer, "var[%d]*=var[%d]\n", param1, param3);
- } else if (opcode - 1 == 0xD) {
- sprintf(lineBuffer, "var[%d]/=var[%d]\n", param1, param3);
- }
- } else {
- int16 param3;
-
- param3 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
-
- if (opcode - 1 == 0xA) {
- sprintf(lineBuffer, "var[%d]+=%d\n", param1, param3);
- } else if (opcode - 1 == 0xB) {
- sprintf(lineBuffer, "var[%d]-=%d\n", param1, param3);
- } else if (opcode - 1 == 0xC) {
- sprintf(lineBuffer, "var[%d]*=%d\n", param1, param3);
- } else if (opcode - 1 == 0xD) {
- sprintf(lineBuffer, "var[%d]/=%d\n", param1, param3);
- }
+ if (opcode - 1 == 0xA) {
+ sprintf(lineBuffer, "var[%d]+=%d\n", param1, param3);
+ } else if (opcode - 1 == 0xB) {
+ sprintf(lineBuffer, "var[%d]-=%d\n", param1, param3);
+ } else if (opcode - 1 == 0xC) {
+ sprintf(lineBuffer, "var[%d]*=%d\n", param1, param3);
+ } else if (opcode - 1 == 0xD) {
+ sprintf(lineBuffer, "var[%d]/=%d\n", param1, param3);
}
- break;
}
- case 0xE:
- {
- byte param1;
- byte param2;
+ break;
+ }
+ case 0xE: {
+ byte param1;
+ byte param2;
- param1 = *(localScriptPtr + position);
- position++;
+ param1 = *(localScriptPtr + position);
+ position++;
- param2 = *(localScriptPtr + position);
- position++;
+ param2 = *(localScriptPtr + position);
+ position++;
- if (param2) {
- byte param3;
+ if (param2) {
+ byte param3;
- param3 = *(localScriptPtr + position);
- position++;
+ param3 = *(localScriptPtr + position);
+ position++;
- if (param2 == 1) {
- sprintf(compareString1, "var[%d]", param1);
- sprintf(compareString2, "var[%d]", param3);
+ if (param2 == 1) {
+ sprintf(compareString1, "var[%d]", param1);
+ sprintf(compareString2, "var[%d]", param3);
- } else if (param2 == 2) {
- sprintf(compareString1, "var[%d]", param1);
- sprintf(compareString2, "globalVar[%d]", param3);
- } else {
- error("decompileScript: 0x0E: param2 = %d", param2);
- }
+ } else if (param2 == 2) {
+ sprintf(compareString1, "var[%d]", param1);
+ sprintf(compareString2, "globalVar[%d]", param3);
} else {
- int16 param3;
+ error("decompileScript: 0x0E: param2 = %d", param2);
+ }
+ } else {
+ int16 param3;
- param3 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- sprintf(compareString1, "var[%d]", param1);
- sprintf(compareString2, "%d", param3);
- }
- break;
+ sprintf(compareString1, "var[%d]", param1);
+ sprintf(compareString2, "%d", param3);
}
- case 0xF:
- {
- byte param1;
- byte param2;
- byte param3;
+ break;
+ }
+ case 0xF: {
+ byte param1;
+ byte param2;
+ byte param3;
- param1 = *(localScriptPtr + position);
- position++;
+ param1 = *(localScriptPtr + position);
+ position++;
- param2 = *(localScriptPtr + position);
- position++;
+ param2 = *(localScriptPtr + position);
+ position++;
- param3 = *(localScriptPtr + position);
- position++;
+ param3 = *(localScriptPtr + position);
+ position++;
- sprintf(lineBuffer, "obj[%d]%s=var[%d]\n", param1, getObjPramName(param2), param3);
+ sprintf(lineBuffer, "obj[%d]%s=var[%d]\n", param1, getObjPramName(param2), param3);
- break;
- }
+ break;
+ }
case 0x13:
case 0x14:
case 0x15:
case 0x16:
case 0x17:
case 0x18:
- case 0x19:
- {
- byte param;
-
- param = *(localScriptPtr + position);
- position++;
-
- if (opcode - 1 == 0x13) {
- sprintf(lineBuffer, "loadMask0(%d)\n", param);
- } else if (opcode - 1 == 0x14) {
- sprintf(lineBuffer, "unloadMask0(%d)\n", param);
- } else if (opcode - 1 == 0x15) {
- sprintf(lineBuffer, "OP_15(%d)\n", param);
- } else if (opcode - 1 == 0x16) {
- sprintf(lineBuffer, "loadMask1(%d)\n", param);
- } else if (opcode - 1 == 0x17) {
- sprintf(lineBuffer, "unloadMask0(%d)\n", param);
- } else if (opcode - 1 == 0x18) {
- sprintf(lineBuffer, "loadMask4(%d)\n", param);
- } else if (opcode - 1 == 0x19) {
- sprintf(lineBuffer, "unloadMask4(%d)\n", param);
- }
- break;
+ case 0x19: {
+ byte param;
+
+ param = *(localScriptPtr + position);
+ position++;
+
+ if (opcode - 1 == 0x13) {
+ sprintf(lineBuffer, "loadMask0(%d)\n", param);
+ } else if (opcode - 1 == 0x14) {
+ sprintf(lineBuffer, "unloadMask0(%d)\n", param);
+ } else if (opcode - 1 == 0x15) {
+ sprintf(lineBuffer, "OP_15(%d)\n", param);
+ } else if (opcode - 1 == 0x16) {
+ sprintf(lineBuffer, "loadMask1(%d)\n", param);
+ } else if (opcode - 1 == 0x17) {
+ sprintf(lineBuffer, "unloadMask0(%d)\n", param);
+ } else if (opcode - 1 == 0x18) {
+ sprintf(lineBuffer, "loadMask4(%d)\n", param);
+ } else if (opcode - 1 == 0x19) {
+ sprintf(lineBuffer, "unloadMask4(%d)\n", param);
}
- case 0x1A:
- {
- byte param;
+ break;
+ }
+ case 0x1A: {
+ byte param;
- param = *(localScriptPtr + position);
- position++;
+ param = *(localScriptPtr + position);
+ position++;
- sprintf(lineBuffer, "OP_1A(%d)\n", param);
+ sprintf(lineBuffer, "OP_1A(%d)\n", param);
- break;
- }
- case 0x1B:
- {
- sprintf(lineBuffer, "bgIncrustList.clear()\n");
- break;
- }
- case 0x1D:
- {
- byte param;
+ break;
+ }
+ case 0x1B: {
+ sprintf(lineBuffer, "bgIncrustList.clear()\n");
+ break;
+ }
+ case 0x1D: {
+ byte param;
- param = *(localScriptPtr + position);
- position++;
+ param = *(localScriptPtr + position);
+ position++;
- sprintf(lineBuffer, "label(%d)\n", param);
+ sprintf(lineBuffer, "label(%d)\n", param);
- break;
- }
- case 0x1E:
- {
- byte param;
+ break;
+ }
+ case 0x1E: {
+ byte param;
- param = *(localScriptPtr + position);
- position++;
+ param = *(localScriptPtr + position);
+ position++;
- sprintf(lineBuffer, "goto(%d)\n", param);
+ sprintf(lineBuffer, "goto(%d)\n", param);
- break;
- }
+ break;
+ }
// If cases
case 0x1F:
case 0x20:
case 0x21:
case 0x22:
case 0x23:
- case 0x24:
- {
- byte param;
-
- param = *(localScriptPtr + position);
- position++;
-
- if (opcode - 1 == 0x1F) {
- sprintf(lineBuffer, "if(%s>%s) goto(%d)\n", compareString1, compareString2, param);
- } else if (opcode - 1 == 0x20) {
- sprintf(lineBuffer, "if(%s>=%s) goto(%d)\n", compareString1, compareString2, param);
- } else if (opcode - 1 == 0x21) {
- sprintf(lineBuffer, "if(%s<%s) goto(%d)\n", compareString1, compareString2, param);
- } else if (opcode - 1 == 0x22) {
- sprintf(lineBuffer, "if(%s<=%s) goto(%d)\n", compareString1, compareString2, param);
- } else if (opcode - 1 == 0x23) {
- sprintf(lineBuffer, "if(%s==%s) goto(%d)\n", compareString1, compareString2, param);
- } else if (opcode - 1 == 0x24) {
- sprintf(lineBuffer, "if(%s!=%s) goto(%d)\n", compareString1, compareString2, param);
- }
- break;
+ case 0x24: {
+ byte param;
+
+ param = *(localScriptPtr + position);
+ position++;
+
+ if (opcode - 1 == 0x1F) {
+ sprintf(lineBuffer, "if(%s>%s) goto(%d)\n", compareString1, compareString2, param);
+ } else if (opcode - 1 == 0x20) {
+ sprintf(lineBuffer, "if(%s>=%s) goto(%d)\n", compareString1, compareString2, param);
+ } else if (opcode - 1 == 0x21) {
+ sprintf(lineBuffer, "if(%s<%s) goto(%d)\n", compareString1, compareString2, param);
+ } else if (opcode - 1 == 0x22) {
+ sprintf(lineBuffer, "if(%s<=%s) goto(%d)\n", compareString1, compareString2, param);
+ } else if (opcode - 1 == 0x23) {
+ sprintf(lineBuffer, "if(%s==%s) goto(%d)\n", compareString1, compareString2, param);
+ } else if (opcode - 1 == 0x24) {
+ sprintf(lineBuffer, "if(%s!=%s) goto(%d)\n", compareString1, compareString2, param);
}
- case 0x25:
- {
- byte param;
+ break;
+ }
+ case 0x25: {
+ byte param;
- param = *(localScriptPtr + position);
- position++;
+ param = *(localScriptPtr + position);
+ position++;
- sprintf(lineBuffer, "removeLabel(%d)\n", param);
+ sprintf(lineBuffer, "removeLabel(%d)\n", param);
- break;
- }
- case 0x26:
- {
- byte param1;
- byte param2;
+ break;
+ }
+ case 0x26: {
+ byte param1;
+ byte param2;
- param1 = *(localScriptPtr + position);
- position++;
- param2 = *(localScriptPtr + position);
- position++;
+ param1 = *(localScriptPtr + position);
+ position++;
+ param2 = *(localScriptPtr + position);
+ position++;
- sprintf(lineBuffer, "loop(--var[%d]) -> label(%d)\n", param1, param2);
+ sprintf(lineBuffer, "loop(--var[%d]) -> label(%d)\n", param1, param2);
- break;
- }
+ break;
+ }
case 0x31:
- case 0x32:
- {
- byte param;
+ case 0x32: {
+ byte param;
- param = *(localScriptPtr + position);
- position++;
+ param = *(localScriptPtr + position);
+ position++;
- if (opcode - 1 == 0x31) {
- sprintf(lineBuffer, "startGlobalScript(%d)\n", param);
- } else if (opcode - 1 == 0x32) {
- sprintf(lineBuffer, "endGlobalScript(%d)\n", param);
- }
- break;
+ if (opcode - 1 == 0x31) {
+ sprintf(lineBuffer, "startGlobalScript(%d)\n", param);
+ } else if (opcode - 1 == 0x32) {
+ sprintf(lineBuffer, "endGlobalScript(%d)\n", param);
}
+ break;
+ }
case 0x3B:
case 0x3C:
case 0x3D:
- case OP_loadPart:
- {
- if (opcode - 1 == 0x3B) {
- sprintf(lineBuffer, "loadResource(%s)\n", localScriptPtr + position);
- } else if (opcode - 1 == 0x3C) {
- sprintf(lineBuffer, "loadBg(%s)\n", localScriptPtr + position);
- } else if (opcode - 1 == 0x3D) {
- sprintf(lineBuffer, "loadCt(%s)\n", localScriptPtr + position);
- } else if (opcode - 1 == OP_loadPart) {
- sprintf(lineBuffer, "loadPart(%s)\n", localScriptPtr + position);
- }
-
- position += strlen((const char *)localScriptPtr + position) + 1;
- break;
- }
- case 0x40:
- {
- sprintf(lineBuffer, "closePart()\n");
- break;
- }
- case OP_loadNewPrcName:
- {
- byte param;
+ case OP_loadPart: {
+ if (opcode - 1 == 0x3B) {
+ sprintf(lineBuffer, "loadResource(%s)\n", localScriptPtr + position);
+ } else if (opcode - 1 == 0x3C) {
+ sprintf(lineBuffer, "loadBg(%s)\n", localScriptPtr + position);
+ } else if (opcode - 1 == 0x3D) {
+ sprintf(lineBuffer, "loadCt(%s)\n", localScriptPtr + position);
+ } else if (opcode - 1 == OP_loadPart) {
+ sprintf(lineBuffer, "loadPart(%s)\n", localScriptPtr + position);
+ }
+
+ position += strlen((const char *)localScriptPtr + position) + 1;
+ break;
+ }
+ case 0x40: {
+ sprintf(lineBuffer, "closePart()\n");
+ break;
+ }
+ case OP_loadNewPrcName: {
+ byte param;
- param = *(localScriptPtr + position);
- position++;
+ param = *(localScriptPtr + position);
+ position++;
- sprintf(lineBuffer, "loadPrc(%d,%s)\n", param, localScriptPtr + position);
+ sprintf(lineBuffer, "loadPrc(%d,%s)\n", param, localScriptPtr + position);
- position += strlen((const char *)localScriptPtr + position) + 1;
- break;
- }
- case OP_requestCheckPendingDataLoad: // nop
- {
- sprintf(lineBuffer, "requestCheckPendingDataLoad()\n");
- break;
- }
- case 0x45:
- {
- sprintf(lineBuffer, "blitAndFade()\n");
- break;
- }
- case 0x46:
- {
- sprintf(lineBuffer, "fadeToBlack()\n");
- break;
- }
- case 0x47:
- {
- byte param1;
- byte param2;
- int16 param3;
- int16 param4;
- int16 param5;
+ position += strlen((const char *)localScriptPtr + position) + 1;
+ break;
+ }
+ case OP_requestCheckPendingDataLoad: { // nop
+ sprintf(lineBuffer, "requestCheckPendingDataLoad()\n");
+ break;
+ }
+ case 0x45: {
+ sprintf(lineBuffer, "blitAndFade()\n");
+ break;
+ }
+ case 0x46: {
+ sprintf(lineBuffer, "fadeToBlack()\n");
+ break;
+ }
+ case 0x47: {
+ byte param1;
+ byte param2;
+ int16 param3;
+ int16 param4;
+ int16 param5;
- param1 = *(localScriptPtr + position);
- position++;
+ param1 = *(localScriptPtr + position);
+ position++;
- param2 = *(localScriptPtr + position);
- position++;
+ param2 = *(localScriptPtr + position);
+ position++;
- param3 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- param4 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param4 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- param5 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param5 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- sprintf(lineBuffer, "transformPaletteRange(%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5);
+ sprintf(lineBuffer, "transformPaletteRange(%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5);
- break;
- }
- case 0x49:
- {
- byte param;
+ break;
+ }
+ case 0x49: {
+ byte param;
- param = *(localScriptPtr + position);
- position++;
+ param = *(localScriptPtr + position);
+ position++;
- sprintf(lineBuffer, "setDefaultMenuBgColor(%d)\n", param);
+ sprintf(lineBuffer, "setDefaultMenuBgColor(%d)\n", param);
- break;
- }
- case 0x4F:
- {
- sprintf(lineBuffer, "break()\n");
- exitScript = 1;
- break;
- }
- case 0x50:
- {
- sprintf(lineBuffer, "endScript()\n\n");
- break;
- }
- case 0x51:
- {
- byte param1;
- int16 param2;
- int16 param3;
- int16 param4;
- int16 param5;
+ break;
+ }
+ case 0x4F: {
+ sprintf(lineBuffer, "break()\n");
+ exitScript = 1;
+ break;
+ }
+ case 0x50: {
+ sprintf(lineBuffer, "endScript()\n\n");
+ break;
+ }
+ case 0x51: {
+ byte param1;
+ int16 param2;
+ int16 param3;
+ int16 param4;
+ int16 param5;
- param1 = *(localScriptPtr + position);
- position++;
+ param1 = *(localScriptPtr + position);
+ position++;
- param2 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param2 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- param3 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- param4 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param4 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- param5 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param5 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- sprintf(lineBuffer, "message(%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5);
+ sprintf(lineBuffer, "message(%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5);
- break;
- }
+ break;
+ }
case 0x52:
- case 0x53:
- {
- byte param1;
- byte param2;
+ case 0x53: {
+ byte param1;
+ byte param2;
- param1 = *(localScriptPtr + position);
- position++;
+ param1 = *(localScriptPtr + position);
+ position++;
- param2 = *(localScriptPtr + position);
- position++;
+ param2 = *(localScriptPtr + position);
+ position++;
- if (param2) {
- byte param3;
-
- param3 = *(localScriptPtr + position);
- position++;
-
- if (param2 == 1) {
- if (opcode - 1 == 0x52) {
- sprintf(lineBuffer, "globalVar[%d] = var[%d]\n", param1, param3);
- } else if (opcode - 1 == 0x53) {
- sprintf(compareString1, "globalVar[%d]", param1);
- sprintf(compareString2, "var[%d]", param3);
- }
- } else if (param2 == 2) {
- if (opcode - 1 == 0x52) {
- sprintf(lineBuffer, "globalVar[%d] = globalVar[%d]\n", param1, param3);
- } else if (opcode - 1 == 0x53) {
- sprintf(compareString1, "globalVar[%d]", param1);
- sprintf(compareString2, "globalVar[%d]", param3);
- }
- } else {
- if (opcode - 1 == 0x52) {
- error("decompileScript: 0x52: param2 = %d", param2);
- } else if (opcode - 1 == 0x53) {
- error("decompileScript: 0x53: param2 = %d", param2);
- }
- }
- } else {
- int16 param3;
+ if (param2) {
+ byte param3;
- param3 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param3 = *(localScriptPtr + position);
+ position++;
+ if (param2 == 1) {
if (opcode - 1 == 0x52) {
- sprintf(lineBuffer, "globalVar[%d] = %d\n", param1, param3);
+ sprintf(lineBuffer, "globalVar[%d] = var[%d]\n", param1, param3);
} else if (opcode - 1 == 0x53) {
sprintf(compareString1, "globalVar[%d]", param1);
- sprintf(compareString2, "%d", param3);
+ sprintf(compareString2, "var[%d]", param3);
+ }
+ } else if (param2 == 2) {
+ if (opcode - 1 == 0x52) {
+ sprintf(lineBuffer, "globalVar[%d] = globalVar[%d]\n", param1, param3);
+ } else if (opcode - 1 == 0x53) {
+ sprintf(compareString1, "globalVar[%d]", param1);
+ sprintf(compareString2, "globalVar[%d]", param3);
+ }
+ } else {
+ if (opcode - 1 == 0x52) {
+ error("decompileScript: 0x52: param2 = %d", param2);
+ } else if (opcode - 1 == 0x53) {
+ error("decompileScript: 0x53: param2 = %d", param2);
}
}
- break;
- }
- case 0x59:
- {
- sprintf(lineBuffer, "comment: %s\n", localScriptPtr + position);
+ } else {
+ int16 param3;
- position += strlen((const char *)localScriptPtr + position);
- break;
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
+
+ if (opcode - 1 == 0x52) {
+ sprintf(lineBuffer, "globalVar[%d] = %d\n", param1, param3);
+ } else if (opcode - 1 == 0x53) {
+ sprintf(compareString1, "globalVar[%d]", param1);
+ sprintf(compareString2, "%d", param3);
+ }
}
- case 0x5A:
- {
- byte param1;
- byte param2;
+ break;
+ }
+ case 0x59: {
+ sprintf(lineBuffer, "comment: %s\n", localScriptPtr + position);
- param1 = *(localScriptPtr + position);
- position++;
+ position += strlen((const char *)localScriptPtr + position);
+ break;
+ }
+ case 0x5A: {
+ byte param1;
+ byte param2;
- param2 = *(localScriptPtr + position);
- position++;
+ param1 = *(localScriptPtr + position);
+ position++;
- sprintf(lineBuffer, "freePartRang(%d,%d)\n", param1, param2);
+ param2 = *(localScriptPtr + position);
+ position++;
- break;
- }
- case 0x5B:
- {
- sprintf(lineBuffer, "unloadAllMasks()\n");
- break;
- }
- case 0x65:
- {
- sprintf(lineBuffer, "setupTableUnk1()\n");
- break;
- }
- case 0x66:
- {
- byte param1;
- int16 param2;
+ sprintf(lineBuffer, "freePartRang(%d,%d)\n", param1, param2);
- param1 = *(localScriptPtr + position);
- position++;
+ break;
+ }
+ case 0x5B: {
+ sprintf(lineBuffer, "unloadAllMasks()\n");
+ break;
+ }
+ case 0x65: {
+ sprintf(lineBuffer, "setupTableUnk1()\n");
+ break;
+ }
+ case 0x66: {
+ byte param1;
+ int16 param2;
- param2 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param1 = *(localScriptPtr + position);
+ position++;
- sprintf(lineBuffer, "tableUnk1[%d] = %d\n", param1, param2);
+ param2 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- break;
- }
- case 0x68:
- {
- byte param;
+ sprintf(lineBuffer, "tableUnk1[%d] = %d\n", param1, param2);
- param = *(localScriptPtr + position);
- position++;
+ break;
+ }
+ case 0x68: {
+ byte param;
- sprintf(lineBuffer, "setPlayerCommandPosY(%d)\n", param);
+ param = *(localScriptPtr + position);
+ position++;
- break;
- }
- case 0x69:
- {
- sprintf(lineBuffer, "allowPlayerInput()\n");
- break;
- }
- case 0x6A:
- {
- sprintf(lineBuffer, "disallowPlayerInput()\n");
- break;
- }
- case 0x6B:
- {
- byte newDisk;
+ sprintf(lineBuffer, "setPlayerCommandPosY(%d)\n", param);
- newDisk = *(localScriptPtr + position);
- position++;
+ break;
+ }
+ case 0x69: {
+ sprintf(lineBuffer, "allowPlayerInput()\n");
+ break;
+ }
+ case 0x6A: {
+ sprintf(lineBuffer, "disallowPlayerInput()\n");
+ break;
+ }
+ case 0x6B: {
+ byte newDisk;
- sprintf(lineBuffer, "changeDataDisk(%d)\n", newDisk);
+ newDisk = *(localScriptPtr + position);
+ position++;
- break;
- }
- case 0x6D:
- {
- sprintf(lineBuffer, "loadDat(%s)\n", localScriptPtr + position);
+ sprintf(lineBuffer, "changeDataDisk(%d)\n", newDisk);
- position += strlen((const char *)localScriptPtr + position) + 1;
- break;
- }
- case 0x6E: // nop
- {
- sprintf(lineBuffer, "updateDat()\n");
- break;
- }
- case 0x6F:
- {
- sprintf(lineBuffer, "OP_6F() -> dat related\n");
- break;
- }
- case 0x70:
- {
- sprintf(lineBuffer, "stopSample()\n");
- break;
- }
- case 0x79:
- {
- byte param;
+ break;
+ }
+ case 0x6D: {
+ sprintf(lineBuffer, "loadDat(%s)\n", localScriptPtr + position);
- param = *(localScriptPtr + position);
- position++;
+ position += strlen((const char *)localScriptPtr + position) + 1;
+ break;
+ }
+ case 0x6E: { // nop
+ sprintf(lineBuffer, "updateDat()\n");
+ break;
+ }
+ case 0x6F: {
+ sprintf(lineBuffer, "OP_6F() -> dat related\n");
+ break;
+ }
+ case 0x70: {
+ sprintf(lineBuffer, "stopSample()\n");
+ break;
+ }
+ case 0x79: {
+ byte param;
- sprintf(lineBuffer, "disableSystemMenu(%d)\n", param);
+ param = *(localScriptPtr + position);
+ position++;
- break;
- }
+ sprintf(lineBuffer, "disableSystemMenu(%d)\n", param);
+
+ break;
+ }
case 0x77:
- case 0x78:
- {
- byte param1;
- byte param2;
- int16 param3;
- byte param4;
- int16 param5;
- int16 param6;
+ case 0x78: {
+ byte param1;
+ byte param2;
+ int16 param3;
+ byte param4;
+ int16 param5;
+ int16 param6;
- param1 = *(localScriptPtr + position);
- position++;
+ param1 = *(localScriptPtr + position);
+ position++;
- param2 = *(localScriptPtr + position);
- position++;
+ param2 = *(localScriptPtr + position);
+ position++;
- param3 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- param4 = *(localScriptPtr + position);
- position++;
+ param4 = *(localScriptPtr + position);
+ position++;
- param5 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param5 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- param6 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
-
- if (opcode - 1 == 0x77) {
- sprintf(lineBuffer, "playSample(%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6);
- } else if (opcode - 1 == 0x78) {
- sprintf(lineBuffer, "OP_78(%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6);
- }
+ param6 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- break;
+ if (opcode - 1 == 0x77) {
+ sprintf(lineBuffer, "playSample(%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6);
+ } else if (opcode - 1 == 0x78) {
+ sprintf(lineBuffer, "playSampleSwapped(%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6);
}
- case 0x7A:
- {
- byte param;
- param = *(localScriptPtr + position);
- position++;
+ break;
+ }
+ case 0x7A: {
+ byte param;
- sprintf(lineBuffer, "OP_7A(%d)\n", param);
+ param = *(localScriptPtr + position);
+ position++;
- break;
- }
- case 0x7B: // OS only
- {
- byte param;
+ sprintf(lineBuffer, "OP_7A(%d)\n", param);
- param = *(localScriptPtr + position);
- position++;
+ break;
+ }
+ case 0x7B: { // OS only
+ byte param;
- sprintf(lineBuffer, "OP_7B(%d)\n", param);
+ param = *(localScriptPtr + position);
+ position++;
- break;
- }
- case 0x7F: // OS only
- {
- byte param1;
- byte param2;
- byte param3;
- byte param4;
- int16 param5;
- int16 param6;
- int16 param7;
+ sprintf(lineBuffer, "OP_7B(%d)\n", param);
- param1 = *(localScriptPtr + position);
- position++;
+ break;
+ }
+ case 0x7F: { // OS only
+ byte param1;
+ byte param2;
+ byte param3;
+ byte param4;
+ int16 param5;
+ int16 param6;
+ int16 param7;
- param2 = *(localScriptPtr + position);
- position++;
+ param1 = *(localScriptPtr + position);
+ position++;
- param3 = *(localScriptPtr + position);
- position++;
+ param2 = *(localScriptPtr + position);
+ position++;
- param4 = *(localScriptPtr + position);
- position++;
+ param3 = *(localScriptPtr + position);
+ position++;
- param5 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param4 = *(localScriptPtr + position);
+ position++;
- param6 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param5 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- param7 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param6 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- sprintf(lineBuffer, "OP_7F(%d,%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6, param7);
+ param7 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- break;
- }
- case 0x80: // OS only
- {
- byte param1;
- byte param2;
+ sprintf(lineBuffer, "OP_7F(%d,%d,%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5, param6, param7);
- param1 = *(localScriptPtr + position);
- position++;
+ break;
+ }
+ case 0x80: { // OS only
+ byte param1;
+ byte param2;
- param2 = *(localScriptPtr + position);
- position++;
+ param1 = *(localScriptPtr + position);
+ position++;
- sprintf(lineBuffer, "OP_80(%d,%d)\n", param1, param2);
+ param2 = *(localScriptPtr + position);
+ position++;
- break;
- }
- case 0x82: // OS only
- {
- byte param1;
- byte param2;
- uint16 param3;
- uint16 param4;
- byte param5;
+ sprintf(lineBuffer, "OP_80(%d,%d)\n", param1, param2);
- param1 = *(localScriptPtr + position);
- position++;
+ break;
+ }
+ case 0x82: { // OS only
+ byte param1;
+ byte param2;
+ uint16 param3;
+ uint16 param4;
+ byte param5;
- param2 = *(localScriptPtr + position);
- position++;
+ param1 = *(localScriptPtr + position);
+ position++;
- param3 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param2 = *(localScriptPtr + position);
+ position++;
- param4 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- param5 = *(localScriptPtr + position);
- position++;
+ param4 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- sprintf(lineBuffer, "OP_82(%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5);
+ param5 = *(localScriptPtr + position);
+ position++;
- break;
- }
- case 0x83: // OS only
- {
- byte param1;
- byte param2;
+ sprintf(lineBuffer, "OP_82(%d,%d,%d,%d,%d)\n", param1, param2, param3, param4, param5);
- param1 = *(localScriptPtr + position);
- position++;
+ break;
+ }
+ case 0x83: { // OS only
+ byte param1;
+ byte param2;
- param2 = *(localScriptPtr + position);
- position++;
+ param1 = *(localScriptPtr + position);
+ position++;
- sprintf(lineBuffer, "OP_83(%d,%d)\n", param1, param2);
+ param2 = *(localScriptPtr + position);
+ position++;
- break;
- }
- case 0x89: // OS only
- {
- byte param;
+ sprintf(lineBuffer, "OP_83(%d,%d)\n", param1, param2);
- param = *(localScriptPtr + position);
- position++;
+ break;
+ }
+ case 0x89: { // OS only
+ byte param;
- sprintf(lineBuffer, "if(%s!=%s) goto next label(%d)\n", compareString1, compareString2, param);
+ param = *(localScriptPtr + position);
+ position++;
- break;
- }
- case 0x8B: // OS only
- {
- byte param;
+ sprintf(lineBuffer, "if(%s!=%s) goto next label(%d)\n", compareString1, compareString2, param);
- param = *(localScriptPtr + position);
- position++;
+ break;
+ }
+ case 0x8B: { // OS only
+ byte param;
- sprintf(lineBuffer, "OP_8B(%d)\n", param);
+ param = *(localScriptPtr + position);
+ position++;
- break;
- }
- case 0x8C: // OS only
- {
- byte param;
+ sprintf(lineBuffer, "OP_8B(%d)\n", param);
- param = *(localScriptPtr + position);
- position++;
+ break;
+ }
+ case 0x8C: { // OS only
+ byte param;
- sprintf(lineBuffer, "OP_8C(%d)\n", param);
+ param = *(localScriptPtr + position);
+ position++;
- break;
- }
- case 0x8D: // OS only
- {
- int16 param1;
- int16 param2;
- int16 param3;
- int16 param4;
- int16 param5;
- int16 param6;
- int16 param7;
- int16 param8;
+ sprintf(lineBuffer, "OP_8C(%d)\n", param);
- param1 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ break;
+ }
+ case 0x8D: { // OS only
+ int16 param1;
+ int16 param2;
+ int16 param3;
+ int16 param4;
+ int16 param5;
+ int16 param6;
+ int16 param7;
+ int16 param8;
- param2 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param1 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- param3 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param2 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- param4 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param3 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- param5 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param4 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- param6 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param5 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- param7 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param6 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- param8 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ param7 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- sprintf(compareString1, "obj[%d]", param1);
- sprintf(compareString2, "{%d,%d,%d,%d,%d,%d,%d}", param2, param3, param4, param5, param6, param7, param8);
+ param8 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- break;
- }
- case 0x8E: // OS only
- {
- byte param1;
+ sprintf(compareString1, "obj[%d]", param1);
+ sprintf(compareString2, "{%d,%d,%d,%d,%d,%d,%d}", param2, param3, param4, param5, param6, param7, param8);
- param1 = *(localScriptPtr + position);
- position++;
+ break;
+ }
+ case 0x8E: { // OS only
+ byte param1;
- sprintf(lineBuffer, "ADDBG(%d,%s)\n", param1, localScriptPtr + position);
+ param1 = *(localScriptPtr + position);
+ position++;
- position += strlen((const char *)localScriptPtr + position);
+ sprintf(lineBuffer, "ADDBG(%d,%s)\n", param1, localScriptPtr + position);
- break;
- }
- case 0x8F: // OS only
- {
- byte param;
+ position += strlen((const char *)localScriptPtr + position);
- param = *(localScriptPtr + position);
- position++;
+ break;
+ }
+ case 0x8F: { // OS only
+ byte param;
- sprintf(lineBuffer, "OP_8F(%d)\n", param);
+ param = *(localScriptPtr + position);
+ position++;
- break;
- }
- case 0x90: // OS only
- {
- byte param1;
+ sprintf(lineBuffer, "OP_8F(%d)\n", param);
- param1 = *(localScriptPtr + position);
- position++;
+ break;
+ }
+ case 0x90: { // OS only
+ byte param1;
- sprintf(lineBuffer, "loadABS(%d,%s)\n", param1, localScriptPtr + position);
+ param1 = *(localScriptPtr + position);
+ position++;
- position += strlen((const char *)localScriptPtr + position);
+ sprintf(lineBuffer, "loadABS(%d,%s)\n", param1, localScriptPtr + position);
- break;
- }
- case 0x91: // OS only
- {
- byte param;
+ position += strlen((const char *)localScriptPtr + position);
- param = *(localScriptPtr + position);
- position++;
+ break;
+ }
+ case 0x91: { // OS only
+ byte param;
- sprintf(lineBuffer, "OP_91(%d)\n", param);
+ param = *(localScriptPtr + position);
+ position++;
- break;
- }
- case 0x9D: // OS only
- {
- byte param;
+ sprintf(lineBuffer, "OP_91(%d)\n", param);
- param = *(localScriptPtr + position);
- position++;
+ break;
+ }
+ case 0x9D: { // OS only
+ byte param;
- sprintf(lineBuffer, "OP_9D(%d) -> flip img idx\n", param);
+ param = *(localScriptPtr + position);
+ position++;
- break;
- }
- case 0x9E: // OS only
- {
- byte param;
+ sprintf(lineBuffer, "OP_9D(%d) -> flip img idx\n", param);
- param = *(localScriptPtr + position);
- position++;
+ break;
+ }
+ case 0x9E: { // OS only
+ byte param;
- if (param) {
- byte param2;
+ param = *(localScriptPtr + position);
+ position++;
- param2 = *(localScriptPtr + position);
- position++;
+ if (param) {
+ byte param2;
- sprintf(lineBuffer, "OP_9E(%d,%d)\n", param, param2);
- } else {
- int16 param2;
+ param2 = *(localScriptPtr + position);
+ position++;
- param2 = READ_BE_UINT16(localScriptPtr + position);
- position += 2;
+ sprintf(lineBuffer, "OP_9E(%d,%d)\n", param, param2);
+ } else {
+ int16 param2;
- sprintf(lineBuffer, "OP_9E(%d,%d)\n", param, param2);
- }
+ param2 = READ_BE_UINT16(localScriptPtr + position);
+ position += 2;
- break;
+ sprintf(lineBuffer, "OP_9E(%d,%d)\n", param, param2);
}
- case 0xA0: // OS only
- {
- byte param1;
- byte param2;
- param1 = *(localScriptPtr + position);
- position++;
+ break;
+ }
+ case 0xA0: { // OS only
+ byte param1;
+ byte param2;
- param2 = *(localScriptPtr + position);
- position++;
+ param1 = *(localScriptPtr + position);
+ position++;
- sprintf(lineBuffer, "OP_A0(%d,%d)\n", param1, param2);
+ param2 = *(localScriptPtr + position);
+ position++;
- break;
- }
- case 0xA1: // OS only
- {
- byte param1;
- byte param2;
+ sprintf(lineBuffer, "OP_A0(%d,%d)\n", param1, param2);
- param1 = *(localScriptPtr + position);
- position++;
+ break;
+ }
+ case 0xA1: { // OS only
+ byte param1;
+ byte param2;
- param2 = *(localScriptPtr + position);
- position++;
+ param1 = *(localScriptPtr + position);
+ position++;
- sprintf(lineBuffer, "OP_A1(%d,%d)\n", param1, param2);
+ param2 = *(localScriptPtr + position);
+ position++;
- break;
- }
- default:
- {
- sprintf(lineBuffer, "Unsupported opcode %X in decompileScript\n\n", opcode - 1);
- position = scriptSize;
- break;
- }
+ sprintf(lineBuffer, "OP_A1(%d,%d)\n", param1, param2);
+
+ break;
+ }
+ default: {
+ sprintf(lineBuffer, "Unsupported opcode %X in decompileScript\n\n", opcode - 1);
+ position = scriptSize;
+ break;
+ }
}
- // printf(lineBuffer);
+ //printf(lineBuffer);
strcpy(decompileBuffer[decompileBufferPosition++], lineBuffer);
exitScript = 0;
diff --git a/engines/cine/sound.cpp b/engines/cine/sound.cpp
index 52e1cdac7e..10404ae56b 100644
--- a/engines/cine/sound.cpp
+++ b/engines/cine/sound.cpp
@@ -153,7 +153,7 @@ const int AdLibSoundDriver::_freqTable[] = {
const int AdLibSoundDriver::_freqTableCount = ARRAYSIZE(_freqTable);
const int AdLibSoundDriver::_operatorsTable[] = {
- 0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21
+ 0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21
};
const int AdLibSoundDriver::_operatorsTableCount = ARRAYSIZE(_operatorsTable);
@@ -614,7 +614,7 @@ void AdLibSoundDriverADL::playSample(const byte *data, int size, int channel, in
}
MidiSoundDriverH32::MidiSoundDriverH32(MidiDriver *output)
- : _output(output), _callback(0), _mutex() {
+ : _output(output), _callback(0), _mutex() {
}
MidiSoundDriverH32::~MidiSoundDriverH32() {
@@ -731,13 +731,13 @@ void MidiSoundDriverH32::selectInstrument(int channel, int timbreGroup, int timb
0x00, 0x00, 0x00, // offset
0x00, // Timbre group _ timbreGroup * 64 + timbreNumber should be the
0x00, // Timbre number / MT-32 instrument in case timbreGroup is 0 or 1.
- 0x18, // Key shift (= 0)
+ 0x18, // Key shift (= 0)
0x32, // Fine tune (= 0)
0x0C, // Bender Range
0x03, // Assign Mode
0x01, // Reverb Switch (= enabled)
0x00, // dummy
- 0x00, // Output level
+ 0x00, // Output level
0x07, // Panpot (= balanced)
0x00, // dummy
0x00, // dummy
@@ -998,19 +998,55 @@ void PCSound::stopSound(int channel) {
}
PaulaSound::PaulaSound(Audio::Mixer *mixer, CineEngine *vm)
- : Sound(mixer, vm) {
+ : Sound(mixer, vm), _sfxTimer(0), _musicTimer(0), _musicFadeTimer(0) {
_moduleStream = 0;
+ // The original is using the following timer frequency:
+ // 0.709379Mhz / 8000 = 88.672375Hz
+ // 1000000 / 88.672375Hz = 11277.46944863us
+ g_system->getTimerManager()->installTimerProc(&PaulaSound::sfxTimerProc, 11277, this, "PaulaSound::sfxTimerProc");
+ // The original is using the following timer frequency:
+ // 0.709379Mhz / 14565 = 48.704359Hz
+ // 1000000 / 48.704359Hz = 20532.04313806us
+ g_system->getTimerManager()->installTimerProc(&PaulaSound::musicTimerProc, 20532, this, "PaulaSound::musicTimerProc");
}
PaulaSound::~PaulaSound() {
+ Common::StackLock sfxLock(_sfxMutex);
+ g_system->getTimerManager()->removeTimerProc(&PaulaSound::sfxTimerProc);
for (int i = 0; i < NUM_CHANNELS; ++i) {
stopSound(i);
}
+
+ Common::StackLock musicLock(_musicMutex);
+ g_system->getTimerManager()->removeTimerProc(&PaulaSound::musicTimerProc);
stopMusic();
}
void PaulaSound::loadMusic(const char *name) {
debugC(5, kCineDebugSound, "PaulaSound::loadMusic('%s')", name);
+ for (int i = 0; i < NUM_CHANNELS; ++i) {
+ stopSound(i);
+ }
+
+ // Fade music out when there is music playing.
+ _musicMutex.lock();
+ if (_mixer->isSoundHandleActive(_moduleHandle)) {
+ // Only start fade out when it is not in progress.
+ if (!_musicFadeTimer) {
+ _musicFadeTimer = 1;
+ }
+
+ _musicMutex.unlock();
+ while (_musicFadeTimer != 64) {
+ g_system->delayMillis(50);
+ }
+ } else {
+ _musicMutex.unlock();
+ }
+
+ Common::StackLock lock(_musicMutex);
+ assert(!_mixer->isSoundHandleActive(_moduleHandle));
+
if (_vm->getGameType() == GType_FW) {
// look for separate files
Common::File f;
@@ -1031,54 +1067,135 @@ void PaulaSound::loadMusic(const char *name) {
void PaulaSound::playMusic() {
debugC(5, kCineDebugSound, "PaulaSound::playMusic()");
+ Common::StackLock lock(_musicMutex);
+
_mixer->stopHandle(_moduleHandle);
if (_moduleStream) {
+ _musicFadeTimer = 0;
_mixer->playStream(Audio::Mixer::kMusicSoundType, &_moduleHandle, _moduleStream);
}
}
void PaulaSound::stopMusic() {
debugC(5, kCineDebugSound, "PaulaSound::stopMusic()");
+ Common::StackLock lock(_musicMutex);
+
_mixer->stopHandle(_moduleHandle);
}
void PaulaSound::fadeOutMusic() {
debugC(5, kCineDebugSound, "PaulaSound::fadeOutMusic()");
- // TODO
- stopMusic();
+ Common::StackLock lock(_musicMutex);
+
+ _musicFadeTimer = 1;
}
void PaulaSound::playSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat) {
- // TODO: handle volume slides and repeat
debugC(5, kCineDebugSound, "PaulaSound::playSound() channel %d size %d", channel, size);
+ Common::StackLock lock(_sfxMutex);
+ assert(frequency > 0);
+
stopSound(channel);
- size = MIN<int>(size - SPL_HDR_SIZE, READ_BE_UINT16(data + 4));
- // TODO: consider skipping the header in loadSpl directly
if (size > 0) {
byte *sound = (byte *)malloc(size);
if (sound) {
- memcpy(sound, data + SPL_HDR_SIZE, size);
- playSoundChannel(channel, frequency, sound, size, volume);
+ // Create the audio stream
+ memcpy(sound, data, size);
+
+ // Clear the first and last 16 bits like in the original.
+ sound[0] = sound[1] = sound[size - 2] = sound[size - 1] = 0;
+
+ Audio::SeekableAudioStream *stream = Audio::makeRawStream(sound, size, PAULA_FREQ / frequency, 0);
+
+ // Initialize the volume control
+ _channelsTable[channel].initialize(volume, volumeStep, stepCount);
+
+ // Start the sfx
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &_channelsTable[channel].handle,
+ Audio::makeLoopingAudioStream(stream, repeat ? 0 : 1),
+ -1, volume * Audio::Mixer::kMaxChannelVolume / 63,
+ _channelBalance[channel]);
}
}
}
void PaulaSound::stopSound(int channel) {
debugC(5, kCineDebugSound, "PaulaSound::stopSound() channel %d", channel);
- _mixer->stopHandle(_channelsTable[channel]);
+ Common::StackLock lock(_sfxMutex);
+
+ _mixer->stopHandle(_channelsTable[channel].handle);
}
-void PaulaSound::update() {
- // process volume slides and start sound playback
- // TODO
+void PaulaSound::sfxTimerProc(void *param) {
+ PaulaSound *sound = (PaulaSound *)param;
+ sound->sfxTimerCallback();
}
-void PaulaSound::playSoundChannel(int channel, int frequency, uint8 *data, int size, int volume) {
- assert(frequency > 0);
- frequency = PAULA_FREQ / frequency;
- Audio::AudioStream *stream = Audio::makeRawStream(data, size, frequency, 0);
- _mixer->playStream(Audio::Mixer::kSFXSoundType, &_channelsTable[channel], stream);
- _mixer->setChannelVolume(_channelsTable[channel], volume * Audio::Mixer::kMaxChannelVolume / 63);
+void PaulaSound::sfxTimerCallback() {
+ Common::StackLock lock(_sfxMutex);
+
+ if (_sfxTimer < 6) {
+ ++_sfxTimer;
+
+ for (int i = 0; i < NUM_CHANNELS; ++i) {
+ // Only process active channels
+ if (!_mixer->isSoundHandleActive(_channelsTable[i].handle)) {
+ continue;
+ }
+
+ if (_channelsTable[i].curStep) {
+ --_channelsTable[i].curStep;
+ } else {
+ _channelsTable[i].curStep = _channelsTable[i].stepCount;
+ const int volume = CLIP(_channelsTable[i].volume + _channelsTable[i].volumeStep, 0, 63);
+ _channelsTable[i].volume = volume;
+ // Unlike the original we stop silent sounds
+ if (volume) {
+ _mixer->setChannelVolume(_channelsTable[i].handle, volume * Audio::Mixer::kMaxChannelVolume / 63);
+ } else {
+ _mixer->stopHandle(_channelsTable[i].handle);
+ }
+ }
+ }
+ } else {
+ _sfxTimer = 0;
+ // Possible TODO: The original only ever started sounds here. This
+ // should not be noticable though. So we do not do it for now.
+ }
}
+void PaulaSound::musicTimerProc(void *param) {
+ PaulaSound *sound = (PaulaSound *)param;
+ sound->musicTimerCallback();
+}
+
+void PaulaSound::musicTimerCallback() {
+ Common::StackLock lock(_musicMutex);
+
+ ++_musicTimer;
+ if (_musicTimer == 6) {
+ _musicTimer = 0;
+ if (_musicFadeTimer) {
+ ++_musicFadeTimer;
+ if (_musicFadeTimer == 64) {
+ stopMusic();
+ } else {
+ if (_mixer->isSoundHandleActive(_moduleHandle)) {
+ _mixer->setChannelVolume(_moduleHandle, (64 - _musicFadeTimer) * Audio::Mixer::kMaxChannelVolume / 64);
+ }
+ }
+ }
+ }
+}
+
+const int PaulaSound::_channelBalance[NUM_CHANNELS] = {
+ // L/R/R/L This is according to the Hardware Reference Manual.
+ // TODO: It seems the order is swapped for some Amiga models:
+ // http://www.amiga.org/forums/archive/index.php/t-7862.html
+ // Maybe we should consider using R/L/L/R to match Amiga 500?
+ // This also is a bit more drastic to what WineUAE defaults,
+ // which is only 70% of full panning.
+ -127, 127, 127, -127
+};
+
} // End of namespace Cine
diff --git a/engines/cine/sound.h b/engines/cine/sound.h
index afc0994a26..fdb183ad34 100644
--- a/engines/cine/sound.h
+++ b/engines/cine/sound.h
@@ -24,6 +24,7 @@
#define CINE_SOUND_H_
#include "common/util.h"
+#include "common/mutex.h"
#include "audio/mixer.h"
namespace Audio {
@@ -47,7 +48,6 @@ public:
virtual void playSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat) = 0;
virtual void stopSound(int channel) = 0;
- virtual void update() {}
protected:
@@ -91,19 +91,39 @@ public:
virtual void playSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat);
virtual void stopSound(int channel);
- virtual void update();
enum {
- PAULA_FREQ = 7093789,
- NUM_CHANNELS = 4,
- SPL_HDR_SIZE = 22
+ PAULA_FREQ = 3579545,
+ NUM_CHANNELS = 4
};
protected:
- void playSoundChannel(int channel, int frequency, uint8 *data, int size, int volume);
-
- Audio::SoundHandle _channelsTable[NUM_CHANNELS];
+ struct SfxChannel {
+ Audio::SoundHandle handle;
+ int volume;
+ int volumeStep;
+ int curStep;
+ int stepCount;
+
+ void initialize(int vol, int volStep, int stepCnt) {
+ volume = vol;
+ volumeStep = volStep;
+ curStep = stepCount = stepCnt;
+ }
+ };
+ SfxChannel _channelsTable[NUM_CHANNELS];
+ static const int _channelBalance[NUM_CHANNELS];
+ Common::Mutex _sfxMutex;
+ int _sfxTimer;
+ static void sfxTimerProc(void *param);
+ void sfxTimerCallback();
+
+ Common::Mutex _musicMutex;
+ int _musicTimer;
+ int _musicFadeTimer;
+ static void musicTimerProc(void *param);
+ void musicTimerCallback();
Audio::SoundHandle _moduleHandle;
Audio::AudioStream *_moduleStream;
};
diff --git a/engines/cine/texte.cpp b/engines/cine/texte.cpp
index 33ea569df7..998075c6ce 100644
--- a/engines/cine/texte.cpp
+++ b/engines/cine/texte.cpp
@@ -88,7 +88,7 @@ static const CharacterEntry fontParamTable_standard[NUM_FONT_CHARS] = {
{64, 3}, {65, 3}, { 0, 0}, { 0, 0}, {62, 2}, {74, 6}, {66, 1}, {67, 6},
{52, 6}, {53, 6}, {54, 6}, {55, 6}, {56, 6}, {57, 6}, {58, 6}, {59, 6},
{60, 6}, {61, 6}, {76, 3}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {75, 6},
- { 0, 0}, { 0, 6}, //a
+ { 0, 0}, { 0, 6}, //a
{ 1, 6}, { 2, 6}, { 3, 6}, { 4, 6}, { 5, 6}, { 6, 6},
{ 7, 6}, { 8, 3}, { 9, 6}, {10, 6}, {11, 6}, {12, 7}, {13, 6}, {14, 6},
{15, 6}, {16, 6}, {17, 6}, {18, 6}, {19, 6}, {20, 6}, {21, 6}, {22, 7},
diff --git a/engines/cine/texte.h b/engines/cine/texte.h
index dd4b7e06ee..185dc53bfd 100644
--- a/engines/cine/texte.h
+++ b/engines/cine/texte.h
@@ -46,7 +46,7 @@ struct CharacterEntry {
};
struct TextHandler {
- byte textTable[NUM_FONT_CHARS][2][FONT_WIDTH * FONT_HEIGHT];
+ byte textTable[NUM_FONT_CHARS][2][FONT_WIDTH *FONT_HEIGHT];
CharacterEntry fontParamTable[NUM_FONT_CHARS];
};
diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp
index eccd71cf05..23f439a7a7 100644
--- a/engines/cine/various.cpp
+++ b/engines/cine/various.cpp
@@ -99,8 +99,7 @@ byte isInPause = 0;
* Bit on = mouse button down
* Bit off = mouse button up
*/
-enum MouseButtonState
-{
+enum MouseButtonState {
kLeftMouseButton = (1 << 0),
kRightMouseButton = (1 << 1)
};
@@ -271,7 +270,7 @@ int16 getObjectUnderCursor(uint16 x, uint16 y) {
} else if (it->type == 1 && gfxGetBit(xdif, ydif, g_cine->_animDataTable[frame].data(), g_cine->_animDataTable[frame]._width * 4)) {
return it->objIdx;
}
- } else if (it->type == 0) { // use generated mask
+ } else if (it->type == 0) { // use generated mask
if (gfxGetBit(xdif, ydif, g_cine->_animDataTable[frame].mask(), g_cine->_animDataTable[frame]._width)) {
return it->objIdx;
}
@@ -358,128 +357,122 @@ void CineEngine::makeSystemMenu() {
systemCommand = makeMenuChoice(systemMenu, numEntry, mouseX, mouseY, 140);
switch (systemCommand) {
- case 0: // Pause
- {
- renderer->drawString(otherMessages[2], 0);
- waitPlayerInput();
- break;
- }
- case 1: // Restart Game
- {
- getMouseData(mouseUpdateStatus, (uint16 *)&mouseButton, (uint16 *)&mouseX, (uint16 *)&mouseY);
- if (!makeMenuChoice(confirmMenu, 2, mouseX, mouseY + 8, 100)) {
- _restartRequested = true;
- }
- break;
- }
- case 2: // Quit
- {
- getMouseData(mouseUpdateStatus, (uint16 *)&mouseButton, (uint16 *)&mouseX, (uint16 *)&mouseY);
- if (!makeMenuChoice(confirmMenu, 2, mouseX, mouseY + 8, 100)) {
- quitGame();
- }
- break;
+ case 0: { // Pause
+ renderer->drawString(otherMessages[2], 0);
+ waitPlayerInput();
+ break;
+ }
+ case 1: { // Restart Game
+ getMouseData(mouseUpdateStatus, (uint16 *)&mouseButton, (uint16 *)&mouseX, (uint16 *)&mouseY);
+ if (!makeMenuChoice(confirmMenu, 2, mouseX, mouseY + 8, 100)) {
+ _restartRequested = true;
}
- case 3: // Select save drive... change ?
- {
- break;
+ break;
+ }
+ case 2: { // Quit
+ getMouseData(mouseUpdateStatus, (uint16 *)&mouseButton, (uint16 *)&mouseX, (uint16 *)&mouseY);
+ if (!makeMenuChoice(confirmMenu, 2, mouseX, mouseY + 8, 100)) {
+ quitGame();
}
- case 4: // load game
- {
- if (loadSaveDirectory()) {
+ break;
+ }
+ case 3: { // Select save drive... change ?
+ break;
+ }
+ case 4: { // load game
+ if (loadSaveDirectory()) {
// int16 selectedSave;
- getMouseData(mouseUpdateStatus, (uint16 *)&mouseButton, (uint16 *)&mouseX, (uint16 *)&mouseY);
- selectedSave = makeMenuChoice(currentSaveName, 10, mouseX, mouseY + 8, 180);
+ getMouseData(mouseUpdateStatus, (uint16 *)&mouseButton, (uint16 *)&mouseX, (uint16 *)&mouseY);
+ selectedSave = makeMenuChoice(currentSaveName, 10, mouseX, mouseY + 8, 180);
- if (selectedSave >= 0) {
- char saveNameBuffer[256];
- sprintf(saveNameBuffer, "%s.%1d", _targetName.c_str(), selectedSave);
+ if (selectedSave >= 0) {
+ char saveNameBuffer[256];
+ sprintf(saveNameBuffer, "%s.%1d", _targetName.c_str(), selectedSave);
- getMouseData(mouseUpdateStatus, (uint16 *)&mouseButton, (uint16 *)&mouseX, (uint16 *)&mouseY);
- if (!makeMenuChoice(confirmMenu, 2, mouseX, mouseY + 8, 100)) {
- char loadString[256];
+ getMouseData(mouseUpdateStatus, (uint16 *)&mouseButton, (uint16 *)&mouseX, (uint16 *)&mouseY);
+ if (!makeMenuChoice(confirmMenu, 2, mouseX, mouseY + 8, 100)) {
+ char loadString[256];
- sprintf(loadString, otherMessages[3], currentSaveName[selectedSave]);
- renderer->drawString(loadString, 0);
+ sprintf(loadString, otherMessages[3], currentSaveName[selectedSave]);
+ renderer->drawString(loadString, 0);
- makeLoad(saveNameBuffer);
- } else {
- renderer->drawString(otherMessages[4], 0);
- waitPlayerInput();
- checkDataDisk(-1);
- }
+ makeLoad(saveNameBuffer);
} else {
renderer->drawString(otherMessages[4], 0);
waitPlayerInput();
checkDataDisk(-1);
}
} else {
- renderer->drawString(otherMessages[5], 0);
+ renderer->drawString(otherMessages[4], 0);
waitPlayerInput();
checkDataDisk(-1);
}
- break;
+ } else {
+ renderer->drawString(otherMessages[5], 0);
+ waitPlayerInput();
+ checkDataDisk(-1);
}
- case 5: // Save game
- {
- loadSaveDirectory();
- selectedSave = makeMenuChoice(currentSaveName, 10, mouseX, mouseY + 8, 180);
+ break;
+ }
+ case 5: { // Save game
+ loadSaveDirectory();
+ selectedSave = makeMenuChoice(currentSaveName, 10, mouseX, mouseY + 8, 180);
- if (selectedSave >= 0) {
- char saveFileName[256];
- char saveName[20];
- saveName[0] = 0;
+ if (selectedSave >= 0) {
+ char saveFileName[256];
+ char saveName[20];
+ saveName[0] = 0;
- if (!makeTextEntryMenu(otherMessages[6], saveName, 20, 120))
- break;
+ if (!makeTextEntryMenu(otherMessages[6], saveName, 20, 120))
+ break;
- strncpy(currentSaveName[selectedSave], saveName, 20);
+ strncpy(currentSaveName[selectedSave], saveName, 20);
- sprintf(saveFileName, "%s.%1d", _targetName.c_str(), selectedSave);
+ sprintf(saveFileName, "%s.%1d", _targetName.c_str(), selectedSave);
- getMouseData(mouseUpdateStatus, (uint16 *)&mouseButton, (uint16 *)&mouseX, (uint16 *)&mouseY);
- if (!makeMenuChoice(confirmMenu, 2, mouseX, mouseY + 8, 100)) {
- char saveString[256];
- Common::String tmp = Common::String::format("%s.dir", _targetName.c_str());
+ getMouseData(mouseUpdateStatus, (uint16 *)&mouseButton, (uint16 *)&mouseX, (uint16 *)&mouseY);
+ if (!makeMenuChoice(confirmMenu, 2, mouseX, mouseY + 8, 100)) {
+ char saveString[256];
+ Common::String tmp = Common::String::format("%s.dir", _targetName.c_str());
- Common::OutSaveFile *fHandle = _saveFileMan->openForSaving(tmp);
- if (!fHandle) {
- warning("Unable to open file %s for saving", tmp.c_str());
- break;
- }
+ Common::OutSaveFile *fHandle = _saveFileMan->openForSaving(tmp);
+ if (!fHandle) {
+ warning("Unable to open file %s for saving", tmp.c_str());
+ break;
+ }
- fHandle->write(currentSaveName, 200);
- delete fHandle;
+ fHandle->write(currentSaveName, 200);
+ delete fHandle;
- sprintf(saveString, otherMessages[3], currentSaveName[selectedSave]);
- renderer->drawString(saveString, 0);
+ sprintf(saveString, otherMessages[3], currentSaveName[selectedSave]);
+ renderer->drawString(saveString, 0);
- makeSave(saveFileName);
+ makeSave(saveFileName);
- checkDataDisk(-1);
- } else {
- renderer->drawString(otherMessages[4], 0);
- waitPlayerInput();
- checkDataDisk(-1);
- }
+ checkDataDisk(-1);
+ } else {
+ renderer->drawString(otherMessages[4], 0);
+ waitPlayerInput();
+ checkDataDisk(-1);
}
- break;
}
+ break;
+ }
}
inMenu = false;
}
}
-void drawMessageBox(int16 x, int16 y, int16 width, int16 currentY, int16 offset, int16 color, byte* page) {
- gfxDrawLine(x + offset, y + offset, x + width - offset, y + offset, color, page); // top
- gfxDrawLine(x + offset, currentY + 4 - offset, x + width - offset, currentY + 4 - offset, color, page); // bottom
- gfxDrawLine(x + offset, y + offset, x + offset, currentY + 4 - offset, color, page); // left
- gfxDrawLine(x + width - offset, y + offset, x + width - offset, currentY + 4 - offset, color, page); // right
+void drawMessageBox(int16 x, int16 y, int16 width, int16 currentY, int16 offset, int16 color, byte *page) {
+ gfxDrawLine(x + offset, y + offset, x + width - offset, y + offset, color, page); // top
+ gfxDrawLine(x + offset, currentY + 4 - offset, x + width - offset, currentY + 4 - offset, color, page); // bottom
+ gfxDrawLine(x + offset, y + offset, x + offset, currentY + 4 - offset, color, page); // left
+ gfxDrawLine(x + width - offset, y + offset, x + width - offset, currentY + 4 - offset, color, page); // right
}
-void drawDoubleMessageBox(int16 x, int16 y, int16 width, int16 currentY, int16 color, byte* page) {
+void drawDoubleMessageBox(int16 x, int16 y, int16 width, int16 currentY, int16 color, byte *page) {
drawMessageBox(x, y, width, currentY, 1, 0, page);
drawMessageBox(x, y, width, currentY, 0, color, page);
}
@@ -581,7 +574,7 @@ void makeCommandLine() {
g_cine->_commandBuffer = "";
}
- if ((playerCommand != -1) && (choiceResultTable[playerCommand] == 2)) { // need object selection ?
+ if ((playerCommand != -1) && (choiceResultTable[playerCommand] == 2)) { // need object selection?
int16 si;
getMouseData(mouseUpdateStatus, &dummyU16, &x, &y);
@@ -635,7 +628,7 @@ void makeCommandLine() {
}
if (g_cine->getGameType() == Cine::GType_OS && playerCommand != 2) {
- if (playerCommand != -1 && canUseOnObject != 0) { // call use on sub object
+ if (playerCommand != -1 && canUseOnObject != 0) { // call use on sub object
int16 si;
getMouseData(mouseUpdateStatus, &dummyU16, &x, &y);
@@ -742,11 +735,11 @@ int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X,
mainLoopSub6();
}
- if (menuVar4 && currentSelection > 0) { // go up
+ if (menuVar4 && currentSelection > 0) { // go up
currentSelection--;
}
- if (menuVar5) { // go down
+ if (menuVar5) { // go down
if (height - 1 > currentSelection) {
currentSelection++;
}
@@ -763,7 +756,7 @@ int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X,
}
}
- if (currentSelection != oldSelection) { // old != new
+ if (currentSelection != oldSelection) { // old != new
if (needMouseSave) {
hideMouse();
}
@@ -789,7 +782,7 @@ int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X,
getMouseData(mouseUpdateStatus, &button, &dummyU16, &dummyU16);
} while (button && !g_cine->shouldQuit());
- if (var_4 == 2) { // recheck
+ if (var_4 == 2) { // recheck
if (!recheckValue)
return -1;
else
@@ -809,7 +802,7 @@ void makeActionMenu() {
getMouseData(mouseUpdateStatus, &mouseButton, &mouseX, &mouseY);
if (g_cine->getGameType() == Cine::GType_OS) {
- if(disableSystemMenu == 0) {
+ if (disableSystemMenu == 0) {
playerCommand = makeMenuChoice(defaultActionCommand, 6, mouseX, mouseY, 70, true);
}
@@ -818,7 +811,7 @@ void makeActionMenu() {
canUseOnObject = canUseOnItemTable[playerCommand];
}
} else {
- if(disableSystemMenu == 0) {
+ if (disableSystemMenu == 0) {
playerCommand = makeMenuChoice(defaultActionCommand, 6, mouseX, mouseY, 70);
}
}
@@ -1185,7 +1178,7 @@ void removeMessages() {
Common::List<overlay>::iterator it;
bool remove;
- for (it = g_cine->_overlayList.begin(); it != g_cine->_overlayList.end(); ) {
+ for (it = g_cine->_overlayList.begin(); it != g_cine->_overlayList.end();) {
if (g_cine->getGameType() == Cine::GType_OS) {
// NOTE: These are really removeOverlay calls that have been deferred.
// In Operation Stealth's disassembly elements are removed from the
@@ -1348,7 +1341,7 @@ void modifySeqListElement(uint16 objIdx, int16 var4Test, int16 param1, int16 par
}
void computeMove1(SeqListElement &element, int16 x, int16 y, int16 param1,
- int16 param2, int16 x2, int16 y2) {
+ int16 param2, int16 x2, int16 y2) {
element.var16 = 0;
element.var14 = 0;
@@ -1397,7 +1390,7 @@ uint16 addAni(uint16 param1, uint16 objIdx, const int8 *ptr, SeqListElement &ele
int16 di;
debug(5, "addAni: param1 = %d, objIdx = %d, ptr = %p, element.var8 = %d, element.var14 = %d param3 = %d",
- param1, objIdx, ptr, element.var8, element.var14, param3);
+ param1, objIdx, ptr, element.var8, element.var14, param3);
// In the original an error string is set and 0 is returned if the following doesn't hold
assert(ptr);
@@ -1413,16 +1406,16 @@ uint16 addAni(uint16 param1, uint16 objIdx, const int8 *ptr, SeqListElement &ele
di = (g_cine->_objectTable[objIdx].costume + 1) % (*ptrData);
++ptrData; // Jump over the just read byte
// Here ptr2 seems to be indexing a table of structs (8 bytes per struct):
- // struct {
- // int8 x; // 0 (Used with checkCollision)
- // int8 y; // 1 (Used with checkCollision)
- // int8 numZones; // 2 (Used with checkCollision)
- // int8 var3; // 3 (Not used in this function)
- // int8 xAdd; // 4 (Used with an object)
- // int8 yAdd; // 5 (Used with an object)
- // int8 maskAdd; // 6 (Used with an object)
- // int8 frameAdd; // 7 (Used with an object)
- // };
+ // struct {
+ // int8 x; // 0 (Used with checkCollision)
+ // int8 y; // 1 (Used with checkCollision)
+ // int8 numZones; // 2 (Used with checkCollision)
+ // int8 var3; // 3 (Not used in this function)
+ // int8 xAdd; // 4 (Used with an object)
+ // int8 yAdd; // 5 (Used with an object)
+ // int8 maskAdd; // 6 (Used with an object)
+ // int8 frameAdd; // 7 (Used with an object)
+ // };
ptr2 = ptrData + di * 8;
// We might probably safely discard the AND by 1 here because
@@ -1572,8 +1565,7 @@ void processSeqListElement(SeqListElement &element) {
var_4 = -1;
if ((element.var16 == 1
- && !addAni(3, element.objIdx, ptr1, element, 0, &var_4)) || (element.var16 == 2 && !addAni(2, element.objIdx, ptr1, element, 0,
- &var_4))) {
+ && !addAni(3, element.objIdx, ptr1, element, 0, &var_4)) || (element.var16 == 2 && !addAni(2, element.objIdx, ptr1, element, 0, &var_4))) {
if (element.varC == 255) {
g_cine->_globalVars[VAR_MOUSE_Y_POS] = 0;
}
@@ -1702,9 +1694,9 @@ bool makeTextEntryMenu(const char *messagePtr, char *inputString, int stringMaxL
}
break;
default:
- if (((keycode >= 'a') && (keycode <='z')) ||
- ((keycode >= '0') && (keycode <='9')) ||
- ((keycode >= 'A') && (keycode <='Z')) ||
+ if (((keycode >= 'a') && (keycode <= 'z')) ||
+ ((keycode >= '0') && (keycode <= '9')) ||
+ ((keycode >= 'A') && (keycode <= 'Z')) ||
(keycode == ' ')) {
if (inputLength < stringMaxLength - 1) {
ch[0] = keycode;
diff --git a/engines/composer/composer.cpp b/engines/composer/composer.cpp
index 23a9d2ff85..5db778dfda 100644
--- a/engines/composer/composer.cpp
+++ b/engines/composer/composer.cpp
@@ -20,7 +20,7 @@
*
*/
#include "common/scummsys.h"
-
+
#include "common/config-manager.h"
#include "common/events.h"
#include "common/file.h"
@@ -102,13 +102,14 @@ Common::Error ComposerEngine::run() {
if (_bookIni.hasKey("Height", "Common"))
height = atoi(getStringFromConfig("Common", "Height").c_str());
initGraphics(width, height, true);
- _surface.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+ _screen.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
_needsUpdate = true;
Graphics::Cursor *cursor = Graphics::makeDefaultWinCursor();
CursorMan.replaceCursor(cursor->getSurface(), cursor->getWidth(), cursor->getHeight(), cursor->getHotspotX(),
cursor->getHotspotY(), cursor->getKeyColor());
CursorMan.replaceCursorPalette(cursor->getPalette(), cursor->getPaletteStartIndex(), cursor->getPaletteCount());
+ delete cursor;
loadLibrary(0);
@@ -213,6 +214,8 @@ Common::Error ComposerEngine::run() {
_system->delayMillis(20);
}
+ _screen.free();
+
return Common::kNoError;
}
diff --git a/engines/composer/composer.h b/engines/composer/composer.h
index 0f53258289..33a5356b3a 100644
--- a/engines/composer/composer.h
+++ b/engines/composer/composer.h
@@ -170,7 +170,7 @@ private:
bool _needsUpdate;
Common::Array<Common::Rect> _dirtyRects;
- Graphics::Surface _surface;
+ Graphics::Surface _screen;
Common::List<Sprite> _sprites;
uint _directoriesToStrip;
diff --git a/engines/composer/graphics.cpp b/engines/composer/graphics.cpp
index 1314e903ae..2b68fac233 100644
--- a/engines/composer/graphics.cpp
+++ b/engines/composer/graphics.cpp
@@ -507,7 +507,7 @@ const Sprite *ComposerEngine::getSpriteAtPos(const Common::Point &pos) {
void ComposerEngine::dirtySprite(const Sprite &sprite) {
Common::Rect rect(sprite._pos.x, sprite._pos.y, sprite._pos.x + sprite._surface.w, sprite._pos.y + sprite._surface.h);
- rect.clip(_surface.w, _surface.h);
+ rect.clip(_screen.w, _screen.h);
if (rect.isEmpty())
return;
@@ -541,8 +541,8 @@ void ComposerEngine::redraw() {
for (uint i = 0; i < _dirtyRects.size(); i++) {
const Common::Rect &rect = _dirtyRects[i];
- byte *pixels = (byte *)_surface.pixels + (rect.top * _surface.pitch) + rect.left;
- _system->copyRectToScreen(pixels, _surface.pitch, rect.left, rect.top, rect.width(), rect.height());
+ byte *pixels = (byte *)_screen.pixels + (rect.top * _screen.pitch) + rect.left;
+ _system->copyRectToScreen(pixels, _screen.pitch, rect.left, rect.top, rect.width(), rect.height());
}
_system->updateScreen();
@@ -814,16 +814,16 @@ void ComposerEngine::drawSprite(const Sprite &sprite) {
int y = sprite._pos.y;
// incoming data is BMP-style (bottom-up), so flip it
- byte *pixels = (byte *)_surface.pixels;
+ byte *pixels = (byte *)_screen.pixels;
for (int j = 0; j < sprite._surface.h; j++) {
if (j + y < 0)
continue;
- if (j + y >= _surface.h)
+ if (j + y >= _screen.h)
break;
byte *in = (byte *)sprite._surface.pixels + (sprite._surface.h - j - 1) * sprite._surface.w;
- byte *out = pixels + ((j + y) * _surface.w) + x;
+ byte *out = pixels + ((j + y) * _screen.w) + x;
for (int i = 0; i < sprite._surface.w; i++)
- if ((x + i >= 0) && (x + i < _surface.w) && in[i])
+ if ((x + i >= 0) && (x + i < _screen.w) && in[i])
out[i] = in[i];
}
}
diff --git a/engines/composer/resource.cpp b/engines/composer/resource.cpp
index a4e292747c..83e49971fb 100644
--- a/engines/composer/resource.cpp
+++ b/engines/composer/resource.cpp
@@ -240,7 +240,7 @@ bool ComposerArchive::openStream(Common::SeekableReadStream *stream) {
res.flags = flags;
debug(4, "Id %d, offset %d, size %d, flags %08x", id, offset, size, flags);
}
-
+
stream->seek(oldPos);
}
diff --git a/engines/configure.engines b/engines/configure.engines
index e0052c52ee..e17e2f67e0 100644
--- a/engines/configure.engines
+++ b/engines/configure.engines
@@ -1,9 +1,10 @@
# This file is included from the main "configure" script
-add_engine scumm "SCUMM" yes "scumm_7_8 he"
+# 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"
+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
@@ -13,38 +14,39 @@ 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"
+add_engine groovie "Groovie" yes "groovie2" "7th Guest"
add_engine groovie2 "Groovie 2 games" no
add_engine hopkins "Hopkins FBI" no
add_engine hugo "Hugo Trilogy" yes
-add_engine kyra "Legend of Kyrandia" yes "lol eob"
+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" no
-add_engine lastexpress "The Last Express" no
+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"
+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
-add_engine myst "Myst" no
+add_engine riven "Riven: The Sequel to Myst" no "" "" "16bit"
+add_engine myst "Myst" no "" "" "16bit"
add_engine parallaction "Parallaction" yes
+add_engine pegasus "The Journeyman Project: Pegasus Prime" no "" "" "16bit"
add_engine queen "Flight of the Amazon Queen" yes
-add_engine saga "SAGA" yes "ihnm saga2"
+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"
+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"
+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" no
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" no
+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 wintermute "Wintermute" no "" "png zlib vorbis"
+add_engine wintermute "Wintermute" no "" "" "png zlib vorbis 16bit"
diff --git a/engines/cruise/detection.cpp b/engines/cruise/detection.cpp
index cbe17ea4d3..ba79df4822 100644
--- a/engines/cruise/detection.cpp
+++ b/engines/cruise/detection.cpp
@@ -295,7 +295,7 @@ void CruiseMetaEngine::removeSaveState(const char *target, int slot) const {
SaveStateDescriptor CruiseMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(
Cruise::CruiseEngine::getSavegameFile(slot));
-
+
if (f) {
Cruise::CruiseSavegameHeader header;
Cruise::readSavegameHeader(f, header);
diff --git a/engines/dialogs.cpp b/engines/dialogs.cpp
index cf3dfaa44b..c884075093 100644
--- a/engines/dialogs.cpp
+++ b/engines/dialogs.cpp
@@ -229,7 +229,7 @@ void MainMenuDialog::save() {
"Please consult the README for basic information, and for "
"instructions on how to obtain further assistance."), status.getDesc().c_str());
GUI::MessageDialog dialog(failMessage);
- dialog.runModal();
+ dialog.runModal();
}
close();
diff --git a/engines/draci/detection.cpp b/engines/draci/detection.cpp
index 61705a1e59..2d78d05933 100644
--- a/engines/draci/detection.cpp
+++ b/engines/draci/detection.cpp
@@ -153,7 +153,7 @@ void DraciMetaEngine::removeSaveState(const char *target, int slot) const {
SaveStateDescriptor DraciMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(
Draci::DraciEngine::getSavegameFile(slot));
-
+
if (f) {
Draci::DraciSavegameHeader header;
Draci::readSavegameHeader(f, header);
diff --git a/engines/drascula/detection.cpp b/engines/drascula/detection.cpp
index 6e38d49b94..760d8b7d98 100644
--- a/engines/drascula/detection.cpp
+++ b/engines/drascula/detection.cpp
@@ -284,7 +284,7 @@ public:
Common::StringArray filenames = saveFileMan->listSavefiles(pattern);
Common::Array<int> slots;
for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
-
+
// Obtain the last 2 digits of the filename, since they correspond to the save slot
int slotNum = atoi(file->c_str() + file->size() - 2);
@@ -299,7 +299,7 @@ public:
// Load save index
Common::String fileEpa = Common::String::format("%s.epa", target);
- Common::InSaveFile *epa = saveFileMan->openForLoading(fileEpa);
+ Common::InSaveFile *epa = saveFileMan->openForLoading(fileEpa);
// Get savegame names from index
Common::String saveDesc;
@@ -307,19 +307,19 @@ public:
int line = 1;
for (size_t i = 0; i < slots.size(); i++) {
// ignore lines corresponding to unused saveslots
- for (; line < slots[i]; line++)
- epa->readLine();
+ for (; line < slots[i]; line++)
+ epa->readLine();
// copy the name in the line corresponding to the save slot and truncate to 22 characters
saveDesc = Common::String(epa->readLine().c_str(), 22);
// handle cases where the save directory and save index are detectably out of sync
- if (saveDesc == "*")
+ if (saveDesc == "*")
saveDesc = "No name specified.";
// increment line number to keep it in sync with slot number
- line++;
-
+ line++;
+
// Insert savegame name into list
saveList.push_back(SaveStateDescriptor(slots[i], saveDesc));
}
diff --git a/engines/dreamweb/dreamweb.cpp b/engines/dreamweb/dreamweb.cpp
index 0ca98d5a7b..5f5d627553 100644
--- a/engines/dreamweb/dreamweb.cpp
+++ b/engines/dreamweb/dreamweb.cpp
@@ -516,7 +516,7 @@ uint8 DreamWebEngine::modifyChar(uint8 c) const {
case Common::IT_ITA:
switch(c) {
case 133:
- return 'Z' + 1;
+ return 'Z' + 1;
case 130:
return 'Z' + 2;
case 138:
@@ -548,10 +548,10 @@ uint8 DreamWebEngine::modifyChar(uint8 c) const {
return c;
}
}
-
+
Common::String DreamWebEngine::modifyFileName(const char *name) {
Common::String fileName(name);
-
+
// Sanity check
if (!fileName.hasPrefix("DREAMWEB."))
return fileName;
diff --git a/engines/dreamweb/dreamweb.h b/engines/dreamweb/dreamweb.h
index 1f6deb8566..a4597b1867 100644
--- a/engines/dreamweb/dreamweb.h
+++ b/engines/dreamweb/dreamweb.h
@@ -196,7 +196,7 @@ protected:
// from monitor.cpp
char _inputLine[64];
- char _operand1[14];
+ char _operand1[64];
char _currentFile[14];
// from newplace.cpp
diff --git a/engines/dreamweb/monitor.cpp b/engines/dreamweb/monitor.cpp
index 4e9d8eecc1..1886a80b6a 100644
--- a/engines/dreamweb/monitor.cpp
+++ b/engines/dreamweb/monitor.cpp
@@ -194,7 +194,7 @@ void DreamWebEngine::printLogo() {
}
void DreamWebEngine::input() {
- memset(_inputLine, 0, 64);
+ memset(_inputLine, 0, sizeof(_inputLine));
_curPos = 0;
printChar(_monitorCharset, _monAdX, _monAdY, '>', 0, NULL, NULL);
multiDump(_monAdX, _monAdY, 6, 8);
@@ -665,7 +665,7 @@ void DreamWebEngine::searchForFiles(const char *filesString) {
const char *DreamWebEngine::parser() {
char *output = _operand1;
- memset(output, 0, 14);
+ memset(output, 0, sizeof(_operand1));
*output++ = '=';
diff --git a/engines/dreamweb/object.cpp b/engines/dreamweb/object.cpp
index b42591ef91..1e84aba6bd 100644
--- a/engines/dreamweb/object.cpp
+++ b/engines/dreamweb/object.cpp
@@ -516,7 +516,7 @@ void DreamWebEngine::inToInv() {
if (_mouseButton == _oldButton || !(_mouseButton & 1))
return; // notletgo2
-
+
delPointer();
DynObject *object = getExAd(_itemFrame);
object->mapad[0] = 4;
@@ -1034,7 +1034,7 @@ void DreamWebEngine::fillOpen() {
size = 4;
findAllOpen();
for (uint8 i = 0; i < size; ++i) {
- uint8 index = _openInvList[i]._index;
+ uint8 index = _openInvList[i]._index;
uint8 type = _openInvList[i]._type;
obToInv(index, type, kInventx + i * kItempicsize, kInventy + 96);
}
diff --git a/engines/dreamweb/people.cpp b/engines/dreamweb/people.cpp
index 36a756a49b..dbb81406cd 100644
--- a/engines/dreamweb/people.cpp
+++ b/engines/dreamweb/people.cpp
@@ -411,7 +411,7 @@ void DreamWebEngine::interviewer(ReelRoutine &routine) {
if (routine.reelPointer() != 250 && routine.reelPointer() != 259 && checkSpeed(routine))
routine.incReelPointer();
-
+
showGameReel(&routine);
}
@@ -745,7 +745,7 @@ void DreamWebEngine::introMonks2(ReelRoutine &routine) {
if (nextReelPointer == 110) {
_introCount++;
monks2text();
-
+
if (_introCount == 35)
nextReelPointer = 111;
else
@@ -895,7 +895,7 @@ void DreamWebEngine::helicopter(ReelRoutine &routine) {
nextReelPointer = 9;
}
}
- }
+ }
routine.setReelPointer(nextReelPointer);
}
@@ -1002,7 +1002,7 @@ void DreamWebEngine::businessMan(ReelRoutine &routine) {
nextReelPointer = 92;
}
}
-
+
routine.setReelPointer(nextReelPointer);
}
@@ -1037,7 +1037,7 @@ void DreamWebEngine::endGameSeq(ReelRoutine &routine) {
showGameReel(&routine);
routine.mapY = _mapY;
-
+
if (routine.reelPointer() == 145) {
routine.setReelPointer(146);
rollEndCreditsGameWon();
@@ -1070,7 +1070,7 @@ void DreamWebEngine::poolGuard(ReelRoutine &routine) {
if (checkSpeed(routine)) {
uint16 nextReelPointer = routine.reelPointer() + 1;
-
+
if (nextReelPointer != 122) {
// Not end guard 1
if (nextReelPointer == 147) {
@@ -1103,12 +1103,12 @@ void DreamWebEngine::poolGuard(ReelRoutine &routine) {
}
}
}
-
+
routine.setReelPointer(nextReelPointer);
}
showGameReel(&routine);
-
+
if (routine.reelPointer() != 121 && routine.reelPointer() != 146) {
_pointerMode = 0;
_vars._watchingTime = 2;
diff --git a/engines/dreamweb/print.cpp b/engines/dreamweb/print.cpp
index 3a2c45e07b..64b9849980 100644
--- a/engines/dreamweb/print.cpp
+++ b/engines/dreamweb/print.cpp
@@ -212,7 +212,7 @@ const char *DreamWebEngine::monPrint(const char *string) {
while (!done) {
uint16 count = getNumber(_monitorCharset, (const uint8 *)iterator, 166, false, &x);
- do {
+ do {
char c = *iterator++;
if (c == ':')
break;
diff --git a/engines/dreamweb/sprite.cpp b/engines/dreamweb/sprite.cpp
index 5b6cf6a6ac..01570c907a 100644
--- a/engines/dreamweb/sprite.cpp
+++ b/engines/dreamweb/sprite.cpp
@@ -52,7 +52,7 @@ void DreamWebEngine::printASprite(const Sprite *sprite) {
} else {
x = sprite->x + _mapAdX;
}
-
+
uint8 c;
if (sprite->walkFrame != 0)
c = 8;
@@ -97,7 +97,7 @@ void DreamWebEngine::spriteUpdate() {
else {
backObject(&sprite);
}
-
+
if (_nowInNewRoom == 1)
break;
}
@@ -373,7 +373,7 @@ void DreamWebEngine::lockedDoorway(Sprite *sprite, SetObject *objData) {
if (sprite->animFrame != 0)
--sprite->animFrame;
-
+
_vars._throughDoor = 0;
sprite->frameNumber = objData->index = objData->frames[sprite->animFrame];
@@ -407,7 +407,7 @@ void DreamWebEngine::liftSprite(Sprite *sprite, SetObject *objData) {
}
sprite->animFrame = 12;
sprite->frameNumber = objData->index = objData->frames[sprite->animFrame];
- }
+ }
else if (liftFlag == 3) { //openlift
if (sprite->animFrame == 12) {
_vars._liftFlag = 1;
@@ -672,7 +672,7 @@ static const ReelSound g_roomSound6[] = {
{ 255,0 }
};
static const ReelSound g_roomSound8[] = {
-
+
{ 12, 51 },
{ 13, 53 },
{ 14, 14 },
@@ -691,7 +691,7 @@ static const ReelSound g_roomSound10[] = {
{ 13, 16 },
{ 255,0 }
};
-
+
static const ReelSound g_roomSound11[] = {
{ 13, 20 },
{ 255,0 }
@@ -779,7 +779,7 @@ static const ReelSound g_roomSound26[] = {
{ 15, 102 }, // was 90, should be mine cart
{ 255,0 }
};
-
+
static const ReelSound g_roomSound27[] = {
{ 22, 36 },
{ 13, 125 },
diff --git a/engines/dreamweb/vgagrafx.cpp b/engines/dreamweb/vgagrafx.cpp
index ec306c4924..d2390fb1fd 100644
--- a/engines/dreamweb/vgagrafx.cpp
+++ b/engines/dreamweb/vgagrafx.cpp
@@ -23,6 +23,7 @@
#include "dreamweb/dreamweb.h"
#include "engines/util.h"
#include "graphics/surface.h"
+#include "graphics/decoders/pcx.h"
namespace DreamWeb {
@@ -152,70 +153,33 @@ void DreamWebEngine::setMode() {
void DreamWebEngine::showPCX(const Common::String &suffix) {
Common::String name = getDatafilePrefix() + suffix;
Common::File pcxFile;
-
if (!pcxFile.open(name)) {
warning("showpcx: Could not open '%s'", name.c_str());
return;
}
- uint8 *mainGamePal;
- int i, j;
+ Graphics::PCXDecoder pcx;
+ if (!pcx.loadStream(pcxFile)) {
+ warning("showpcx: Could not process '%s'", name.c_str());
+ return;
+ }
// Read the 16-color palette into the 'maingamepal' buffer. Note that
// the color components have to be adjusted from 8 to 6 bits.
-
- pcxFile.seek(16, SEEK_SET);
- mainGamePal = _mainPal;
- pcxFile.read(mainGamePal, 48);
-
- memset(mainGamePal + 48, 0xff, 720);
- for (i = 0; i < 48; i++) {
- mainGamePal[i] >>= 2;
+ memset(_mainPal, 0xff, 256 * 3);
+ memcpy(_mainPal, pcx.getPalette(), 48);
+ for (int i = 0; i < 48; i++) {
+ _mainPal[i] >>= 2;
}
- // Decode the image data.
-
Graphics::Surface *s = g_system->lockScreen();
- Common::Rect rect(640, 480);
-
- s->fillRect(rect, 0);
- pcxFile.seek(128, SEEK_SET);
-
- for (int y = 0; y < 480; y++) {
- byte *dst = (byte *)s->getBasePtr(0, y);
- int decoded = 0;
-
- while (decoded < 320) {
- byte col = pcxFile.readByte();
- byte len;
-
- if ((col & 0xc0) == 0xc0) {
- len = col & 0x3f;
- col = pcxFile.readByte();
- } else {
- len = 1;
- }
-
- // The image uses 16 colors and is stored as four bit
- // planes, one for each bit of the color, least
- // significant bit plane first.
-
- for (i = 0; i < len; i++) {
- int plane = decoded / 80;
- int pos = decoded % 80;
-
- for (j = 0; j < 8; j++) {
- byte bit = (col >> (7 - j)) & 1;
- dst[8 * pos + j] |= (bit << plane);
- }
-
- decoded++;
- }
- }
- }
-
+ s->fillRect(Common::Rect(640, 480), 0);
+ const Graphics::Surface *pcxSurface = pcx.getSurface();
+ if (pcxSurface->format.bytesPerPixel != 1)
+ error("Invalid bytes per pixel in PCX surface (%d)", pcxSurface->format.bytesPerPixel);
+ for (uint16 y = 0; y < pcxSurface->h; y++)
+ memcpy((byte *)s->getBasePtr(0, y), pcxSurface->getBasePtr(0, y), pcxSurface->w);
g_system->unlockScreen();
- pcxFile.close();
}
void DreamWebEngine::frameOutV(uint8 *dst, const uint8 *src, uint16 pitch, uint16 width, uint16 height, int16 x, int16 y) {
@@ -370,9 +334,9 @@ void DreamWebEngine::zoom() {
for (size_t j = 0; j < 23; ++j) {
uint8 v = src[j];
dst[2*j+0] = v;
- dst[2*j+1] = v;
+ dst[2*j+1] = v;
dst[2*j+320] = v;
- dst[2*j+321] = v;
+ dst[2*j+321] = v;
}
src += 320;
dst += 320*2;
diff --git a/engines/engines.mk b/engines/engines.mk
index 6022a05f8a..bcf97df991 100644
--- a/engines/engines.mk
+++ b/engines/engines.mk
@@ -135,6 +135,11 @@ 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
diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp
index 1a3b313649..895686b5e0 100644
--- a/engines/groovie/detection.cpp
+++ b/engines/groovie/detection.cpp
@@ -142,7 +142,7 @@ static const GroovieGameDescription gameDescriptions[] = {
{
"11h", "Demo",
AD_ENTRY1s("disk.1", "aacb32ce07e0df2894bd83a3dee40c12", 70),
- Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO | ADGF_UNSTABLE,
+ Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO | ADGF_UNSTABLE,
GUIO5(GUIO_NOLAUNCHLOAD, GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
},
kGroovieV2, 1
diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp
index 35d7ecf886..72a61fefb2 100644
--- a/engines/groovie/roq.cpp
+++ b/engines/groovie/roq.cpp
@@ -288,19 +288,18 @@ bool ROQPlayer::processBlockInfo(ROQBlockHeader &blockHeader) {
// them it should be just fine.
_currBuf->create(width, height, Graphics::PixelFormat(3, 0, 0, 0, 0, 0, 0, 0, 0));
_prevBuf->create(width, height, Graphics::PixelFormat(3, 0, 0, 0, 0, 0, 0, 0, 0));
+ }
- // Clear the buffers with black YUV values
- byte *ptr1 = (byte *)_currBuf->getBasePtr(0, 0);
- byte *ptr2 = (byte *)_prevBuf->getBasePtr(0, 0);
- for (int i = 0; i < width * height; i++) {
- *ptr1++ = 0;
- *ptr1++ = 128;
- *ptr1++ = 128;
- *ptr2++ = 0;
- *ptr2++ = 128;
- *ptr2++ = 128;
- }
-
+ // Clear the buffers with black YUV values
+ byte *ptr1 = (byte *)_currBuf->getBasePtr(0, 0);
+ byte *ptr2 = (byte *)_prevBuf->getBasePtr(0, 0);
+ for (int i = 0; i < width * height; i++) {
+ *ptr1++ = 0;
+ *ptr1++ = 128;
+ *ptr1++ = 128;
+ *ptr2++ = 0;
+ *ptr2++ = 128;
+ *ptr2++ = 128;
}
return true;
@@ -405,7 +404,7 @@ void ROQPlayer::processBlockQuadVectorBlock(int baseX, int baseY, int8 Mx, int8
}
void ROQPlayer::processBlockQuadVectorBlockSub(int baseX, int baseY, int8 Mx, int8 My) {
- debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing quad vector sub block");
+ debugC(6, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing quad vector sub block");
uint16 codingType = getCodingType();
switch (codingType) {
@@ -433,7 +432,7 @@ void ROQPlayer::processBlockQuadVectorBlockSub(int baseX, int baseY, int8 Mx, in
bool ROQPlayer::processBlockStill(ROQBlockHeader &blockHeader) {
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing still (JPEG) block");
- warning("Groovie::ROQ: JPEG frame (unfinshed)");
+ warning("Groovie::ROQ: JPEG frame (unfinished)");
Graphics::JPEGDecoder *jpg = new Graphics::JPEGDecoder();
jpg->loadStream(*_file);
diff --git a/engines/hugo/file.cpp b/engines/hugo/file.cpp
index 15ee06c82a..1758f3f6a5 100644
--- a/engines/hugo/file.cpp
+++ b/engines/hugo/file.cpp
@@ -32,7 +32,11 @@
#include "common/savefile.h"
#include "common/textconsole.h"
#include "common/config-manager.h"
+
+#include "graphics/surface.h"
+#include "graphics/decoders/pcx.h"
#include "graphics/thumbnail.h"
+
#include "gui/saveload.h"
#include "hugo/hugo.h"
@@ -88,66 +92,33 @@ const char *FileManager::getUifFilename() const {
}
/**
- * Convert 4 planes (RGBI) data to 8-bit DIB format
- * Return original plane data ptr
- */
-byte *FileManager::convertPCC(byte *p, const uint16 y, const uint16 bpl, ImagePtr dataPtr) const {
- debugC(2, kDebugFile, "convertPCC(byte *p, %d, %d, ImagePtr dataPtr)", y, bpl);
-
- dataPtr += y * bpl * 8; // Point to correct DIB line
- for (int16 r = 0, g = bpl, b = g + bpl, i = b + bpl; r < bpl; r++, g++, b++, i++) { // Each byte in all planes
- for (int8 bit = 7; bit >= 0; bit--) { // Each bit in byte
- *dataPtr++ = (((p[r] >> bit & 1) << 0) |
- ((p[g] >> bit & 1) << 1) |
- ((p[b] >> bit & 1) << 2) |
- ((p[i] >> bit & 1) << 3));
- }
- }
- return p;
-}
-
-/**
* Read a pcx file of length len. Use supplied seqPtr and image_p or
* allocate space if NULL. Name used for errors. Returns address of seqPtr
* Set first TRUE to initialize b_index (i.e. not reading a sequential image in file).
*/
-Seq *FileManager::readPCX(Common::ReadStream &f, Seq *seqPtr, byte *imagePtr, const bool firstFl, const char *name) {
+Seq *FileManager::readPCX(Common::SeekableReadStream &f, Seq *seqPtr, byte *imagePtr, const bool firstFl, const char *name) {
debugC(1, kDebugFile, "readPCX(..., %s)", name);
- // Read in the PCC header and check consistency
- _PCCHeader._mfctr = f.readByte();
- _PCCHeader._vers = f.readByte();
- _PCCHeader._enc = f.readByte();
- _PCCHeader._bpx = f.readByte();
- _PCCHeader._x1 = f.readUint16LE();
- _PCCHeader._y1 = f.readUint16LE();
- _PCCHeader._x2 = f.readUint16LE();
- _PCCHeader._y2 = f.readUint16LE();
- _PCCHeader._xres = f.readUint16LE();
- _PCCHeader._yres = f.readUint16LE();
- f.read(_PCCHeader._palette, sizeof(_PCCHeader._palette));
- _PCCHeader._vmode = f.readByte();
- _PCCHeader._planes = f.readByte();
- _PCCHeader._bytesPerLine = f.readUint16LE();
- f.read(_PCCHeader._fill2, sizeof(_PCCHeader._fill2));
-
- if (_PCCHeader._mfctr != 10)
- error("Bad data file format: %s", name);
-
// Allocate memory for Seq if 0
if (seqPtr == 0) {
if ((seqPtr = (Seq *)malloc(sizeof(Seq))) == 0)
error("Insufficient memory to run game.");
}
+ Graphics::PCXDecoder pcx;
+ if (!pcx.loadStream(f))
+ error("Error while reading PCX image");
+
+ const Graphics::Surface *pcxSurface = pcx.getSurface();
+ if (pcxSurface->format.bytesPerPixel != 1)
+ error("Invalid bytes per pixel in PCX surface (%d)", pcxSurface->format.bytesPerPixel);
+
// Find size of image data in 8-bit DIB format
// Note save of x2 - marks end of valid data before garbage
- uint16 bytesPerLine4 = _PCCHeader._bytesPerLine * 4; // 4-bit bpl
- seqPtr->_bytesPerLine8 = bytesPerLine4 * 2; // 8-bit bpl
- seqPtr->_lines = _PCCHeader._y2 - _PCCHeader._y1 + 1;
- seqPtr->_x2 = _PCCHeader._x2 - _PCCHeader._x1 + 1;
+ seqPtr->_lines = pcxSurface->h;
+ seqPtr->_x2 = seqPtr->_bytesPerLine8 = pcxSurface->w;
// Size of the image
- uint16 size = seqPtr->_lines * seqPtr->_bytesPerLine8;
+ uint16 size = pcxSurface->w * pcxSurface->h;
// Allocate memory for image data if NULL
if (imagePtr == 0)
@@ -156,26 +127,9 @@ Seq *FileManager::readPCX(Common::ReadStream &f, Seq *seqPtr, byte *imagePtr, co
assert(imagePtr);
seqPtr->_imagePtr = imagePtr;
+ for (uint16 y = 0; y < pcxSurface->h; y++)
+ memcpy(imagePtr + y * pcxSurface->w, pcxSurface->getBasePtr(0, y), pcxSurface->w);
- // Process the image data, converting to 8-bit DIB format
- uint16 y = 0; // Current line index
- byte pline[kXPix]; // Hold 4 planes of data
- byte *p = pline; // Ptr to above
- while (y < seqPtr->_lines) {
- byte c = f.readByte();
- if ((c & kRepeatMask) == kRepeatMask) {
- byte d = f.readByte(); // Read data byte
- for (int i = 0; i < (c & kLengthMask); i++) {
- *p++ = d;
- if ((uint16)(p - pline) == bytesPerLine4)
- p = convertPCC(pline, y++, _PCCHeader._bytesPerLine, imagePtr);
- }
- } else {
- *p++ = c;
- if ((uint16)(p - pline) == bytesPerLine4)
- p = convertPCC(pline, y++, _PCCHeader._bytesPerLine, imagePtr);
- }
- }
return seqPtr;
}
diff --git a/engines/hugo/file.h b/engines/hugo/file.h
index 1438bd2054..44f257a2af 100644
--- a/engines/hugo/file.h
+++ b/engines/hugo/file.h
@@ -112,16 +112,13 @@ protected:
Common::File _sceneryArchive1; // Handle for scenery file
Common::File _objectsArchive; // Handle for objects file
- PCCHeader _PCCHeader;
-
- Seq *readPCX(Common::ReadStream &f, Seq *seqPtr, byte *imagePtr, const bool firstFl, const char *name);
+ Seq *readPCX(Common::SeekableReadStream &f, Seq *seqPtr, byte *imagePtr, const bool firstFl, const char *name);
// If this is the first call, read the lookup table
bool _hasReadHeader;
SoundHdr _soundHdr[kMaxSounds]; // Sound lookup table
private:
- byte *convertPCC(byte *p, const uint16 y, const uint16 bpl, ImagePtr dataPtr) const;
UifHdr *getUIFHeader(const Uif id);
};
diff --git a/engines/lure/decode.cpp b/engines/lure/decode.cpp
index 1338559534..484126c43f 100644
--- a/engines/lure/decode.cpp
+++ b/engines/lure/decode.cpp
@@ -255,7 +255,7 @@ MemoryBlock *PictureDecoder::vgaDecode(MemoryBlock *src, uint32 maxOutputSize) {
decrCtr();
if (shlCarry())
break;
-
+
AL = dataIn->data()[BP + 3];
} else {
decrCtr();
@@ -375,7 +375,7 @@ uint32 AnimationDecoder::decode_data(MemoryBlock *src, MemoryBlock *dest, uint32
// Main loop
bool loopFlag = true;
while (loopFlag) {
- for (;;) {
+ for (;;) {
carry = false;
rcl(currData, carry);
if (--bitCtr == 0) {
diff --git a/engines/made/screenfx.cpp b/engines/made/screenfx.cpp
index de9231a158..ad71f1fb49 100644
--- a/engines/made/screenfx.cpp
+++ b/engines/made/screenfx.cpp
@@ -200,10 +200,10 @@ void ScreenEffects::stepBlendedPalette() {
setBlendedPalette(_blendedPaletteStatus._palette, _blendedPaletteStatus._newPalette,
_blendedPaletteStatus._colorCount, _blendedPaletteStatus._value, _blendedPaletteStatus._maxValue);
if (_blendedPaletteStatus._value == _blendedPaletteStatus._maxValue)
- _blendedPaletteStatus._value++;
- else
- _blendedPaletteStatus._value = MIN<int16>(_blendedPaletteStatus._value + _blendedPaletteStatus._incr, _blendedPaletteStatus._maxValue);
- }
+ _blendedPaletteStatus._value++;
+ else
+ _blendedPaletteStatus._value = MIN<int16>(_blendedPaletteStatus._value + _blendedPaletteStatus._incr, _blendedPaletteStatus._maxValue);
+ }
}
void ScreenEffects::copyFxRect(Graphics::Surface *surface, int16 x1, int16 y1, int16 x2, int16 y2) {
diff --git a/engines/mohawk/bitmap.cpp b/engines/mohawk/bitmap.cpp
index 952b6daec2..bc19fe2d3e 100644
--- a/engines/mohawk/bitmap.cpp
+++ b/engines/mohawk/bitmap.cpp
@@ -630,7 +630,7 @@ void MohawkBitmap::drawRLE8(Graphics::Surface *surface, bool isLE) {
// Myst Bitmap Decoder
//////////////////////////////////////////
-MohawkSurface *MystBitmap::decodeImage(Common::SeekableReadStream* stream) {
+MohawkSurface *MystBitmap::decodeImage(Common::SeekableReadStream *stream) {
uint32 uncompressedSize = stream->readUint32LE();
Common::SeekableReadStream *bmpStream = decompressLZ(stream, uncompressedSize);
delete stream;
@@ -652,10 +652,10 @@ MohawkSurface *MystBitmap::decodeImage(Common::SeekableReadStream* stream) {
}
// Copy the palette to one of our own
- const byte *palette = bitmapDecoder.getPalette();
byte *newPal = 0;
- if (palette) {
+ if (bitmapDecoder.hasPalette()) {
+ const byte *palette = bitmapDecoder.getPalette();
newPal = (byte *)malloc(256 * 3);
memcpy(newPal, palette, 256 * 3);
}
diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp
index 0ed4f38b53..b1b99722d5 100644
--- a/engines/mohawk/video.cpp
+++ b/engines/mohawk/video.cpp
@@ -478,7 +478,7 @@ VideoHandle VideoManager::findVideoHandle(const Common::String &filename) {
return NULL_VID_HANDLE;
}
-int32 VideoManager::getCurFrame(VideoHandle handle) {
+int VideoManager::getCurFrame(VideoHandle handle) {
assert(handle != NULL_VID_HANDLE);
return _videoStreams[handle]->getCurFrame();
}
diff --git a/engines/mohawk/video.h b/engines/mohawk/video.h
index 9dddcde09b..6d2783936d 100644
--- a/engines/mohawk/video.h
+++ b/engines/mohawk/video.h
@@ -98,7 +98,7 @@ public:
// Handle functions
VideoHandle findVideoHandle(uint16 id);
VideoHandle findVideoHandle(const Common::String &filename);
- int32 getCurFrame(VideoHandle handle);
+ int getCurFrame(VideoHandle handle);
uint32 getFrameCount(VideoHandle handle);
uint32 getTime(VideoHandle handle);
uint32 getDuration(VideoHandle videoHandle);
diff --git a/engines/parallaction/adlib.cpp b/engines/parallaction/adlib.cpp
new file mode 100644
index 0000000000..134e5cfbf3
--- /dev/null
+++ b/engines/parallaction/adlib.cpp
@@ -0,0 +1,808 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/system.h"
+
+#include "audio/fmopl.h"
+#include "audio/mpu401.h"
+#include "audio/softsynth/emumidi.h"
+
+namespace Parallaction {
+
+const uint kNumVoices = 9;
+// adlib FM voices 0-5
+const uint kNumMelodic = 6;
+// adlib FM voice 6 and 7-8
+const uint kNumPercussion = 5;
+
+// mask for maximum volume level
+#define LEVEL_MASK 0x7f
+
+struct OPLOperator {
+ uint8 characteristic; // amplitude modulation, vibrato, envelope, keyboard scaling, modulator frequency
+ uint8 levels;
+ uint8 attackDecay;
+ uint8 sustainRelease;
+ uint8 waveform;
+};
+
+struct MelodicProgram {
+ OPLOperator op[2];
+ uint8 feedbackAlgo;
+};
+
+struct PercussionNote {
+ OPLOperator op[2];
+ uint8 feedbackAlgo;
+ uint8 percussion;
+ uint8 valid;
+ uint16 frequency;
+ uint8 octave;
+};
+
+static const MelodicProgram melodicPrograms[128] = {
+ {{{ 0x1, 0x51, 0xf2, 0xb2, 0x0 }, { 0x11, 0x0, 0xf2, 0xa2, 0x0 }}, 0x0 },
+ {{{ 0xc2, 0x4b, 0xf1, 0x53, 0x0 }, { 0xd2, 0x0, 0xf2, 0x74, 0x0 }}, 0x4 },
+ {{{ 0x81, 0x9d, 0xf2, 0x74, 0x0 }, { 0x13, 0x0, 0xf2, 0xf1, 0x0 }}, 0x6 },
+ {{{ 0x3, 0x4f, 0xf1, 0x53, 0x0 }, { 0x17, 0x3, 0xf2, 0x74, 0x0 }}, 0x6 },
+ {{{ 0xd1, 0x81, 0x81, 0x73, 0x2 }, { 0xd4, 0x0, 0xe1, 0x34, 0x0 }}, 0x3 },
+ {{{ 0x1, 0x0, 0x94, 0xa6, 0x0 }, { 0x2, 0x0, 0x83, 0x26, 0x0 }}, 0x1 },
+ {{{ 0xf3, 0x84, 0x81, 0x2, 0x1 }, { 0x55, 0x80, 0xdd, 0x3, 0x0 }}, 0x4 },
+ {{{ 0x5, 0x8a, 0xf2, 0x26, 0x0 }, { 0x1, 0x80, 0xf3, 0x48, 0x0 }}, 0x0 },
+ {{{ 0x32, 0x0, 0xb1, 0x14, 0x0 }, { 0x12, 0x0, 0xfd, 0x36, 0x0 }}, 0x3 },
+ {{{ 0x1, 0x0, 0x82, 0xa, 0x2 }, { 0x2, 0x0, 0x85, 0x15, 0x0 }}, 0x3 },
+ {{{ 0xd1, 0x1, 0x97, 0xaa, 0x0 }, { 0x4, 0xd, 0xf3, 0xa5, 0x1 }}, 0x9 },
+ {{{ 0x17, 0x0, 0xf2, 0x62, 0x0 }, { 0x12, 0x0, 0xf2, 0x72, 0x0 }}, 0x8 },
+ {{{ 0x6, 0x0, 0xff, 0xf4, 0x0 }, { 0xc4, 0x0, 0xf8, 0xb5, 0x0 }}, 0xe },
+ {{{ 0xc0, 0x81, 0xf2, 0x13, 0x2 }, { 0xc0, 0xc1, 0xf3, 0x14, 0x2 }}, 0xb },
+ {{{ 0x44, 0x53, 0xf5, 0x31, 0x0 }, { 0x60, 0x80, 0xfd, 0x22, 0x0 }}, 0x6 },
+ {{{ 0xe0, 0x80, 0xf4, 0xf2, 0x0 }, { 0x61, 0x0, 0xf2, 0x6, 0x0 }}, 0x8 },
+ {{{ 0xc1, 0x6, 0x83, 0x23, 0x0 }, { 0xc1, 0x4, 0xf0, 0x26, 0x0 }}, 0x1 },
+ {{{ 0x26, 0x0, 0xf4, 0xb6, 0x0 }, { 0x21, 0x0, 0x81, 0x4b, 0x0 }}, 0x1 },
+ {{{ 0x24, 0x80, 0xff, 0xf, 0x0 }, { 0x21, 0x80, 0xff, 0xf, 0x0 }}, 0x1 },
+ {{{ 0x24, 0x4f, 0xf2, 0xb, 0x0 }, { 0x31, 0x0, 0x52, 0xb, 0x0 }}, 0xb },
+ {{{ 0x31, 0x8, 0x81, 0xb, 0x0 }, { 0xa1, 0x80, 0x92, 0x3b, 0x0 }}, 0x0 },
+ {{{ 0x70, 0xc5, 0x52, 0x11, 0x1 }, { 0x71, 0x80, 0x31, 0xfe, 0x1 }}, 0x0 },
+ {{{ 0x51, 0x88, 0x10, 0xf0, 0x0 }, { 0x42, 0x83, 0x40, 0xfc, 0x0 }}, 0x8 },
+ {{{ 0xf0, 0xd9, 0x81, 0x3, 0x0 }, { 0xb1, 0x80, 0xf1, 0x5, 0x0 }}, 0xa },
+ {{{ 0x21, 0x4f, 0xf1, 0x31, 0x0 }, { 0x2, 0x80, 0xc3, 0x45, 0x0 }}, 0x0 },
+ {{{ 0x7, 0x8f, 0x9c, 0x33, 0x1 }, { 0x1, 0x80, 0x8a, 0x13, 0x0 }}, 0x0 },
+ {{{ 0x21, 0x40, 0xf1, 0x31, 0x0 }, { 0x6, 0x80, 0xf4, 0x44, 0x0 }}, 0x0 },
+ {{{ 0x21, 0x40, 0xf1, 0x31, 0x3 }, { 0x81, 0x0, 0xf4, 0x44, 0x2 }}, 0x2 },
+ {{{ 0x11, 0x8d, 0xfd, 0x11, 0x0 }, { 0x11, 0x80, 0xfd, 0x11, 0x0 }}, 0x8 },
+ {{{ 0xf0, 0x1, 0x97, 0x17, 0x0 }, { 0x21, 0xd, 0xf1, 0x18, 0x0 }}, 0x8 },
+ {{{ 0xf1, 0x1, 0x97, 0x17, 0x0 }, { 0x21, 0xd, 0xf1, 0x18, 0x0 }}, 0x8 },
+ {{{ 0xcd, 0x9e, 0x55, 0xd1, 0x0 }, { 0xd1, 0x0, 0xf2, 0x71, 0x0 }}, 0xe },
+ {{{ 0x1, 0x0, 0xf2, 0x88, 0x0 }, { 0x1, 0x0, 0xf5, 0x88, 0x0 }}, 0x1 },
+ {{{ 0x30, 0xd, 0xf2, 0xef, 0x0 }, { 0x21, 0x0, 0xf5, 0x78, 0x0 }}, 0x6 },
+ {{{ 0x0, 0x10, 0xf4, 0xd9, 0x0 }, { 0x0, 0x0, 0xf5, 0xd7, 0x0 }}, 0x4 },
+ {{{ 0x1, 0x4c, 0xf2, 0x50, 0x0 }, { 0x1, 0x40, 0xd2, 0x59, 0x0 }}, 0x8 },
+ {{{ 0x20, 0x11, 0xe2, 0x8a, 0x0 }, { 0x20, 0x0, 0xe4, 0xa8, 0x0 }}, 0xa },
+ {{{ 0x21, 0x40, 0x7b, 0x4, 0x1 }, { 0x21, 0x0, 0x75, 0x72, 0x0 }}, 0x2 },
+ {{{ 0x31, 0xd, 0xf2, 0xef, 0x0 }, { 0x21, 0x0, 0xf5, 0x78, 0x0 }}, 0xa },
+ {{{ 0x1, 0xc, 0xf5, 0x2f, 0x1 }, { 0x0, 0x80, 0xf5, 0x5c, 0x0 }}, 0x0 },
+ {{{ 0xb0, 0x1c, 0x81, 0x3, 0x2 }, { 0x20, 0x0, 0x54, 0x67, 0x2 }}, 0xe },
+ {{{ 0x1, 0x0, 0xf1, 0x65, 0x0 }, { 0x1, 0x80, 0xa3, 0xa8, 0x2 }}, 0x1 },
+ {{{ 0xe1, 0x4f, 0xc1, 0xd3, 0x2 }, { 0x21, 0x0, 0x32, 0x74, 0x1 }}, 0x0 },
+ {{{ 0x2, 0x0, 0xf6, 0x16, 0x0 }, { 0x12, 0x0, 0xf2, 0xf8, 0x0 }}, 0x1 },
+ {{{ 0xe0, 0x63, 0xf8, 0xf3, 0x0 }, { 0x70, 0x80, 0xf7, 0xf3, 0x0 }}, 0x4 },
+ {{{ 0x1, 0x6, 0xf3, 0xff, 0x0 }, { 0x8, 0x0, 0xf7, 0xff, 0x0 }}, 0x4 },
+ {{{ 0x21, 0x16, 0xb0, 0x81, 0x1 }, { 0x22, 0x0, 0xb3, 0x13, 0x1 }}, 0xc },
+ {{{ 0x1, 0x4f, 0xf0, 0xff, 0x0 }, { 0x30, 0x0, 0x90, 0xf, 0x0 }}, 0x6 },
+ {{{ 0x0, 0x10, 0xf1, 0xf2, 0x2 }, { 0x1, 0x0, 0xf1, 0xf2, 0x3 }}, 0x0 },
+ {{{ 0x1, 0x4f, 0xf1, 0x50, 0x0 }, { 0x21, 0x80, 0xa3, 0x5, 0x3 }}, 0x6 },
+ {{{ 0xb1, 0x3, 0x55, 0x3, 0x0 }, { 0xb1, 0x3, 0x8, 0xa, 0x0 }}, 0x9 },
+ {{{ 0x22, 0x0, 0xa9, 0x34, 0x1 }, { 0x1, 0x0, 0xa2, 0x42, 0x2 }}, 0x2 },
+ {{{ 0xa0, 0xdc, 0x81, 0x31, 0x3 }, { 0xb1, 0x80, 0xf1, 0x1, 0x3 }}, 0x0 },
+ {{{ 0x1, 0x4f, 0xf1, 0x50, 0x0 }, { 0x21, 0x80, 0xa3, 0x5, 0x3 }}, 0x6 },
+ {{{ 0xf1, 0x80, 0xa0, 0x72, 0x0 }, { 0x74, 0x0, 0x90, 0x22, 0x0 }}, 0x9 },
+ {{{ 0xe1, 0x13, 0x71, 0xae, 0x0 }, { 0xe1, 0x0, 0xf0, 0xfc, 0x1 }}, 0xa },
+ {{{ 0x31, 0x1c, 0x41, 0xb, 0x0 }, { 0xa1, 0x80, 0x92, 0x3b, 0x0 }}, 0xe },
+ {{{ 0x71, 0x1c, 0x41, 0x1f, 0x0 }, { 0xa1, 0x80, 0x92, 0x3b, 0x0 }}, 0xe },
+ {{{ 0x21, 0x1c, 0x53, 0x1d, 0x0 }, { 0xa1, 0x80, 0x52, 0x3b, 0x0 }}, 0xc },
+ {{{ 0x21, 0x1d, 0xa4, 0xae, 0x1 }, { 0x21, 0x0, 0xb1, 0x9e, 0x0 }}, 0xc },
+ {{{ 0xe1, 0x16, 0x71, 0xae, 0x0 }, { 0xe1, 0x0, 0x81, 0x9e, 0x0 }}, 0xa },
+ {{{ 0xe1, 0x15, 0x71, 0xae, 0x0 }, { 0xe2, 0x0, 0x81, 0x9e, 0x0 }}, 0xe },
+ {{{ 0x21, 0x16, 0x71, 0xae, 0x0 }, { 0x21, 0x0, 0x81, 0x9e, 0x0 }}, 0xe },
+ {{{ 0x71, 0x1c, 0x41, 0x1f, 0x0 }, { 0xa1, 0x80, 0x92, 0x3b, 0x0 }}, 0xe },
+ {{{ 0x21, 0x4f, 0x81, 0x53, 0x0 }, { 0x32, 0x0, 0x22, 0x2c, 0x0 }}, 0xa },
+ {{{ 0x22, 0x4f, 0x81, 0x53, 0x0 }, { 0x32, 0x0, 0x22, 0x2c, 0x0 }}, 0xa },
+ {{{ 0x23, 0x4f, 0x81, 0x53, 0x0 }, { 0x34, 0x0, 0x22, 0x2c, 0x0 }}, 0xa },
+ {{{ 0xe1, 0x16, 0x71, 0xae, 0x0 }, { 0xe1, 0x0, 0x81, 0x9e, 0x0 }}, 0xa },
+ {{{ 0x71, 0xc5, 0x6e, 0x17, 0x0 }, { 0x22, 0x5, 0x8b, 0xe, 0x0 }}, 0x2 },
+ {{{ 0xe6, 0x27, 0x70, 0xf, 0x1 }, { 0xe3, 0x0, 0x60, 0x9f, 0x0 }}, 0xa },
+ {{{ 0x30, 0xc8, 0xd5, 0x19, 0x0 }, { 0xb1, 0x80, 0x61, 0x1b, 0x0 }}, 0xc },
+ {{{ 0x32, 0x9a, 0x51, 0x1b, 0x0 }, { 0xa1, 0x82, 0xa2, 0x3b, 0x0 }}, 0xc },
+ {{{ 0xad, 0x3, 0x74, 0x29, 0x0 }, { 0xa2, 0x82, 0x73, 0x29, 0x0 }}, 0x7 },
+ {{{ 0x21, 0x83, 0x74, 0x17, 0x0 }, { 0x62, 0x8d, 0x65, 0x17, 0x0 }}, 0x7 },
+ {{{ 0x94, 0xb, 0x85, 0xff, 0x1 }, { 0x13, 0x0, 0x74, 0xff, 0x0 }}, 0xc },
+ {{{ 0x74, 0x87, 0xa4, 0x2, 0x0 }, { 0xd6, 0x80, 0x45, 0x42, 0x0 }}, 0x2 },
+ {{{ 0xb3, 0x85, 0x76, 0x21, 0x1 }, { 0x20, 0x0, 0x3d, 0xc1, 0x0 }}, 0x6 },
+ {{{ 0x17, 0x4f, 0xf2, 0x61, 0x0 }, { 0x12, 0x8, 0xf1, 0xb4, 0x0 }}, 0x8 },
+ {{{ 0x4f, 0x86, 0x65, 0x1, 0x0 }, { 0x1f, 0x0, 0x32, 0x74, 0x0 }}, 0x4 },
+ {{{ 0xe1, 0x23, 0x71, 0xae, 0x0 }, { 0xe4, 0x0, 0x82, 0x9e, 0x0 }}, 0xa },
+ {{{ 0x11, 0x86, 0xf2, 0xbd, 0x0 }, { 0x4, 0x80, 0xa0, 0x9b, 0x1 }}, 0x8 },
+ {{{ 0x20, 0x90, 0xf5, 0x9e, 0x2 }, { 0x11, 0x0, 0xf4, 0x5b, 0x3 }}, 0xc },
+ {{{ 0xf0, 0x80, 0x34, 0xe4, 0x0 }, { 0x7e, 0x0, 0xa2, 0x6, 0x0 }}, 0x8 },
+ {{{ 0x90, 0xf, 0xff, 0x1, 0x3 }, { 0x0, 0x0, 0x1f, 0x1, 0x0 }}, 0xe },
+ {{{ 0x1, 0x4f, 0xf0, 0xff, 0x0 }, { 0x33, 0x0, 0x90, 0xf, 0x0 }}, 0x6 },
+ {{{ 0x1e, 0x0, 0x1f, 0xf, 0x0 }, { 0x10, 0x0, 0x1f, 0x7f, 0x0 }}, 0x0 },
+ {{{ 0xbe, 0x0, 0xf1, 0x1, 0x3 }, { 0x31, 0x0, 0xf1, 0x1, 0x0 }}, 0x4 },
+ {{{ 0xbe, 0x0, 0xf1, 0x1, 0x3 }, { 0x31, 0x0, 0xf1, 0x1, 0x0 }}, 0x4 },
+ {{{ 0x93, 0x6, 0xc1, 0x4, 0x1 }, { 0x82, 0x0, 0x51, 0x9, 0x0 }}, 0x6 },
+ {{{ 0xa0, 0x0, 0x96, 0x33, 0x0 }, { 0x20, 0x0, 0x55, 0x2b, 0x0 }}, 0x6 },
+ {{{ 0x0, 0xc0, 0xff, 0x5, 0x0 }, { 0x0, 0x0, 0xff, 0x5, 0x3 }}, 0x0 },
+ {{{ 0x4, 0x8, 0xf8, 0x7, 0x0 }, { 0x1, 0x0, 0x82, 0x74, 0x0 }}, 0x8 },
+ {{{ 0x0, 0x0, 0x2f, 0x5, 0x0 }, { 0x20, 0x0, 0xff, 0x5, 0x3 }}, 0xa },
+ {{{ 0x93, 0x0, 0xf7, 0x7, 0x2 }, { 0x0, 0x0, 0xf7, 0x7, 0x0 }}, 0xa },
+ {{{ 0x0, 0x40, 0x80, 0x7a, 0x0 }, { 0xc4, 0x0, 0xc0, 0x7e, 0x0 }}, 0x8 },
+ {{{ 0x90, 0x80, 0x55, 0xf5, 0x0 }, { 0x0, 0x0, 0x55, 0xf5, 0x0 }}, 0x8 },
+ {{{ 0xe1, 0x80, 0x34, 0xe4, 0x0 }, { 0x69, 0x0, 0xf2, 0x6, 0x0 }}, 0x8 },
+ {{{ 0x3, 0x2, 0xf0, 0xff, 0x3 }, { 0x11, 0x80, 0xf0, 0xff, 0x2 }}, 0x2 },
+ {{{ 0x1e, 0x0, 0x1f, 0xf, 0x0 }, { 0x10, 0x0, 0x1f, 0x7f, 0x0 }}, 0x0 },
+ {{{ 0x0, 0x0, 0x2f, 0x1, 0x0 }, { 0x0, 0x0, 0xff, 0x1, 0x0 }}, 0x4 },
+ {{{ 0xbe, 0x0, 0xf1, 0x1, 0x3 }, { 0x31, 0x0, 0xf1, 0x1, 0x0 }}, 0x4 },
+ {{{ 0x93, 0x85, 0x3f, 0x6, 0x1 }, { 0x0, 0x0, 0x5f, 0x7, 0x0 }}, 0x6 },
+ {{{ 0x6, 0x0, 0xa0, 0xf0, 0x0 }, { 0x44, 0x0, 0xc5, 0x75, 0x0 }}, 0xe },
+ {{{ 0x60, 0x0, 0x10, 0x81, 0x0 }, { 0x20, 0x8c, 0x12, 0x91, 0x0 }}, 0xe },
+ {{{ 0x1, 0x40, 0xf1, 0x53, 0x0 }, { 0x8, 0x40, 0xf1, 0x53, 0x0 }}, 0x0 },
+ {{{ 0x31, 0x0, 0x56, 0x31, 0x0 }, { 0x16, 0x0, 0x7d, 0x41, 0x0 }}, 0x0 },
+ {{{ 0x0, 0x10, 0xf2, 0x72, 0x0 }, { 0x13, 0x0, 0xf2, 0x72, 0x0 }}, 0xc },
+ {{{ 0x10, 0x0, 0x75, 0x93, 0x1 }, { 0x1, 0x0, 0xf5, 0x82, 0x1 }}, 0x0 },
+ {{{ 0x0, 0x0, 0xf6, 0xff, 0x2 }, { 0x0, 0x0, 0xf6, 0xff, 0x0 }}, 0x8 },
+ {{{ 0x30, 0x0, 0xff, 0xa0, 0x3 }, { 0x63, 0x0, 0x65, 0xb, 0x2 }}, 0x0 },
+ {{{ 0x2a, 0x0, 0xf6, 0x87, 0x0 }, { 0x2b, 0x0, 0x76, 0x25, 0x0 }}, 0x0 },
+ {{{ 0x85, 0x0, 0xb8, 0x84, 0x0 }, { 0x43, 0x0, 0xe5, 0x8f, 0x0 }}, 0x6 },
+ {{{ 0x7, 0x4f, 0xf2, 0x60, 0x0 }, { 0x12, 0x0, 0xf2, 0x72, 0x0 }}, 0x8 },
+ {{{ 0x5, 0x40, 0xb3, 0xd3, 0x0 }, { 0x86, 0x80, 0xf2, 0x24, 0x0 }}, 0x2 },
+ {{{ 0xd0, 0x0, 0x11, 0xcf, 0x0 }, { 0xd1, 0x0, 0xf4, 0xe8, 0x3 }}, 0x0 },
+ {{{ 0x5, 0x4e, 0xda, 0x25, 0x2 }, { 0x1, 0x0, 0xf9, 0x15, 0x0 }}, 0xa },
+ {{{ 0x3, 0x0, 0x8f, 0x7, 0x2 }, { 0x2, 0x0, 0xff, 0x6, 0x0 }}, 0x0 },
+ {{{ 0x13, 0x0, 0x8f, 0x7, 0x2 }, { 0x2, 0x0, 0xf9, 0x5, 0x0 }}, 0x0 },
+ {{{ 0xf0, 0x1, 0x97, 0x17, 0x0 }, { 0x21, 0xd, 0xf1, 0x18, 0x0 }}, 0x8 },
+ {{{ 0xf1, 0x41, 0x11, 0x11, 0x0 }, { 0xf1, 0x41, 0x11, 0x11, 0x0 }}, 0x2 },
+ {{{ 0x13, 0x0, 0x8f, 0x7, 0x2 }, { 0x2, 0x0, 0xff, 0x6, 0x0 }}, 0x0 },
+ {{{ 0x1, 0x0, 0x2f, 0x1, 0x0 }, { 0x1, 0x0, 0xaf, 0x1, 0x3 }}, 0xf },
+ {{{ 0x1, 0x6, 0xf3, 0xff, 0x0 }, { 0x8, 0x0, 0xf7, 0xff, 0x0 }}, 0x4 },
+ {{{ 0xc0, 0x4f, 0xf1, 0x3, 0x0 }, { 0xbe, 0xc, 0x10, 0x1, 0x0 }}, 0x2 },
+ {{{ 0x0, 0x2, 0xf0, 0xff, 0x0 }, { 0x11, 0x80, 0xf0, 0xff, 0x0 }}, 0x6 },
+ {{{ 0x81, 0x47, 0xf1, 0x83, 0x0 }, { 0xa2, 0x4, 0x91, 0x86, 0x0 }}, 0x6 },
+ {{{ 0xf0, 0xc0, 0xff, 0xff, 0x3 }, { 0xe5, 0x0, 0xfb, 0xf0, 0x0 }}, 0xe },
+ {{{ 0x0, 0x2, 0xf0, 0xff, 0x0 }, { 0x11, 0x80, 0xf0, 0xff, 0x0 }}, 0x6 }
+};
+
+static const PercussionNote percussionNotes[47] = {
+ {{{ 0x0, 0xb, 0xa8, 0x38, 0x0 }, { 0x0, 0x0, 0xd6, 0x49, 0x0 }}, 0x0, 0x4, 0x1, 0x97, 0x4 },
+ {{{ 0xc0, 0xc0, 0xf8, 0x3f, 0x2 }, { 0xc0, 0x0, 0xf6, 0x8e, 0x0 }}, 0x0, 0x4, 0x1, 0xf7, 0x4 },
+ {{{ 0xc0, 0x80, 0xc9, 0xab, 0x0 }, { 0xeb, 0x40, 0xb5, 0xf6, 0x0 }}, 0x1, 0x3, 0x1, 0x6a, 0x6 },
+ {{{ 0xc, 0x0, 0xd8, 0xa6, 0x0 }, { 0x0, 0x0, 0xd6, 0x4f, 0x0 }}, 0x1, 0x3, 0x1, 0x6c, 0x5 },
+ {{{ 0x1, 0x0, 0xe2, 0xd2, 0x0 }, { 0x3, 0x41, 0x8f, 0x48, 0x49 }}, 0xc, 0x4, 0x1, 0x2f, 0x5 },
+ {{{ 0x0, 0x0, 0xc8, 0x58, 0x3 }, { 0x0, 0x0, 0xf6, 0x4f, 0x0 }}, 0x9, 0x3, 0x1, 0x108, 0x4 },
+ {{{ 0x1, 0x0, 0xff, 0x5, 0x0 }, { 0xf2, 0xff, 0xe0, 0x50, 0x52 }}, 0x5d, 0x2, 0x1, 0x9f, 0x5 },
+ {{{ 0xe, 0x9, 0xb9, 0x47, 0x0 }, { 0xeb, 0x40, 0xf5, 0xe6, 0x0 }}, 0x0, 0x0, 0x1, 0x82, 0x6 },
+ {{{ 0x0, 0x0, 0xd6, 0x83, 0x0 }, { 0xd6, 0xd7, 0xe0, 0x41, 0x5e }}, 0x4a, 0x2, 0x1, 0xc7, 0x5 },
+ {{{ 0x1, 0x9, 0x89, 0x67, 0x0 }, { 0xd6, 0xd7, 0xe0, 0x41, 0x5e }}, 0x4a, 0x0, 0x1, 0x80, 0x6 },
+ {{{ 0x1, 0x0, 0xd6, 0x96, 0x0 }, { 0xd6, 0xd7, 0xe0, 0x41, 0x5e }}, 0x4a, 0x2, 0x1, 0xed, 0x5 },
+ {{{ 0x0, 0x9, 0xa9, 0x55, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x1, 0x82, 0x6 },
+ {{{ 0x2, 0x0, 0xc6, 0x96, 0x0 }, { 0xe0, 0x0, 0xe0, 0x40, 0x0 }}, 0x1, 0x2, 0x1, 0x123, 0x5 },
+ {{{ 0x5, 0x0, 0xf6, 0x56, 0x0 }, { 0xf7, 0xff, 0xb3, 0x90, 0x4f }}, 0x1, 0x2, 0x1, 0x15b, 0x5 },
+ {{{ 0x1, 0x0, 0xf7, 0x14, 0x0 }, { 0xf7, 0xff, 0x36, 0x90, 0x79 }}, 0xe7, 0x1, 0x1, 0x1ac, 0x5 },
+ {{{ 0x0, 0x0, 0xf6, 0x56, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x1, 0x2, 0x1, 0x18b, 0x5 },
+ {{{ 0x0, 0x83, 0xfb, 0x5, 0x0 }, { 0xf7, 0x41, 0x39, 0x90, 0x79 }}, 0x1, 0x1, 0x1, 0xc8, 0x5 },
+ {{{ 0x0, 0x0, 0xff, 0x5, 0x0 }, { 0xf7, 0xff, 0x36, 0x90, 0x79 }}, 0xe7, 0x1, 0x1, 0xf9, 0x5 },
+ {{{ 0x1, 0x0, 0xa0, 0x5, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x2, 0x1, 0x27a, 0x6 },
+ {{{ 0x0, 0x5, 0xf3, 0x6, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x2, 0x1, 0x108, 0x7 },
+ {{{ 0x1, 0x0, 0xf9, 0x34, 0x0 }, { 0xf7, 0xff, 0x36, 0x90, 0x79 }}, 0xe7, 0x1, 0x1, 0x147, 0x4 },
+ {{{ 0x0, 0x0, 0xf7, 0x16, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x2, 0x1, 0x120, 0x6 },
+ {{{ 0x1, 0x0, 0xff, 0x5, 0x0 }, { 0xf7, 0xff, 0x36, 0x90, 0x79 }}, 0xe7, 0x1, 0x1, 0x42, 0x6 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x1, 0x0, 0xff, 0x5, 0x0 }, { 0xf7, 0xff, 0x36, 0x90, 0x79 }}, 0xe7, 0x1, 0x1, 0x6d, 0x5 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 },
+ {{{ 0x0, 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0, 0x0 }}, 0x0, 0x0, 0x0, 0x3fc, 0x4 }
+};
+
+const uint16 melodicFrequencies[36] = {
+ 0x55, 0x5a, 0x60, 0x66, 0x6c, 0x72, 0x79, 0x80, 0x88,
+ 0x90, 0x99, 0xa1, 0xab, 0xb5, 0xc0, 0xcc, 0xd8, 0xe5,
+ 0xf2, 0x101, 0x110, 0x120, 0x132, 0x143, 0x156, 0x16b, 0x181,
+ 0x198, 0x1b0, 0x1ca, 0x1e5, 0x202, 0x220, 0x241, 0x263, 0x286
+};
+
+class AdLibDriver;
+
+class AdLibChannel : public MidiChannel_MPU401 {
+public:
+ void reset();
+
+ uint8 _program;
+ uint8 _volume;
+ uint8 _pedal;
+};
+
+struct MelodicVoice {
+ bool _used;
+ uint8 _channel;
+ uint8 _program;
+
+ uint8 _key;
+ uint32 _timestamp;
+ uint16 _frequency;
+ int8 _octave;
+};
+
+class AdLibDriver : public MidiDriver_Emulated {
+public:
+ AdLibDriver(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer) {
+ for (uint i = 0; i < 16; ++i)
+ _channels[i].init(this, i);
+ }
+
+ int open();
+ void close();
+ void send(uint32 b);
+ MidiChannel *allocateChannel();
+ MidiChannel *getPercussionChannel() { return &_channels[9]; }
+
+ bool isStereo() const { return false; }
+ int getRate() const { return _mixer->getOutputRate(); }
+
+ void generateSamples(int16 *buf, int len);
+
+protected:
+ OPL::OPL *_opl;
+ AdLibChannel _channels[16];
+ MelodicVoice _voices[kNumMelodic];
+ uint8 _notesPerPercussion[kNumPercussion];
+
+ uint _lastVoice;
+
+ uint8 _percussionMask;
+
+ void noteOff(uint8 channel, uint8 note);
+ void noteOn(uint8 channel, uint8 note, uint8 velocity);
+ void allNotesOff();
+ void setModulationWheel(uint8 channel, uint8 value);
+ void setFootController(uint8 channel, uint8 value);
+ void setVolume(uint8 channel, uint8 value);
+ void setPitchBend(uint8 channel, int16 value);
+
+ void playNote(uint8 voice, uint8 octave, uint16 frequency);
+
+ void programOperatorSimple(uint8 offset, const OPLOperator &op);
+ void programOperator(uint8 offset, const OPLOperator &op);
+ void setOperatorLevel(uint8 offset, const OPLOperator &op, uint8 velocity, uint8 channel, bool forceVolume);
+
+ void setupPercussion(const PercussionNote &note);
+ void playPercussion(uint8 channel, const PercussionNote &note, uint8 velocity);
+
+ void programMelodicVoice(uint8 voice, uint8 program);
+ void playMelodicNote(uint8 voice, uint8 channel, uint8 note, uint8 velocity);
+ void muteMelodicVoice(uint8 voice);
+
+ void initVoices();
+};
+
+MidiDriver *createAdLibDriver() {
+ return new AdLibDriver(g_system->getMixer());
+}
+
+void AdLibChannel::reset() {
+ _program = 0;
+ _volume = 127;
+ _pedal = 0;
+}
+
+/*
+ bit 7 - Clear: AM depth is 1 dB
+ bit 6 - Clear: Vibrato depth is 7 cent
+ bit 5 - Set: Rhythm enabled (6 melodic voices)
+ bit 4 - Bass drum off
+ bit 3 - Snare drum off
+ bit 2 - Tom tom off
+ bit 1 - Cymbal off
+ bit 0 - Hi Hat off
+*/
+const uint8 kDefaultPercussionMask = 0x20;
+
+int AdLibDriver::open() {
+ if (_isOpen)
+ return MERR_ALREADY_OPEN;
+
+ MidiDriver_Emulated::open();
+
+ _opl = OPL::Config::create();
+ _opl->init(getRate());
+ _opl->writeReg(0x1, 0x20); // set bit 5 (enable all waveforms)
+
+ // Reset the OPL registers.
+ for (uint i = 0; i < kNumVoices; ++i) {
+ _opl->writeReg(0xA0 + i, 0); // frequency
+ _opl->writeReg(0xB0 + i, 0); // key on
+ _opl->writeReg(0xC0 + i, 0); // feedback
+ }
+ _opl->writeReg(0xBD, kDefaultPercussionMask);
+
+ initVoices();
+
+ _mixer->playStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+ return 0;
+}
+
+void AdLibDriver::close() {
+ if (!_isOpen)
+ return;
+
+ _isOpen = false;
+ _mixer->stopHandle(_mixerSoundHandle);
+
+ delete _opl;
+}
+
+void AdLibDriver::send(uint32 b) {
+ uint channel = b & 0xf;
+ uint cmd = (b >> 4) & 0xf;
+ uint param1 = (b >> 8) & 0xff;
+ uint param2 = (b >> 16) & 0xff;
+
+ switch (cmd) {
+ case 8:
+ noteOff(channel, param1);
+ break;
+ case 9:
+ // TODO: map volume?
+ noteOn(channel, param1, param2);
+ break;
+ case 11:
+ // controller change
+ switch (param1) {
+ case 1:
+ setModulationWheel(channel, param2);
+ break;
+ case 4:
+ setFootController(channel, param2);
+ break;
+ case 7:
+ setVolume(channel, param2);
+ break;
+ case 123:
+ // all notes off
+ allNotesOff();
+ break;
+ }
+ break;
+ case 12:
+ // program change
+ _channels[channel]._program = param1;
+ break;
+ case 14:
+ setPitchBend(channel, (param1 | (param2 << 7)) - 0x2000);
+ break;
+ }
+}
+
+void AdLibDriver::noteOff(uint8 channel, uint8 note) {
+ if (channel == 9) {
+ if (note < 35 || note > 81)
+ return;
+
+ _percussionMask &= ~(1 << percussionNotes[note - 35].percussion);
+ _opl->writeReg(0xBD, _percussionMask);
+ return;
+ }
+
+ for (int i = kNumMelodic - 1; i >= 0; --i) {
+ if (_voices[i]._channel != channel)
+ continue;
+ if (_voices[i]._key != note)
+ continue;
+ muteMelodicVoice(i);
+ _voices[i]._used = false;
+ return;
+ }
+
+ //debug(1, "failed to find voice off for channel %d, note %d", channel, note);
+}
+
+void AdLibDriver::noteOn(uint8 channel, uint8 note, uint8 velocity) {
+ if (channel == 9) {
+ if (note < 35 || note > 81)
+ return;
+
+ const PercussionNote &info = percussionNotes[note - 35];
+ if (!info.valid)
+ return;
+
+ if (note != _notesPerPercussion[info.percussion]) {
+ setupPercussion(info);
+ _notesPerPercussion[info.percussion] = note;
+ }
+
+ playPercussion(channel, info, velocity);
+ return;
+ }
+
+ if (velocity == 0) {
+ noteOff(channel, note);
+ return;
+ }
+
+ // We want to play a note on a melodic (voice) channel.
+
+ // First, look for a voice playing the same note with the same program.
+ for (uint i = 0; i < kNumMelodic; ++i) {
+ if (_voices[i]._channel != channel || _voices[i]._key != note)
+ continue;
+ if (_voices[i]._program != _channels[channel]._program)
+ continue;
+ muteMelodicVoice(i);
+ playMelodicNote(i, channel, note, velocity);
+ return;
+ }
+
+ // The loops below try to start at _lastVoice and find a voice to use.
+ // They ignore _lastVoice itself, and update _lastVoice if they succeed.
+
+ // Then, try finding a melodic voice with the same program.
+ for (uint i = (_lastVoice + 1) % kNumMelodic; i != _lastVoice; i = (i + 1) % kNumMelodic) {
+ if (_voices[i]._used)
+ continue;
+ if (_voices[i]._program != _channels[channel]._program)
+ continue;
+ playMelodicNote(i, channel, note, velocity);
+ _lastVoice = i;
+ return;
+ }
+
+ // Then, try finding a free melodic voice of any kind.
+ for (uint i = (_lastVoice + 1) % kNumMelodic; i != _lastVoice; i = (i + 1) % kNumMelodic) {
+ if (_voices[i]._used)
+ continue;
+ programMelodicVoice(i, _channels[channel]._program);
+ playMelodicNote(i, channel, note, velocity);
+ _lastVoice = i;
+ return;
+ }
+
+ // Then just try finding a melodic voice with the same program,
+ // and steal it.
+ for (uint i = (_lastVoice + 1) % kNumMelodic; i != _lastVoice; i = (i + 1) % kNumMelodic) {
+ if (_voices[i]._program != _channels[channel]._program)
+ continue;
+ muteMelodicVoice(i);
+ playMelodicNote(i, channel, note, velocity);
+ _lastVoice = i;
+ return;
+ }
+
+ // Finally, just take control of the channel used least recently.
+ uint voiceId = 0;
+ uint32 bestTimestamp = 0xffffffff;
+ for (uint i = 0; i < kNumMelodic; ++i)
+ if (bestTimestamp > _voices[i]._timestamp) {
+ voiceId = i;
+ bestTimestamp = _voices[i]._timestamp;
+ }
+
+ //debug(1, "ran out of voices for channel %d, note %d, program %d: reused voice %d", channel, note, _channels[channel]._program, voiceId);
+ programMelodicVoice(voiceId, _channels[channel]._program);
+ playMelodicNote(voiceId, channel, note, velocity);
+ _lastVoice = voiceId;
+}
+
+// TODO: this doesn't match original
+void AdLibDriver::allNotesOff() {
+ for (uint i = 0; i < kNumMelodic; ++i) {
+ muteMelodicVoice(i);
+ _voices[i]._used = false;
+ }
+
+ _percussionMask = kDefaultPercussionMask;
+ _opl->writeReg(0xBD, kDefaultPercussionMask);
+}
+
+void AdLibDriver::setModulationWheel(uint8 channel, uint8 value) {
+ if (value >= 64)
+ _percussionMask |= 0x80;
+ else
+ _percussionMask &= 0x7f;
+
+ _opl->writeReg(0xBD, _percussionMask);
+}
+
+void AdLibDriver::setFootController(uint8 channel, uint8 value) {
+ _channels[channel]._pedal = (value >= 64);
+}
+
+void AdLibDriver::setVolume(uint8 channel, uint8 value) {
+ _channels[channel]._volume = value;
+}
+
+void AdLibDriver::setPitchBend(uint8 channel, int16 value) {
+ for (uint i = 0; i < kNumMelodic; ++i) {
+ if (_voices[i]._channel != channel || !_voices[i]._used)
+ continue;
+
+ // index into frequency table
+ uint f = 12 + (_voices[i]._key % 12);
+
+ int16 bendAmount = value;
+ if (bendAmount > 0) {
+ // bend up two semitones
+ bendAmount *= (melodicFrequencies[f + 2] - melodicFrequencies[f]);
+ } else {
+ // bend down two semitones
+ bendAmount *= (melodicFrequencies[f] - melodicFrequencies[f - 2]);
+ }
+ bendAmount /= 0x2000;
+ bendAmount += melodicFrequencies[f]; // add the base frequency
+ playNote(i, _voices[i]._octave, bendAmount);
+ _voices[i]._timestamp = g_system->getMillis();
+ }
+}
+
+void AdLibDriver::playNote(uint8 voice, uint8 octave, uint16 frequency) {
+ /* Percussions are always fed keyOn = 0 even to set the note, as they are activated using the
+ BD register instead. I wonder if they can just be fed the same value as melodic voice and
+ be done with it. */
+ uint8 keyOn = (voice < kNumMelodic) ? 0x20 : 0;
+
+ // key on, octave, high 2 bits of frequency
+ _opl->writeReg(0xB0 + voice, keyOn | ((octave & 7) << 2) | ((frequency >> 8) & 3));
+ // low 8 bits of frequency
+ _opl->writeReg(0xA0 + voice, frequency & 0xff);
+}
+
+void AdLibDriver::programOperatorSimple(uint8 offset, const OPLOperator &op) {
+ _opl->writeReg(0x40 + offset, op.levels & LEVEL_MASK);
+ _opl->writeReg(0x60 + offset, op.attackDecay);
+ _opl->writeReg(0x80 + offset, op.sustainRelease);
+}
+
+void AdLibDriver::programOperator(uint8 offset, const OPLOperator &op) {
+ _opl->writeReg(0x20 + offset, op.characteristic);
+ _opl->writeReg(0x60 + offset, op.attackDecay);
+ _opl->writeReg(0x80 + offset, op.sustainRelease);
+ _opl->writeReg(0xE0 + offset, op.waveform);
+ _opl->writeReg(0x40 + offset, op.levels);
+}
+
+const uint16 adlibLogVolume[] = {
+ 0, 37, 58, 73, 85, 95, 103, 110, 116, 121, 127, 131, 135, 139, 143, 146,
+ 149, 153, 155, 158, 161, 163, 165, 168, 170, 172, 174, 176, 178, 179, 181, 183,
+ 184, 186, 188, 189, 191, 192, 193, 195, 196, 197, 198, 200, 201, 202, 203, 204,
+ 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 219,
+ 220, 221, 222, 223, 223, 224, 225, 226, 226, 227, 228, 228, 229, 230, 231, 231,
+ 232, 233, 233, 234, 234, 235, 236, 236, 237, 237, 238, 239, 239, 240, 240, 241,
+ 241, 242, 242, 243, 244, 244, 245, 245, 246, 246, 247, 247, 248, 248, 248, 249,
+ 249, 250, 250, 251, 251, 252, 252, 253, 253, 253, 254, 254, 255, 255, 256, 256,
+ 256
+};
+
+void AdLibDriver::setOperatorLevel(uint8 offset, const OPLOperator &op, uint8 velocity, uint8 channel, bool forceVolume) {
+ uint8 programLevel = LEVEL_MASK;
+ if (!forceVolume)
+ programLevel -= (op.levels & LEVEL_MASK);
+
+ uint32 noteLevel = adlibLogVolume[velocity];
+ uint32 channelLevel = adlibLogVolume[_channels[channel]._volume];
+ // programLevel comes from the static data and is probably already in the correct logarithmic scale
+ uint32 finalLevel = LEVEL_MASK - ((noteLevel * channelLevel * programLevel) >> 16);
+
+ // high 2 bits are scaling level, the rest is (inversed) volume
+ _opl->writeReg(0x40 + offset, (op.levels & 0xc0) | (finalLevel & 0x3f));
+}
+
+const uint8 operatorOffsetsForPercussion[] = {
+ 0x11, // hi-hat
+ 0x15, // cymbal
+ 0x12, // tom tom
+ 0x14 // snare drum
+};
+
+void AdLibDriver::setupPercussion(const PercussionNote &note) {
+ if (note.percussion < 4) {
+ // simple percussion (1 operator)
+
+ // turn off relevant percussion
+ _percussionMask &= ~(1 << note.percussion);
+ _opl->writeReg(0xBD, _percussionMask);
+
+ programOperatorSimple(operatorOffsetsForPercussion[note.percussion], note.op[0]);
+ return;
+ }
+
+ // bass drum (2 operators)
+
+ // turn off bass drum
+ _percussionMask &= ~(0x10);
+ _opl->writeReg(0xBD, _percussionMask);
+
+ programOperator(0x10, note.op[0]);
+ programOperator(0x13, note.op[1]);
+
+ _opl->writeReg(0xC0 + 6, note.feedbackAlgo);
+}
+
+void AdLibDriver::playPercussion(uint8 channel, const PercussionNote &note, uint8 velocity) {
+ if (note.percussion < 4) {
+ // simple percussion (1 operator)
+
+ // turn off relevant percussion
+ _percussionMask &= ~(1 << note.percussion);
+ _opl->writeReg(0xBD, _percussionMask);
+
+ setOperatorLevel(operatorOffsetsForPercussion[note.percussion], note.op[0], velocity, channel, true);
+
+ if (note.percussion == 2) {
+ // tom tom
+ playNote(8, note.octave, note.frequency);
+ } else if (note.percussion == 3) {
+ // snare drum
+ playNote(7, note.octave, note.frequency);
+ }
+
+ // turn on relevant percussion
+ _percussionMask |= (1 << note.percussion);
+ _opl->writeReg(0xBD, _percussionMask);
+ return;
+ }
+
+ // turn off bass drum
+ _percussionMask &= ~(0x10);
+ _opl->writeReg(0xBD, _percussionMask);
+
+ if (note.feedbackAlgo & 1) {
+ // operators 1 and 2 in additive synthesis
+ setOperatorLevel(0x10, note.op[0], velocity, channel, true);
+ setOperatorLevel(0x13, note.op[1], velocity, channel, true);
+ } else {
+ // operator 2 is modulating operator 1
+ setOperatorLevel(0x13, note.op[1], velocity, channel, true);
+ }
+
+ playNote(6, note.octave, note.frequency);
+
+ // turn on bass drum
+ _percussionMask |= 0x10;
+ _opl->writeReg(0xBD, _percussionMask);
+}
+
+const uint8 offset1ForMelodic[kNumVoices] = { 0x0, 0x1, 0x2, 0x8, 0x9, 0xa, 0x10, 0x11, 0x12 };
+const uint8 offset2ForMelodic[kNumVoices] = { 0x3, 0x4, 0x5, 0xb, 0xc, 0xd, 0x13, 0x14, 0x15 };
+
+void AdLibDriver::programMelodicVoice(uint8 voice, uint8 program) {
+ assert(program < 128);
+ assert(voice < kNumMelodic);
+
+ const MelodicProgram &info = melodicPrograms[program];
+ uint8 offset1 = offset1ForMelodic[voice];
+ uint8 offset2 = offset2ForMelodic[voice];
+
+ // Start at lowest volume.
+ _opl->writeReg(0x40 + offset1, LEVEL_MASK);
+ _opl->writeReg(0x40 + offset2, LEVEL_MASK);
+
+ muteMelodicVoice(voice);
+
+ programOperator(offset1, info.op[0]);
+ programOperator(offset2, info.op[1]);
+
+ _opl->writeReg(0xC0 + voice, info.feedbackAlgo);
+}
+
+void AdLibDriver::playMelodicNote(uint8 voice, uint8 channel, uint8 note, uint8 velocity) {
+ assert(voice < kNumMelodic);
+
+ uint8 octave = note / 12;
+ uint8 f = 12 + (note % 12);
+
+ if (octave > 7)
+ octave = 7;
+
+ const MelodicProgram &info = melodicPrograms[_channels[channel]._program];
+ uint8 offset1 = offset1ForMelodic[voice];
+ uint8 offset2 = offset2ForMelodic[voice];
+
+ if (info.feedbackAlgo & 1) {
+ setOperatorLevel(offset1, info.op[0], velocity, channel, false);
+ setOperatorLevel(offset2, info.op[1], velocity, channel, false);
+ } else {
+ setOperatorLevel(offset2, info.op[1], velocity, channel, true);
+ }
+
+ playNote(voice, octave, melodicFrequencies[f]);
+
+ _voices[voice]._program = _channels[channel]._program;
+ _voices[voice]._key = note;
+ _voices[voice]._channel = channel;
+ _voices[voice]._timestamp = g_system->getMillis();
+ _voices[voice]._frequency = melodicFrequencies[f];
+ _voices[voice]._octave = octave;
+ _voices[voice]._used = true;
+}
+
+void AdLibDriver::muteMelodicVoice(uint8 voice) {
+ _opl->writeReg(0xB0 + voice, 0 | ((_voices[voice]._octave & 7) << 2) | ((_voices[voice]._frequency >> 8) & 3));
+}
+
+MidiChannel *AdLibDriver::allocateChannel() {
+ for (uint i = 0; i < 16; ++i) {
+ if (i == 9)
+ continue;
+
+ if (_channels[i].allocate())
+ return &_channels[i];
+ }
+
+ return NULL;
+}
+
+void AdLibDriver::generateSamples(int16 *buf, int len) {
+ memset(buf, 0, sizeof(int16) * len);
+ _opl->readBuffer(buf, len);
+}
+
+void AdLibDriver::initVoices() {
+ _percussionMask = kDefaultPercussionMask;
+ _opl->writeReg(0xBD, _percussionMask);
+
+ for (uint i = 0; i < 16; ++i)
+ _channels[i].reset();
+
+ for (uint i = 0; i < kNumMelodic; ++i) {
+ _voices[i]._key = 0xff;
+ _voices[i]._program = 0xff;
+ _voices[i]._channel = 0xff;
+ _voices[i]._timestamp = 0;
+ _voices[i]._frequency = 0;
+ _voices[i]._octave = 0;
+ _voices[i]._used = false;
+ }
+
+ for (uint i = 0; i < kNumPercussion; ++i)
+ _notesPerPercussion[i] = 0xff;
+
+ _lastVoice = 0;
+}
+
+} // namespace Parallaction
diff --git a/engines/parallaction/callables_ns.cpp b/engines/parallaction/callables_ns.cpp
index 64885c7ff3..c1720a1a8e 100644
--- a/engines/parallaction/callables_ns.cpp
+++ b/engines/parallaction/callables_ns.cpp
@@ -275,7 +275,7 @@ void Parallaction_ns::_c_contaFoglie(void *parm) {
if (num_foglie != 6)
return;
- _globalFlags |= 0x1000;
+ g_globalFlags |= 0x1000;
return;
}
@@ -286,7 +286,7 @@ void Parallaction_ns::_c_zeroFoglie(void *parm) {
}
void Parallaction_ns::_c_trasformata(void *parm) {
- _engineFlags ^= kEngineTransformedDonna;
+ g_engineFlags ^= kEngineTransformedDonna;
// No need to invoke changeCharacter here, as
// transformation happens on a location switch
// and character change is automatically triggered.
@@ -295,11 +295,11 @@ void Parallaction_ns::_c_trasformata(void *parm) {
void Parallaction_ns::_c_offMouse(void *parm) {
_input->setMouseState(MOUSE_DISABLED);
- _engineFlags |= kEngineBlockInput;
+ g_engineFlags |= kEngineBlockInput;
}
void Parallaction_ns::_c_onMouse(void *parm) {
- _engineFlags &= ~kEngineBlockInput;
+ g_engineFlags &= ~kEngineBlockInput;
_input->setMouseState(MOUSE_ENABLED_SHOW);
}
@@ -389,7 +389,7 @@ void Parallaction_ns::_c_finito(void *parm) {
}
void Parallaction_ns::_c_ridux(void *parm) {
- changeCharacter(_minidinoName);
+ changeCharacter(g_minidinoName);
return;
}
@@ -444,7 +444,7 @@ void Parallaction_ns::_c_startIntro(void *parm) {
_soundManI->playMusic();
}
- _engineFlags |= kEngineBlockInput;
+ g_engineFlags |= kEngineBlockInput;
_input->setMouseState(MOUSE_DISABLED);
_intro = true;
}
diff --git a/engines/parallaction/debug.cpp b/engines/parallaction/debug.cpp
index 0cb329e0f0..25acac9b06 100644
--- a/engines/parallaction/debug.cpp
+++ b/engines/parallaction/debug.cpp
@@ -103,7 +103,7 @@ bool Debugger::Cmd_Locations(int argc, const char **argv) {
bool Debugger::Cmd_GlobalFlags(int argc, const char **argv) {
- uint32 flags = _globalFlags;
+ uint32 flags = g_globalFlags;
DebugPrintf("+------------------------------+---------+\n"
"| flag name | value |\n"
@@ -128,10 +128,10 @@ bool Debugger::Cmd_ToggleGlobalFlag(int argc, const char **argv) {
DebugPrintf("invalid flag '%s'\n", argv[1]);
} else {
i--;
- if ((_globalFlags & (1 << i)) == 0)
- _globalFlags |= (1 << i);
+ if ((g_globalFlags & (1 << i)) == 0)
+ g_globalFlags |= (1 << i);
else
- _globalFlags &= ~(1 << i);
+ g_globalFlags &= ~(1 << i);
}
break;
diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp
index e0bd6a6677..78cc23311f 100644
--- a/engines/parallaction/dialogue.cpp
+++ b/engines/parallaction/dialogue.cpp
@@ -192,7 +192,7 @@ void DialogueManager::transitionToState(DialogueState newState) {
bool DialogueManager::testAnswerFlags(Answer *a) {
uint32 flags = _vm->getLocationFlags();
if (a->_yesFlags & kFlagsGlobal)
- flags = _globalFlags | kFlagsGlobal;
+ flags = g_globalFlags | kFlagsGlobal;
return ((a->_yesFlags & flags) == a->_yesFlags) && ((a->_noFlags & ~flags) == a->_noFlags);
}
@@ -370,9 +370,9 @@ protected:
bool _askPassword;
bool checkPassword() {
- return ((!scumm_stricmp(_vm->_char.getBaseName(), _doughName) && _vm->_password.hasPrefix("1732461")) ||
- (!scumm_stricmp(_vm->_char.getBaseName(), _donnaName) && _vm->_password.hasPrefix("1622")) ||
- (!scumm_stricmp(_vm->_char.getBaseName(), _dinoName) && _vm->_password.hasPrefix("179")));
+ return ((!scumm_stricmp(_vm->_char.getBaseName(), g_doughName) && _vm->_password.hasPrefix("1732461")) ||
+ (!scumm_stricmp(_vm->_char.getBaseName(), g_donnaName) && _vm->_password.hasPrefix("1622")) ||
+ (!scumm_stricmp(_vm->_char.getBaseName(), g_dinoName) && _vm->_password.hasPrefix("179")));
}
void resetPassword() {
diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp
index ee981a2c7d..8988897456 100644
--- a/engines/parallaction/disk_br.cpp
+++ b/engines/parallaction/disk_br.cpp
@@ -31,7 +31,7 @@
namespace Parallaction {
-extern byte _braAmigaFramesDefaultPalette[];
+extern byte braAmigaFramesDefaultPalette[];
struct Sprite {
uint16 size;
@@ -475,7 +475,7 @@ void AmigaDisk_br::loadBackground(BackgroundInfo& info, const char *filename) {
}
delete stream;
} else {
- p = _braAmigaFramesDefaultPalette;
+ p = braAmigaFramesDefaultPalette;
for (i = 0; i < 16; i++) {
r = *p >> 2;
p++;
diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp
index 8d4afd6847..bad854525d 100644
--- a/engines/parallaction/disk_ns.cpp
+++ b/engines/parallaction/disk_ns.cpp
@@ -262,8 +262,15 @@ Common::SeekableReadStream *DosDisk_ns::tryOpenFile(const char* name) {
Script* Disk_ns::loadLocation(const char *name) {
char path[PATH_LEN];
+ const char *charName = _vm->_char.getBaseName();
- sprintf(path, "%s%s/%s.loc", _vm->_char.getBaseName(), _language.c_str(), name);
+ // WORKAROUND: Special case for the Multilingual DOS version: during the ending
+ // sequence, it tries to load a non-existing file using "Dinor" as a character
+ // name. In this case, the character name should be just "dino".
+ if (!strcmp(charName, "Dinor"))
+ charName = "dino";
+
+ sprintf(path, "%s%s/%s.loc", charName, _language.c_str(), name);
debugC(3, kDebugDisk, "Disk_ns::loadLocation(%s): trying '%s'", name, path);
Common::SeekableReadStream *stream = tryOpenFile(path);
@@ -328,7 +335,7 @@ GfxObj* DosDisk_ns::loadTalk(const char *name) {
}
char v20[30];
- if (_engineFlags & kEngineTransformedDonna) {
+ if (g_engineFlags & kEngineTransformedDonna) {
sprintf(v20, "%stta.cnv", name);
} else {
sprintf(v20, "%stal.cnv", name);
diff --git a/engines/parallaction/exec.cpp b/engines/parallaction/exec.cpp
index 8594d02641..122abf9e0e 100644
--- a/engines/parallaction/exec.cpp
+++ b/engines/parallaction/exec.cpp
@@ -56,7 +56,7 @@ void ProgramExec::runScript(ProgramPtr script, AnimationPtr a) {
}
void ProgramExec::runScripts(ProgramList::iterator first, ProgramList::iterator last) {
- if (_engineFlags & kEnginePauseJobs) {
+ if (g_engineFlags & kEnginePauseJobs) {
return;
}
@@ -110,7 +110,7 @@ void CommandExec::runList(CommandList::iterator first, CommandList::iterator las
}
if (cmd->_flagsOn & kFlagsGlobal) {
- useFlags = _globalFlags | kFlagsGlobal;
+ useFlags = g_globalFlags | kFlagsGlobal;
useLocalFlags = false;
} else {
useFlags = _vm->getLocationFlags();
@@ -182,7 +182,7 @@ void CommandExec::suspend() {
}
void CommandExec::runSuspended() {
- if (_engineFlags & kEngineWalking) {
+ if (g_engineFlags & kEngineWalking) {
return;
}
diff --git a/engines/parallaction/exec_br.cpp b/engines/parallaction/exec_br.cpp
index 658ef5af82..985ea29311 100644
--- a/engines/parallaction/exec_br.cpp
+++ b/engines/parallaction/exec_br.cpp
@@ -307,7 +307,7 @@ DECLARE_COMMAND_OPCODE(testsfx) {
DECLARE_COMMAND_OPCODE(ret) {
- _engineFlags |= kEngineReturn;
+ g_engineFlags |= kEngineReturn;
}
@@ -327,7 +327,7 @@ DECLARE_INSTRUCTION_OPCODE(invalid) {
DECLARE_COMMAND_OPCODE(clear) {
if (ctxt._cmd->_flags & kFlagsGlobal) {
ctxt._cmd->_flags &= ~kFlagsGlobal;
- _globalFlags &= ~ctxt._cmd->_flags;
+ g_globalFlags &= ~ctxt._cmd->_flags;
} else {
_vm->clearLocationFlags(ctxt._cmd->_flags);
}
@@ -356,7 +356,7 @@ DECLARE_COMMAND_OPCODE(get) {
DECLARE_COMMAND_OPCODE(toggle) {
if (ctxt._cmd->_flags & kFlagsGlobal) {
ctxt._cmd->_flags &= ~kFlagsGlobal;
- _globalFlags ^= ctxt._cmd->_flags;
+ g_globalFlags ^= ctxt._cmd->_flags;
} else {
_vm->toggleLocationFlags(ctxt._cmd->_flags);
}
@@ -373,7 +373,7 @@ DECLARE_COMMAND_OPCODE(invalid) {
DECLARE_COMMAND_OPCODE(set) {
if (ctxt._cmd->_flags & kFlagsGlobal) {
ctxt._cmd->_flags &= ~kFlagsGlobal;
- _globalFlags |= ctxt._cmd->_flags;
+ g_globalFlags |= ctxt._cmd->_flags;
} else {
_vm->setLocationFlags(ctxt._cmd->_flags);
}
diff --git a/engines/parallaction/exec_ns.cpp b/engines/parallaction/exec_ns.cpp
index d8fbdea971..3ea4332e50 100644
--- a/engines/parallaction/exec_ns.cpp
+++ b/engines/parallaction/exec_ns.cpp
@@ -151,7 +151,7 @@ DECLARE_INSTRUCTION_OPCODE(call) {
DECLARE_INSTRUCTION_OPCODE(wait) {
- if (_engineFlags & kEngineWalking) {
+ if (g_engineFlags & kEngineWalking) {
ctxt._ip--;
ctxt._suspend = true;
}
@@ -198,7 +198,7 @@ DECLARE_COMMAND_OPCODE(invalid) {
DECLARE_COMMAND_OPCODE(set) {
if (ctxt._cmd->_flags & kFlagsGlobal) {
ctxt._cmd->_flags &= ~kFlagsGlobal;
- _globalFlags |= ctxt._cmd->_flags;
+ g_globalFlags |= ctxt._cmd->_flags;
} else {
_vm->setLocationFlags(ctxt._cmd->_flags);
}
@@ -208,7 +208,7 @@ DECLARE_COMMAND_OPCODE(set) {
DECLARE_COMMAND_OPCODE(clear) {
if (ctxt._cmd->_flags & kFlagsGlobal) {
ctxt._cmd->_flags &= ~kFlagsGlobal;
- _globalFlags &= ~ctxt._cmd->_flags;
+ g_globalFlags &= ~ctxt._cmd->_flags;
} else {
_vm->clearLocationFlags(ctxt._cmd->_flags);
}
@@ -267,7 +267,7 @@ DECLARE_COMMAND_OPCODE(call) {
DECLARE_COMMAND_OPCODE(toggle) {
if (ctxt._cmd->_flags & kFlagsGlobal) {
ctxt._cmd->_flags &= ~kFlagsGlobal;
- _globalFlags ^= ctxt._cmd->_flags;
+ g_globalFlags ^= ctxt._cmd->_flags;
} else {
_vm->toggleLocationFlags(ctxt._cmd->_flags);
}
diff --git a/engines/parallaction/font.cpp b/engines/parallaction/font.cpp
index d4c9aefd32..3b40960381 100644
--- a/engines/parallaction/font.cpp
+++ b/engines/parallaction/font.cpp
@@ -29,7 +29,7 @@
namespace Parallaction {
-extern byte _amigaTopazFont[];
+extern byte amigaTopazFont[];
class BraFont : public Font {
@@ -675,7 +675,7 @@ void Parallaction_ns::initFonts() {
_introFont = _disk->loadFont("slide");
} else {
_dialogueFont = _disk->loadFont("comic");
- Common::MemoryReadStream stream(_amigaTopazFont, 2600, DisposeAfterUse::NO);
+ Common::MemoryReadStream stream(amigaTopazFont, 2600, DisposeAfterUse::NO);
_labelFont = new AmigaFont(stream);
_menuFont = _disk->loadFont("slide");
_introFont = _disk->loadFont("intro");
diff --git a/engines/parallaction/gfxbase.cpp b/engines/parallaction/gfxbase.cpp
index 852235ce34..a9889cc7af 100644
--- a/engines/parallaction/gfxbase.cpp
+++ b/engines/parallaction/gfxbase.cpp
@@ -152,22 +152,22 @@ void Gfx::freeCharacterObjects() {
freeDialogueObjects();
}
-void BackgroundInfo::loadGfxObjMask(const char *name, GfxObj *obj) {
+void BackgroundInfo::loadGfxObjMask(Parallaction *vm, const char *name, GfxObj *obj) {
debugC(1, kDebugGraphics, "BackgroundInfo::loadGfxObjMask(\"%s\")", name);
Common::Rect rect;
obj->getRect(0, rect);
- MaskBuffer *buf = _vm->_disk->loadMask(name, rect.width(), rect.height());
+ MaskBuffer *buf = vm->_disk->loadMask(name, rect.width(), rect.height());
obj->_maskId = addMaskPatch(buf);
obj->_hasMask = true;
}
-void BackgroundInfo::loadGfxObjPath(const char *name, GfxObj *obj) {
+void BackgroundInfo::loadGfxObjPath(Parallaction *vm, const char *name, GfxObj *obj) {
Common::Rect rect;
obj->getRect(0, rect);
- PathBuffer *buf = _vm->_disk->loadPath(name, rect.width(), rect.height());
+ PathBuffer *buf = vm->_disk->loadPath(name, rect.width(), rect.height());
obj->_pathId = addPathPatch(buf);
obj->_hasPath = true;
@@ -226,6 +226,11 @@ void Gfx::drawGfxObject(GfxObj *obj, Graphics::Surface &surf) {
rect.translate(x, y);
data = obj->getData(obj->frame);
+ // WORKAROUND: During the end credits, game scripts try to show a
+ // non-existing frame. We change it to an existing one here.
+ if (obj->frame == 14 && obj->getNum() == 9 && !strcmp(obj->getName(), "Dinor"))
+ obj->frame = 8;
+
if (obj->getSize(obj->frame) == obj->getRawSize(obj->frame)) {
blt(rect, data, &surf, obj->layer, obj->scale, obj->transparentKey);
} else {
diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp
index 9855830478..59cd02e6ef 100644
--- a/engines/parallaction/graphics.cpp
+++ b/engines/parallaction/graphics.cpp
@@ -80,11 +80,11 @@ void drawCircle(int xCenter, int yCenter, int radius, int color, void (*plotProc
Palette::Palette() {
- int gameType = _vm->getGameType();
+ int gameType = g_vm->getGameType();
if (gameType == GType_Nippon) {
_colors = 32;
- _hb = (_vm->getPlatform() == Common::kPlatformAmiga);
+ _hb = (g_vm->getPlatform() == Common::kPlatformAmiga);
} else
if (gameType == GType_BRA) {
_colors = 256;
diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h
index f8cb4b3647..e9daabb194 100644
--- a/engines/parallaction/graphics.h
+++ b/engines/parallaction/graphics.h
@@ -377,14 +377,14 @@ public:
void toggleMaskPatch(uint id, int x, int y, bool apply);
uint16 getMaskLayer(uint16 z) const;
void finalizeMask();
- void loadGfxObjMask(const char *name, GfxObj *obj);
+ void loadGfxObjMask(Parallaction *vm, const char *name, GfxObj *obj);
// path management
bool hasPath();
uint addPathPatch(PathBuffer *patch);
void togglePathPatch(uint id, int x, int y, bool apply);
void finalizePath();
- void loadGfxObjPath(const char *name, GfxObj *obj);
+ void loadGfxObjPath(Parallaction *vm, const char *name, GfxObj *obj);
};
diff --git a/engines/parallaction/gui_ns.cpp b/engines/parallaction/gui_ns.cpp
index 3794aeae29..082c37f666 100644
--- a/engines/parallaction/gui_ns.cpp
+++ b/engines/parallaction/gui_ns.cpp
@@ -787,7 +787,7 @@ public:
}
destroyLabels();
- _engineFlags &= ~kEngineBlockInput;
+ g_engineFlags &= ~kEngineBlockInput;
return _helper->getState("selectcharacter");
}
diff --git a/engines/parallaction/input.cpp b/engines/parallaction/input.cpp
index 453bf9849d..4fbd9b99cc 100644
--- a/engines/parallaction/input.cpp
+++ b/engines/parallaction/input.cpp
@@ -188,15 +188,15 @@ int Input::updateGameInput() {
int event = kEvNone;
if (!isMouseEnabled() ||
- (_engineFlags & kEngineBlockInput) ||
- (_engineFlags & kEngineWalking) ||
- (_engineFlags & kEngineChangeLocation)) {
+ (g_engineFlags & kEngineBlockInput) ||
+ (g_engineFlags & kEngineWalking) ||
+ (g_engineFlags & kEngineChangeLocation)) {
debugC(3, kDebugInput, "updateGameInput: input flags (mouse: %i, block: %i, walking: %i, changeloc: %i)",
isMouseEnabled(),
- (_engineFlags & kEngineBlockInput) == 0,
- (_engineFlags & kEngineWalking) == 0,
- (_engineFlags & kEngineChangeLocation) == 0
+ (g_engineFlags & kEngineBlockInput) == 0,
+ (g_engineFlags & kEngineWalking) == 0,
+ (g_engineFlags & kEngineChangeLocation) == 0
);
return event;
@@ -289,7 +289,7 @@ void Input::walkTo(const Common::Point &dest) {
bool Input::translateGameInput() {
- if (_engineFlags & kEnginePauseJobs) {
+ if (g_engineFlags & kEnginePauseJobs) {
return false;
}
@@ -312,7 +312,7 @@ bool Input::translateGameInput() {
// test if mouse is hovering on an interactive zone for the currently selected inventory item
ZonePtr z = _vm->hitZone(_activeItem._id, mousePos.x, mousePos.y);
- if (((_mouseButtons == kMouseLeftUp) && (_activeItem._id == 0) && ((_engineFlags & kEngineWalking) == 0)) && ((!z) || (ACTIONTYPE(z) != kZoneCommand))) {
+ if (((_mouseButtons == kMouseLeftUp) && (_activeItem._id == 0) && ((g_engineFlags & kEngineWalking) == 0)) && ((!z) || (ACTIONTYPE(z) != kZoneCommand))) {
walkTo(mousePos);
return true;
}
@@ -361,7 +361,7 @@ void Input::enterInventoryMode() {
if (hitCharacter) {
if (_activeItem._id != 0) {
_activeItem._index = (_activeItem._id >> 16) & 0xFFFF;
- _engineFlags |= kEngineDragging;
+ g_engineFlags |= kEngineDragging;
} else {
setArrowCursor();
}
@@ -384,9 +384,9 @@ void Input::exitInventoryMode() {
int pos = _vm->getHoverInventoryItem(mousePos.x, mousePos.y);
_vm->highlightInventoryItem(-1); // disable
- if ((_engineFlags & kEngineDragging)) {
+ if ((g_engineFlags & kEngineDragging)) {
- _engineFlags &= ~kEngineDragging;
+ g_engineFlags &= ~kEngineDragging;
ZonePtr z = _vm->hitZone(kZoneMerge, _activeItem._index, _vm->getInventoryItemIndex(pos));
if (z) {
diff --git a/engines/parallaction/module.mk b/engines/parallaction/module.mk
index d65653cd92..36572a51df 100644
--- a/engines/parallaction/module.mk
+++ b/engines/parallaction/module.mk
@@ -1,6 +1,7 @@
MODULE := engines/parallaction
MODULE_OBJS := \
+ adlib.o \
balloons.o \
callables_br.o \
callables_ns.o \
diff --git a/engines/parallaction/objects.cpp b/engines/parallaction/objects.cpp
index d3529c5dd9..50556c3ec4 100644
--- a/engines/parallaction/objects.cpp
+++ b/engines/parallaction/objects.cpp
@@ -203,7 +203,7 @@ Zone::Zone() {
}
Zone::~Zone() {
- _vm->_gfx->unregisterLabel(_label);
+ g_vm->_gfx->unregisterLabel(_label);
delete _label;
}
@@ -325,7 +325,7 @@ int16 ScriptVar::getValue() {
}
if (_flags & kParaRandom) {
- return (_vm->_rnd.getRandomNumber(65536) * _value) >> 16;
+ return (g_vm->_rnd.getRandomNumber(65536) * _value) >> 16;
}
error("Parameter is not an r-value");
diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp
index 3b1b7d54a0..e6ef53aa78 100644
--- a/engines/parallaction/parallaction.cpp
+++ b/engines/parallaction/parallaction.cpp
@@ -33,12 +33,12 @@
#include "parallaction/walk.h"
namespace Parallaction {
-Parallaction *_vm = NULL;
+Parallaction *g_vm = NULL;
// public stuff
-char _saveData1[30] = { '\0' };
-uint32 _engineFlags = 0;
-uint32 _globalFlags = 0;
+char g_saveData1[30] = { '\0' };
+uint32 g_engineFlags = 0;
+uint32 g_globalFlags = 0;
// private stuff
@@ -48,7 +48,7 @@ Parallaction::Parallaction(OSystem *syst, const PARALLACTIONGameDescription *gam
// Setup mixer
syncSoundSettings();
- _vm = this;
+ g_vm = this;
DebugMan.addDebugChannel(kDebugDialogue, "dialogue", "Dialogues debug level");
DebugMan.addDebugChannel(kDebugParser, "parser", "Parser debug level");
DebugMan.addDebugChannel(kDebugDisk, "disk", "Disk debug level");
@@ -87,7 +87,7 @@ Parallaction::~Parallaction() {
Common::Error Parallaction::init() {
_gameType = getGameType();
- _engineFlags = 0;
+ g_engineFlags = 0;
_objectsNames = NULL;
_globalFlagsNames = NULL;
_location._hasSound = false;
@@ -129,13 +129,9 @@ GUI::Debugger *Parallaction::getDebugger() {
return _debugger;
}
-bool canScroll() {
- return (_vm->_gfx->_backgroundInfo->width > _vm->_screenWidth);
-}
-
void Parallaction::updateView() {
- if ((_engineFlags & kEnginePauseJobs) && (_input->_inputMode != Input::kInputModeInventory)) {
+ if ((g_engineFlags & kEnginePauseJobs) && (_input->_inputMode != Input::kInputModeInventory)) {
return;
}
@@ -147,14 +143,14 @@ void Parallaction::updateView() {
void Parallaction::pauseJobs() {
debugC(9, kDebugExec, "pausing jobs execution");
- _engineFlags |= kEnginePauseJobs;
+ g_engineFlags |= kEnginePauseJobs;
return;
}
void Parallaction::resumeJobs() {
debugC(9, kDebugExec, "resuming jobs execution");
- _engineFlags &= ~kEnginePauseJobs;
+ g_engineFlags &= ~kEnginePauseJobs;
return;
}
@@ -265,7 +261,7 @@ void Parallaction::runGameFrame(int event) {
if (shouldQuit())
return;
- if (_engineFlags & kEngineChangeLocation) {
+ if (g_engineFlags & kEngineChangeLocation) {
changeLocation();
}
@@ -900,14 +896,14 @@ void CharacterName::bind(const char *name) {
if (!_dummy) {
if (!strcmp(name, "donna")) {
- _engineFlags &= ~kEngineTransformedDonna;
+ g_engineFlags &= ~kEngineTransformedDonna;
} else {
- if (_engineFlags & kEngineTransformedDonna) {
+ if (g_engineFlags & kEngineTransformedDonna) {
_suffix = _suffixTras;
} else {
const char *s = strstr(name, "tras");
if (s) {
- _engineFlags |= kEngineTransformedDonna;
+ g_engineFlags |= kEngineTransformedDonna;
_suffix = _suffixTras;
end = s;
}
@@ -953,7 +949,7 @@ void Parallaction::beep() {
void Parallaction::scheduleLocationSwitch(const char *location) {
debugC(9, kDebugExec, "scheduleLocationSwitch(%s)\n", location);
_newLocationName = location;
- _engineFlags |= kEngineChangeLocation;
+ g_engineFlags |= kEngineChangeLocation;
}
} // End of namespace Parallaction
diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h
index 0d56b62e2f..2dbb0227d6 100644
--- a/engines/parallaction/parallaction.h
+++ b/engines/parallaction/parallaction.h
@@ -104,17 +104,17 @@ struct PARALLACTIONGameDescription;
-extern uint32 _engineFlags;
-extern char _saveData1[];
-extern uint32 _globalFlags;
-extern const char *_dinoName;
-extern const char *_donnaName;
-extern const char *_doughName;
-extern const char *_drkiName;
-extern const char *_minidinoName;
-extern const char *_minidonnaName;
-extern const char *_minidoughName;
-extern const char *_minidrkiName;
+extern uint32 g_engineFlags;
+extern char g_saveData1[];
+extern uint32 g_globalFlags;
+extern const char *g_dinoName;
+extern const char *g_donnaName;
+extern const char *g_doughName;
+extern const char *g_drkiName;
+extern const char *g_minidinoName;
+extern const char *g_minidonnaName;
+extern const char *g_minidoughName;
+extern const char *g_minidrkiName;
@@ -601,7 +601,7 @@ private:
void _c_password(void *);
};
-extern Parallaction *_vm;
+extern Parallaction *g_vm;
} // End of namespace Parallaction
diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp
index 658a8e8795..07755fac5f 100644
--- a/engines/parallaction/parallaction_br.cpp
+++ b/engines/parallaction/parallaction_br.cpp
@@ -79,7 +79,7 @@ Common::Error Parallaction_br::init() {
_cmdExec = new CommandExec_br(this);
_programExec = new ProgramExec_br(this);
- _walker = new PathWalker_BR;
+ _walker = new PathWalker_BR(this);
_part = -1;
_nextPart = -1;
@@ -161,10 +161,10 @@ Common::Error Parallaction_br::go() {
// initCharacter();
- while (((_engineFlags & kEngineReturn) == 0) && (!shouldQuit())) {
+ while (((g_engineFlags & kEngineReturn) == 0) && (!shouldQuit())) {
runGame();
}
- _engineFlags &= ~kEngineReturn;
+ g_engineFlags &= ~kEngineReturn;
cleanupGame();
}
@@ -259,7 +259,7 @@ void Parallaction_br::cleanupGame() {
_countersNames = 0;
_numLocations = 0;
- _globalFlags = 0;
+ g_globalFlags = 0;
memset(_localFlags, 0, sizeof(_localFlags));
memset(_locationNames, 0, sizeof(_locationNames));
memset(_zoneFlags, 0, sizeof(_zoneFlags));
@@ -275,7 +275,7 @@ void Parallaction_br::changeLocation() {
cleanupGame();
// more cleanup needed for part changes (see also saveload)
- _globalFlags = 0;
+ g_globalFlags = 0;
cleanInventory(true);
strcpy(_characterName1, "null");
@@ -358,7 +358,7 @@ void Parallaction_br::changeLocation() {
// TODO: implement the music commands which control music execution
_soundMan->execute(SC_PLAYMUSIC);
- _engineFlags &= ~kEngineChangeLocation;
+ g_engineFlags &= ~kEngineChangeLocation;
_newLocationName.clear();
_nextPart = -1;
}
@@ -548,7 +548,7 @@ void Parallaction_br::scheduleWalk(int16 x, int16 y, bool fromUser) {
}
}
- _engineFlags |= kEngineWalking;
+ g_engineFlags |= kEngineWalking;
}
void Parallaction_br::setFollower(const Common::String &name) {
diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp
index 0b92db1f0a..d33be0aa47 100644
--- a/engines/parallaction/parallaction_ns.cpp
+++ b/engines/parallaction/parallaction_ns.cpp
@@ -182,7 +182,7 @@ Common::Error Parallaction_ns::init() {
_cmdExec = new CommandExec_ns(this);
_programExec = new ProgramExec_ns(this);
- _walker = new PathWalker_NS;
+ _walker = new PathWalker_NS(this);
_sarcophagusDeltaX = 0;
_movingSarcophagus = false;
@@ -310,6 +310,7 @@ void Parallaction_ns::changeBackground(const char* background, const char* mask,
_system->delayMillis(20);
_gfx->setPalette(pal);
_gfx->updateScreen();
+ return;
}
if (path == 0) {
@@ -382,8 +383,8 @@ void Parallaction_ns::changeLocation() {
changeCharacter(locname.character());
}
- strcpy(_saveData1, locname.location());
- parseLocation(_saveData1);
+ strcpy(g_saveData1, locname.location());
+ parseLocation(g_saveData1);
if (_location._startPosition.x != -1000) {
_char._ani->setX(_location._startPosition.x);
@@ -399,7 +400,7 @@ void Parallaction_ns::changeLocation() {
// BUG #1837503: kEngineChangeLocation flag must be cleared *before* commands
// and acommands are executed, so that it can be set again if needed.
- _engineFlags &= ~kEngineChangeLocation;
+ g_engineFlags &= ~kEngineChangeLocation;
_cmdExec->run(_location._commands);
@@ -412,6 +413,11 @@ void Parallaction_ns::changeLocation() {
if (!_intro) {
_input->setMouseState(oldMouseState);
+ // WORKAROUND: Fix a script bug in the Multilingual DOS version of
+ // Nippon Safes: the mouse cursor is incorrectly hidden outside the
+ // cave at the end of the game. Fix it here.
+ if (!strcmp(_location._name, "ingressocav"))
+ _input->setMouseState(MOUSE_ENABLED_SHOW);
}
debugC(1, kDebugExec, "changeLocation() done");
@@ -526,10 +532,10 @@ void Parallaction_ns::cleanupGame() {
_soundManI->stopMusic();
_inTestResult = false;
- _engineFlags &= ~kEngineTransformedDonna;
+ g_engineFlags &= ~kEngineTransformedDonna;
_numLocations = 0;
- _globalFlags = 0;
+ g_globalFlags = 0;
memset(_localFlags, 0, sizeof(_localFlags));
memset(_locationNames, 0, sizeof(_locationNames));
@@ -553,7 +559,7 @@ void Parallaction_ns::scheduleWalk(int16 x, int16 y, bool fromUser) {
}
_walker->buildPath(a, x, y);
- _engineFlags |= kEngineWalking;
+ g_engineFlags |= kEngineWalking;
}
}// namespace Parallaction
diff --git a/engines/parallaction/parser_br.cpp b/engines/parallaction/parser_br.cpp
index 0904dbf655..e7f1b1b1ed 100644
--- a/engines/parallaction/parser_br.cpp
+++ b/engines/parallaction/parser_br.cpp
@@ -767,10 +767,10 @@ void LocationParser_br::parseGetData(ZonePtr z) {
data->_gfxobj = obj;
} else
if (!scumm_stricmp(_tokens[0], "mask")) {
- _out->_info->loadGfxObjMask(_tokens[1], data->_gfxobj);
+ _out->_info->loadGfxObjMask(_vm, _tokens[1], data->_gfxobj);
} else
if (!scumm_stricmp(_tokens[0], "path")) {
- _out->_info->loadGfxObjPath(_tokens[1], data->_gfxobj);
+ _out->_info->loadGfxObjPath(_vm, _tokens[1], data->_gfxobj);
} else
if (!scumm_stricmp(_tokens[0], "icon")) {
data->_getIcon = 4 + _vm->_objectsNames->lookup(_tokens[1]);
diff --git a/engines/parallaction/parser_ns.cpp b/engines/parallaction/parser_ns.cpp
index f1d1db53e9..41ff74f0b4 100644
--- a/engines/parallaction/parser_ns.cpp
+++ b/engines/parallaction/parser_ns.cpp
@@ -246,7 +246,7 @@ DECLARE_ANIM_PARSER(file) {
char vC8[200];
strcpy(vC8, _tokens[1]);
- if (_engineFlags & kEngineTransformedDonna) {
+ if (g_engineFlags & kEngineTransformedDonna) {
if (!scumm_stricmp(_tokens[1], "donnap") || !scumm_stricmp(_tokens[1], "donnapa")) {
strcat(vC8, "tras");
}
diff --git a/engines/parallaction/saveload.cpp b/engines/parallaction/saveload.cpp
index 8de2d89b18..2ecc5377a4 100644
--- a/engines/parallaction/saveload.cpp
+++ b/engines/parallaction/saveload.cpp
@@ -88,7 +88,7 @@ void SaveLoad_ns::doLoadGame(uint16 slot) {
_vm->_score = atoi(s.c_str());
s = f->readLine();
- _globalFlags = atoi(s.c_str());
+ g_globalFlags = atoi(s.c_str());
s = f->readLine();
_vm->_numLocations = atoi(s.c_str());
@@ -151,7 +151,7 @@ void SaveLoad_ns::doSaveGame(uint16 slot, const char* name) {
sprintf(s, "%s\n", _vm->_char.getFullName());
f->writeString(s);
- sprintf(s, "%s\n", _saveData1);
+ sprintf(s, "%s\n", g_saveData1);
f->writeString(s);
sprintf(s, "%d\n", _vm->_char._ani->getX());
f->writeString(s);
@@ -159,7 +159,7 @@ void SaveLoad_ns::doSaveGame(uint16 slot, const char* name) {
f->writeString(s);
sprintf(s, "%d\n", _vm->_score);
f->writeString(s);
- sprintf(s, "%u\n", _globalFlags);
+ sprintf(s, "%u\n", g_globalFlags);
f->writeString(s);
sprintf(s, "%d\n", _vm->_numLocations);
diff --git a/engines/parallaction/sound.h b/engines/parallaction/sound.h
index e875e69334..e12e50e278 100644
--- a/engines/parallaction/sound.h
+++ b/engines/parallaction/sound.h
@@ -33,6 +33,7 @@
#define PATH_LEN 200
class MidiParser;
+class MidiDriver;
namespace Parallaction {
@@ -41,6 +42,7 @@ class MidiPlayer;
class Parallaction_br;
class MidiPlayer_MSC;
+MidiDriver *createAdLibDriver();
class SoundManImpl {
public:
diff --git a/engines/parallaction/sound_br.cpp b/engines/parallaction/sound_br.cpp
index 0925e55309..ad510eb1f1 100644
--- a/engines/parallaction/sound_br.cpp
+++ b/engines/parallaction/sound_br.cpp
@@ -91,20 +91,20 @@ public:
};
void MidiParser_MSC::parseMetaEvent(EventInfo &info) {
- uint8 type = read1(_position._play_pos);
- uint8 len = read1(_position._play_pos);
+ uint8 type = read1(_position._playPos);
+ uint8 len = read1(_position._playPos);
info.ext.type = type;
info.length = len;
info.ext.data = 0;
if (type == 0x51) {
- info.ext.data = _position._play_pos;
+ info.ext.data = _position._playPos;
} else {
warning("unknown meta event 0x%02X", type);
info.ext.type = 0;
}
- _position._play_pos += len;
+ _position._playPos += len;
}
void MidiParser_MSC::parseMidiEvent(EventInfo &info) {
@@ -116,13 +116,13 @@ void MidiParser_MSC::parseMidiEvent(EventInfo &info) {
case 0xA:
case 0xB:
case 0xE:
- info.basic.param1 = read1(_position._play_pos);
- info.basic.param2 = read1(_position._play_pos);
+ info.basic.param1 = read1(_position._playPos);
+ info.basic.param2 = read1(_position._playPos);
break;
case 0xC:
case 0xD:
- info.basic.param1 = read1(_position._play_pos);
+ info.basic.param1 = read1(_position._playPos);
info.basic.param2 = 0;
break;
@@ -135,9 +135,9 @@ void MidiParser_MSC::parseMidiEvent(EventInfo &info) {
}
void MidiParser_MSC::parseNextEvent(EventInfo &info) {
- info.start = _position._play_pos;
+ info.start = _position._playPos;
- if (_position._play_pos >= _trackEnd) {
+ if (_position._playPos >= _trackEnd) {
// fake an end-of-track meta event
info.delta = 0;
info.event = 0xFF;
@@ -146,8 +146,9 @@ void MidiParser_MSC::parseNextEvent(EventInfo &info) {
return;
}
- info.delta = readVLQ(_position._play_pos);
- info.event = read1(_position._play_pos);
+ info.length = 0;
+ info.delta = readVLQ(_position._playPos);
+ info.event = read1(_position._playPos);
if (info.event == 0xFF) {
parseMetaEvent(info);
@@ -155,7 +156,7 @@ void MidiParser_MSC::parseNextEvent(EventInfo &info) {
}
if (info.event < 0x80) {
- _position._play_pos--;
+ _position._playPos--;
info.event = _lastEvent;
}
@@ -185,7 +186,7 @@ bool MidiParser_MSC::loadMusic(byte *data, uint32 size) {
_lastEvent = 0;
_trackEnd = data + size;
- _num_tracks = 1;
+ _numTracks = 1;
_tracks[0] = pos;
setTempo(500000);
@@ -224,7 +225,12 @@ MidiPlayer_MSC::MidiPlayer_MSC()
: _paused(false) {
MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
- _driver = MidiDriver::createMidi(dev);
+ const MusicType musicType = MidiDriver::getMusicType(dev);
+ if (musicType == MT_ADLIB) {
+ _driver = createAdLibDriver();
+ } else {
+ _driver = MidiDriver::createMidi(dev);
+ }
assert(_driver);
int ret = _driver->open();
diff --git a/engines/parallaction/sound_ns.cpp b/engines/parallaction/sound_ns.cpp
index dcc71e4f2f..0ee3d73556 100644
--- a/engines/parallaction/sound_ns.cpp
+++ b/engines/parallaction/sound_ns.cpp
@@ -168,13 +168,13 @@ void DosSoundMan_ns::playCharacterMusic(const char *character) {
char *name = const_cast<char *>(character);
const char *newMusicFile = 0;
- if (!scumm_stricmp(name, _dinoName)) {
+ if (!scumm_stricmp(name, g_dinoName)) {
newMusicFile = "dino";
} else
- if (!scumm_stricmp(name, _donnaName)) {
+ if (!scumm_stricmp(name, g_donnaName)) {
newMusicFile = "donna";
} else
- if (!scumm_stricmp(name, _doughName)) {
+ if (!scumm_stricmp(name, g_doughName)) {
newMusicFile = "nuts";
} else {
warning("unknown character '%s' in DosSoundMan_ns_ns::playCharacterMusic", character);
diff --git a/engines/parallaction/staticres.cpp b/engines/parallaction/staticres.cpp
index 73e78cae3c..f09b1241bc 100644
--- a/engines/parallaction/staticres.cpp
+++ b/engines/parallaction/staticres.cpp
@@ -89,14 +89,14 @@ byte Input::_resMouseArrow_BR_Amiga[512] = {
/*
This palette snippet is used for animations in Big Red Adventure.
*/
-byte _braAmigaFramesDefaultPalette[48] = {
+byte braAmigaFramesDefaultPalette[48] = {
0x00, 0x00, 0x00, 0x14, 0x14, 0x14, 0xFF, 0xE0, 0xCF, 0x7F, 0x7F, 0x7F, 0xD9, 0x9C, 0x84, 0x00,
0x9E, 0xF0, 0x91, 0xCC, 0x36, 0xFF, 0x6A, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0x11, 0xB0, 0xEE,
0xF0, 0xFF, 0x17, 0x3D, 0x18, 0xAC, 0x3A, 0xB0, 0x00, 0x00, 0x7D, 0x00, 0x00, 0xFF, 0xA8, 0xFF,
};
-byte _amigaTopazFont[2600] = {
+byte amigaTopazFont[2600] = {
0x00, 0x00, 0x03, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x79, 0x00, 0x00, 0x03, 0xe9, 0x00, 0x00, 0x02, 0x79,
0x70, 0xff, 0x4e, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
@@ -263,7 +263,7 @@ byte _amigaTopazFont[2600] = {
};
-const char *_callableNamesRes_ns[] = {
+const char *callableNamesRes_ns[] = {
"Projector",
"HBOff",
"StartIntro",
@@ -292,7 +292,7 @@ const char *_callableNamesRes_ns[] = {
};
-const char *_callableNamesRes_br[] = {
+const char *callableNamesRes_br[] = {
"blufade",
"resetpalette",
"ferrcycle",
@@ -301,15 +301,15 @@ const char *_callableNamesRes_br[] = {
"password"
};
-const char *_dinoName = "dino";
-const char *_donnaName = "donna";
-const char *_doughName = "dough";
-const char *_drkiName = "drki";
+const char *g_dinoName = "dino";
+const char *g_donnaName = "donna";
+const char *g_doughName = "dough";
+const char *g_drkiName = "drki";
-const char *_minidinoName = "minidino";
-const char *_minidonnaName = "minidonna";
-const char *_minidoughName = "minidough";
-const char *_minidrkiName = "minidrki";
+const char *g_minidinoName = "minidino";
+const char *g_minidonnaName = "minidonna";
+const char *g_minidoughName = "minidough";
+const char *g_minidrkiName = "minidrki";
#define CALLABLE_NS(x) &Parallaction_ns::x
@@ -391,7 +391,7 @@ const Parallaction_br::Callable Parallaction_br::_amigaCallables[] = {
void Parallaction_ns::initResources() {
- _callableNames = new Table(ARRAYSIZE(_callableNamesRes_ns), _callableNamesRes_ns);
+ _callableNames = new Table(ARRAYSIZE(callableNamesRes_ns), callableNamesRes_ns);
_localFlagNames = new FixedTable(NUM_LOCATIONS, 1);
_localFlagNames->addData("visited");
@@ -406,7 +406,7 @@ void Parallaction_ns::initResources() {
void Parallaction_br::initResources() {
- _callableNames = new Table(ARRAYSIZE(_callableNamesRes_br), _callableNamesRes_br);
+ _callableNames = new Table(ARRAYSIZE(callableNamesRes_br), callableNamesRes_br);
_localFlagNames = new FixedTable(NUM_LOCATIONS, 2);
_localFlagNames->addData("visited");
diff --git a/engines/parallaction/walk.cpp b/engines/parallaction/walk.cpp
index 53237db4ef..19162cd7db 100644
--- a/engines/parallaction/walk.cpp
+++ b/engines/parallaction/walk.cpp
@@ -55,27 +55,27 @@ WalkFrames _char24WalkFrames_NS = {
};
static int getPathWidth() {
- if (!_vm->_gfx->_backgroundInfo->_path) {
+ if (!g_vm->_gfx->_backgroundInfo->_path) {
warning("getPathWidth() _path is NULL!");
return 0;
} else
- return _vm->_gfx->_backgroundInfo->_path->w;
+ return g_vm->_gfx->_backgroundInfo->_path->w;
}
static int getPathHeight() {
- if (!_vm->_gfx->_backgroundInfo->_path) {
+ if (!g_vm->_gfx->_backgroundInfo->_path) {
warning("getPathHeight() _path is NULL!");
return 0;
} else
- return _vm->_gfx->_backgroundInfo->_path->h;
+ return g_vm->_gfx->_backgroundInfo->_path->h;
}
static bool isPathClear(uint16 x, uint16 y) {
- if (!_vm->_gfx->_backgroundInfo->_path) {
+ if (!g_vm->_gfx->_backgroundInfo->_path) {
warning("isPathClear() _path is NULL!");
return false;
} else
- return (_vm->_gfx->_backgroundInfo->_path->getValue(x, y) ? true : false);
+ return (g_vm->_gfx->_backgroundInfo->_path->getValue(x, y) ? true : false);
}
// adjusts position towards nearest walkable point
@@ -306,7 +306,7 @@ void PathWalker_NS::checkDoor(const Common::Point &foot) {
}
void PathWalker_NS::finalizeWalk() {
- _engineFlags &= ~kEngineWalking;
+ g_engineFlags &= ~kEngineWalking;
Common::Point foot;
_a->getFoot(foot);
@@ -316,7 +316,7 @@ void PathWalker_NS::finalizeWalk() {
}
void PathWalker_NS::walk() {
- if ((_engineFlags & kEngineWalking) == 0) {
+ if ((g_engineFlags & kEngineWalking) == 0) {
return;
}
@@ -382,7 +382,7 @@ void PathWalker_NS::updateDirection(const Common::Point& pos, const Common::Poin
_a->setF(frames->firstWalkFrame[_direction] + (_step / frames->frameRepeat[_direction]) % frames->numWalkFrames[_direction]);
}
-PathWalker_NS::PathWalker_NS() : _direction(WALK_DOWN), _step(0) {
+PathWalker_NS::PathWalker_NS(Parallaction *vm) : _direction(WALK_DOWN), _step(0), _vm(vm) {
}
bool PathWalker_BR::directPathExists(const Common::Point &from, const Common::Point &to) {
@@ -481,7 +481,7 @@ void PathWalker_BR::buildPath(State &s, uint16 x, uint16 y) {
}
void PathWalker_BR::finalizeWalk(State &s) {
- _engineFlags &= ~kEngineWalking;
+ g_engineFlags &= ~kEngineWalking;
Common::Point foot;
_character._a->getFoot(foot);
@@ -508,8 +508,8 @@ void PathWalker_BR::finalizeWalk(State &s) {
#if 0
// TODO: Input::walkTo must be extended to support destination frame in addition to coordinates
- if (_engineFlags & FINAL_WALK_FRAME) { // this flag is set in readInput()
- _engineFlags &= ~FINAL_WALK_FRAME;
+ if (g_engineFlags & FINAL_WALK_FRAME) { // this flag is set in readInput()
+ g_engineFlags &= ~FINAL_WALK_FRAME;
_ch._a->_frame = _moveToF; // from readInput()...
} else {
_ch._a->_frame = _dirFrame; // from walk()
@@ -523,7 +523,7 @@ void PathWalker_BR::finalizeWalk(State &s) {
}
void PathWalker_BR::walk() {
- if ((_engineFlags & kEngineWalking) == 0) {
+ if ((g_engineFlags & kEngineWalking) == 0) {
return;
}
@@ -714,7 +714,7 @@ void PathWalker_BR::doWalk(State &s) {
}
}
-PathWalker_BR::PathWalker_BR() {
+PathWalker_BR::PathWalker_BR(Parallaction *vm) : _vm(vm) {
_character._active = false;
_character._step = 0;
_follower._active = false;
diff --git a/engines/parallaction/walk.h b/engines/parallaction/walk.h
index 6796991f9d..ae6db6eaf1 100644
--- a/engines/parallaction/walk.h
+++ b/engines/parallaction/walk.h
@@ -49,8 +49,10 @@ class PathWalker_NS {
void checkDoor(const Common::Point &foot);
void updateDirection(const Common::Point& pos, const Common::Point& to);
+ Parallaction *_vm;
+
public:
- PathWalker_NS();
+ PathWalker_NS(Parallaction *vm);
void buildPath(AnimationPtr a, uint16 x, uint16 y);
void walk();
@@ -79,8 +81,10 @@ class PathWalker_BR {
void doWalk(State &s);
void checkTrap(const Common::Point &p);
+ Parallaction *_vm;
+
public:
- PathWalker_BR();
+ PathWalker_BR(Parallaction *vm);
~PathWalker_BR() { }
void setCharacterPath(AnimationPtr a, uint16 x, uint16 y);
diff --git a/engines/pegasus/ai/ai_action.cpp b/engines/pegasus/ai/ai_action.cpp
new file mode 100644
index 0000000000..38d639038f
--- /dev/null
+++ b/engines/pegasus/ai/ai_action.cpp
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/ai/ai_action.h"
+#include "pegasus/ai/ai_area.h"
+
+namespace Pegasus {
+
+AICompoundAction::~AICompoundAction() {
+ for (AIActionList::iterator it = _compoundActions.begin(); it != _compoundActions.end(); it++)
+ delete *it;
+}
+
+void AICompoundAction::performAIAction(AIRule *rule) {
+ for (AIActionList::iterator it = _compoundActions.begin(); it != _compoundActions.end(); it++)
+ (*it)->performAIAction(rule);
+}
+
+AIPlayMessageAction::AIPlayMessageAction(const Common::String &movieName, bool keepLastFrame, const InputBits interruptionFilter) {
+ _movieName = movieName;
+ _keepLastFrame = keepLastFrame;
+ _interruptionFilter = interruptionFilter;
+}
+
+void AIPlayMessageAction::performAIAction(AIRule *) {
+ if (g_AIArea) {
+ g_AIArea->checkMiddleArea();
+ g_AIArea->playAIMovie(kRightAreaSignature, _movieName, _keepLastFrame, _interruptionFilter);
+ }
+}
+
+AIStartTimerAction::AIStartTimerAction(AITimerCondition *timerCondition) {
+ _timerCondition = timerCondition;
+}
+
+void AIStartTimerAction::performAIAction(AIRule *) {
+ _timerCondition->startTimer();
+}
+
+AIActivateRuleAction::AIActivateRuleAction(AIRule *rule) {
+ _rule = rule;
+}
+
+void AIActivateRuleAction::performAIAction(AIRule *) {
+ _rule->activateRule();
+}
+
+AIDeactivateRuleAction::AIDeactivateRuleAction(AIRule *rule) {
+ _rule = rule;
+}
+
+void AIDeactivateRuleAction::performAIAction(AIRule *) {
+ _rule->deactivateRule();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/ai/ai_action.h b/engines/pegasus/ai/ai_action.h
new file mode 100644
index 0000000000..6eac976f9c
--- /dev/null
+++ b/engines/pegasus/ai/ai_action.h
@@ -0,0 +1,136 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_AI_AIACTION_H
+#define PEGASUS_AI_AIACTION_H
+
+#include "common/list.h"
+
+#include "pegasus/input.h"
+#include "pegasus/types.h"
+
+namespace Pegasus {
+
+class AIRule;
+class AITimerCondition;
+
+/////////////////////////////////////////////
+//
+// AIAction
+
+class AIAction {
+friend class AIRule;
+public:
+ AIAction() { _actionCount = 1; }
+ virtual ~AIAction() {}
+
+ virtual void performAIAction(AIRule *) = 0;
+
+ void setActionCount(const uint32 count) { _actionCount = count; }
+
+protected:
+ uint32 _actionCount;
+};
+
+typedef Common::List<AIAction *> AIActionList;
+
+/////////////////////////////////////////////
+//
+// AICompoundAction
+
+class AICompoundAction : public AIAction {
+public:
+ AICompoundAction() {}
+ virtual ~AICompoundAction();
+
+ void addAction(AIAction *action) { _compoundActions.push_back(action); }
+
+ virtual void performAIAction(AIRule *);
+
+protected:
+ AIActionList _compoundActions;
+};
+
+/////////////////////////////////////////////
+//
+// AIPlayMessageAction
+
+class AIPlayMessageAction : public AIAction {
+public:
+ AIPlayMessageAction(const Common::String &movieName, bool keepLastFrame, const InputBits = kWarningInterruption);
+
+ virtual void performAIAction(AIRule *);
+
+protected:
+ Common::String _movieName;
+ InputBits _interruptionFilter;
+ bool _keepLastFrame;
+};
+
+/////////////////////////////////////////////
+//
+// AIStartTimerAction
+
+class AIStartTimerAction : public AIAction {
+public:
+ AIStartTimerAction(AITimerCondition *);
+
+ virtual void performAIAction(AIRule *);
+
+protected:
+ AITimerCondition *_timerCondition;
+};
+
+/////////////////////////////////////////////
+//
+// AIActivateRuleAction
+
+class AIActivateRuleAction : public AIAction {
+public:
+ AIActivateRuleAction(AIRule *);
+
+ virtual void performAIAction(AIRule *);
+
+protected:
+ AIRule *_rule;
+};
+
+/////////////////////////////////////////////
+//
+// AIDeactivateRuleAction
+
+class AIDeactivateRuleAction : public AIAction {
+public:
+ AIDeactivateRuleAction(AIRule *rule);
+
+ virtual void performAIAction(AIRule *);
+
+protected:
+ AIRule *_rule;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/ai/ai_area.cpp b/engines/pegasus/ai/ai_area.cpp
new file mode 100644
index 0000000000..5ac8af8812
--- /dev/null
+++ b/engines/pegasus/ai/ai_area.cpp
@@ -0,0 +1,613 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/memstream.h"
+
+#include "pegasus/cursor.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/biochips/aichip.h"
+#include "pegasus/items/biochips/biochipitem.h"
+#include "pegasus/items/biochips/opticalchip.h"
+#include "pegasus/items/biochips/pegasuschip.h"
+#include "pegasus/items/inventory/airmask.h"
+#include "pegasus/items/inventory/inventoryitem.h"
+
+namespace Pegasus {
+
+AIArea *g_AIArea = 0;
+
+AIArea::AIArea(InputHandler *nextHandler) : InputHandler(nextHandler), _leftAreaMovie(kAILeftAreaID),
+ _middleAreaMovie(kAIMiddleAreaID), _rightAreaMovie(kAIRightAreaID), _AIMovie(kAIMovieID) {
+ g_AIArea = this;
+ _leftAreaOwner = kNoClientSignature;
+ _middleAreaOwner = kNoClientSignature;
+ _rightAreaOwner = kNoClientSignature;
+ _leftInventoryTime = 0xffffffff;
+ _middleInventoryTime = 0xffffffff;
+ _middleBiochipTime = 0xffffffff;
+ _rightBiochipTime = 0xffffffff;
+ _lockCount = 0;
+ startIdling();
+}
+
+AIArea::~AIArea() {
+ if (_middleAreaOwner == kBiochipSignature) {
+ BiochipItem *currentBiochip = ((PegasusEngine *)g_engine)->getCurrentBiochip();
+ if (currentBiochip && currentBiochip->isSelected())
+ currentBiochip->giveUpSharedArea();
+ } else if (_middleAreaOwner == kInventorySignature) {
+ InventoryItem *currentItem = ((PegasusEngine *)g_engine)->getCurrentInventoryItem();
+ if (currentItem && currentItem->isSelected())
+ currentItem->giveUpSharedArea();
+ }
+
+ stopIdling();
+
+ for (AIRuleList::iterator it = _AIRules.begin(); it != _AIRules.end(); it++)
+ delete *it;
+
+ g_AIArea = 0;
+}
+
+// Save last state of AI rules...
+void AIArea::saveAIState() {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ delete vm->_aiSaveStream;
+
+ Common::MemoryWriteStreamDynamic out;
+ writeAIRules(&out);
+
+ vm->_aiSaveStream = new Common::MemoryReadStream(out.getData(), out.size(), DisposeAfterUse::YES);
+}
+
+void AIArea::restoreAIState() {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ if (vm->_aiSaveStream)
+ readAIRules(vm->_aiSaveStream);
+}
+
+void AIArea::writeAIRules(Common::WriteStream *stream) {
+ _AIRules.writeAIRules(stream);
+}
+
+void AIArea::readAIRules(Common::ReadStream *stream) {
+ _AIRules.readAIRules(stream);
+}
+
+void AIArea::initAIArea() {
+ allocateSurface(Common::Rect(0, 0, 384, 96));
+
+ _leftAreaMovie.shareSurface(this);
+ _leftAreaMovie.initFromMovieFile("Images/Items/Left Area Movie");
+ _leftAreaMovie.moveElementTo(kAILeftAreaLeft, kAILeftAreaTop);
+ _leftAreaMovie.setDisplayOrder(kAILeftAreaOrder);
+ _leftAreaMovie.startDisplaying();
+ _leftAreaMovie.setVolume(((PegasusEngine *)g_engine)->getSoundFXLevel());
+
+ _middleAreaMovie.shareSurface(this);
+ _middleAreaMovie.initFromMovieFile("Images/Items/Middle Area Movie");
+ _middleAreaMovie.moveElementTo(kAIMiddleAreaLeft, kAIMiddleAreaTop);
+ _middleAreaMovie.moveMovieBoxTo(kAIMiddleAreaLeft - kAILeftAreaLeft, 0);
+ _middleAreaMovie.setDisplayOrder(kAIMiddleAreaOrder);
+ _middleAreaMovie.startDisplaying();
+ _middleAreaMovie.setVolume(((PegasusEngine *)g_engine)->getSoundFXLevel());
+
+ _rightAreaMovie.shareSurface(this);
+ _rightAreaMovie.initFromMovieFile("Images/Items/Right Area Movie");
+ _rightAreaMovie.moveElementTo(kAIRightAreaLeft, kAIRightAreaTop);
+ _rightAreaMovie.moveMovieBoxTo(kAIRightAreaLeft - kAILeftAreaLeft, 0);
+ _rightAreaMovie.setDisplayOrder(kAIRightAreaOrder);
+ _rightAreaMovie.startDisplaying();
+ _rightAreaMovie.setVolume(((PegasusEngine *)g_engine)->getSoundFXLevel());
+
+ _AIMovie.setDisplayOrder(kAIMovieOrder);
+}
+
+void AIArea::setAIVolume(const uint16 volume) {
+ _leftAreaMovie.setVolume(volume);
+ _middleAreaMovie.setVolume(volume);
+ _rightAreaMovie.setVolume(volume);
+}
+
+// There are only so many legal combinations of client/area.
+// Here is the list of supported pairs:
+// kInventorySignature kLeftAreaSignature
+// kInventorySignature kMiddleAreaSignature
+// kBiochipSignature kMiddleAreaSignature
+// kBiochipSignature kRightAreaSignature
+// kAISignature kLeftAreaSignature
+// Further, the kAISignature never sets a static frame time in the left area,
+// but only plays a sequence.
+
+// If this function is called while a sequence is playing, it will just "remember"
+// the time value, so that when the sequence finishes, the new time is asserted.
+
+void AIArea::setAIAreaToTime(const LowerClientSignature client, const LowerAreaSignature area, const TimeValue time) {
+ switch (area) {
+ case kLeftAreaSignature:
+ // Only support kInventorySignature client, since AI never calls SetAIAreaToTime.
+ _leftAreaMovie.setSegment(0, _leftAreaMovie.getDuration());
+
+ if (time == 0xffffffff) {
+ _leftAreaMovie.hide();
+ _leftAreaOwner = kNoClientSignature;
+ } else {
+ setLeftMovieTime(time);
+ }
+ break;
+ case kMiddleAreaSignature:
+ // Only support kInventorySignature and kBiochipSignature clients.
+ _middleAreaMovie.stop();
+ _middleAreaMovie.setFlags(0);
+ _middleAreaMovie.setSegment(0, _middleAreaMovie.getDuration());
+
+ if (time == 0xffffffff) {
+ if (client == kInventorySignature) {
+ if (_middleBiochipTime != 0xffffffff) {
+ setMiddleMovieTime(kBiochipSignature, _middleBiochipTime);
+ } else {
+ _middleAreaMovie.hide();
+ _middleAreaOwner = kNoClientSignature;
+ }
+ } else { // client == kBiochipSignature
+ if (_middleInventoryTime != 0xffffffff) {
+ setMiddleMovieTime(kInventorySignature, _middleInventoryTime);
+ } else {
+ _middleAreaMovie.hide();
+ _middleAreaOwner = kNoClientSignature;
+ }
+ }
+ } else {
+ setMiddleMovieTime(client, time);
+ }
+ break;
+ case kRightAreaSignature:
+ // Only support kBiochipSignature client.
+ _rightAreaMovie.setSegment(0, _rightAreaMovie.getDuration());
+
+ if (time == 0xffffffff) {
+ _rightAreaMovie.hide();
+ _rightAreaOwner = kNoClientSignature;
+ } else {
+ setRightMovieTime(time);
+ }
+ break;
+ }
+}
+
+// Plays a sequence on an area. When the sequence ends, the previous image
+// is restored.
+// Also, is input disabled or not?
+// Easy answer: yes.
+
+// There are only so many legal combinations of client/area.
+// Here is the list of supported pairs:
+// kBiochipSignature kMiddleAreaSignature
+// kBiochipSignature kRightAreaSignature
+// kInventorySignature kMiddleAreaSignature
+
+void AIArea::playAIAreaSequence(const LowerClientSignature, const LowerAreaSignature area, const TimeValue start, const TimeValue stop) {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ lockAIOut();
+
+ switch (area) {
+ case kLeftAreaSignature:
+ break;
+ case kMiddleAreaSignature:
+ if (_middleAreaOwner == kInventorySignature)
+ _middleInventoryTime = _middleAreaMovie.getTime();
+ else if (_middleAreaOwner == kBiochipSignature)
+ _middleBiochipTime = _middleAreaMovie.getTime();
+
+ _middleAreaMovie.stop();
+ _middleAreaMovie.setFlags(0);
+ _middleAreaMovie.setSegment(start, stop);
+ _middleAreaMovie.setTime(start);
+ _middleAreaMovie.show();
+ _middleAreaMovie.start();
+ vm->_cursor->hide();
+
+ while (_middleAreaMovie.isRunning()) {
+ vm->checkCallBacks();
+ vm->refreshDisplay();
+ g_system->delayMillis(10);
+ }
+
+ _middleAreaMovie.stop();
+ vm->_cursor->hideUntilMoved();
+
+ if (_middleAreaOwner == kInventorySignature)
+ setAIAreaToTime(_middleAreaOwner, kMiddleAreaSignature, _middleInventoryTime);
+ else if (_middleAreaOwner == kBiochipSignature)
+ setAIAreaToTime(_middleAreaOwner, kMiddleAreaSignature, _middleBiochipTime);
+ else
+ setAIAreaToTime(_middleAreaOwner, kMiddleAreaSignature, 0xffffffff);
+ break;
+ case kRightAreaSignature:
+ _rightBiochipTime = _rightAreaMovie.getTime();
+ _rightAreaMovie.setSegment(start, stop);
+ _rightAreaMovie.setTime(start);
+ _rightAreaMovie.show();
+ _rightAreaMovie.start();
+ vm->_cursor->hide();
+
+ while (_rightAreaMovie.isRunning()) {
+ vm->checkCallBacks();
+ vm->refreshDisplay();
+ g_system->delayMillis(10);
+ }
+
+ _rightAreaMovie.stop();
+ vm->_cursor->hideUntilMoved();
+ setAIAreaToTime(_rightAreaOwner, kRightAreaSignature, _rightBiochipTime);
+ break;
+ }
+
+ unlockAI();
+}
+
+bool AIArea::playAIMovie(const LowerAreaSignature area, const Common::String &movieName, bool keepLastFrame, const InputBits interruptFilter) {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ lockAIOut();
+
+ InputDevice.waitInput(interruptFilter);
+ if (_AIMovie.isMovieValid())
+ _AIMovie.releaseMovie();
+
+ _AIMovie.shareSurface(this);
+ _AIMovie.initFromMovieFile(movieName);
+
+ if (area == kLeftAreaSignature) {
+ _AIMovie.moveElementTo(kAILeftAreaLeft, kAILeftAreaTop);
+ _leftAreaMovie.hide();
+ } else {
+ _AIMovie.moveElementTo(kAIRightAreaLeft, kAIRightAreaTop);
+ _AIMovie.moveMovieBoxTo(kAIRightAreaLeft - kAILeftAreaLeft, 0);
+ _rightAreaMovie.hide();
+ }
+
+ _AIMovie.setTime(0);
+ _AIMovie.startDisplaying();
+ _AIMovie.show();
+ _AIMovie.redrawMovieWorld();
+ _AIMovie.setVolume(vm->getSoundFXLevel());
+ _AIMovie.start();
+ vm->_cursor->hide();
+
+ bool result = true;
+ bool saveAllowed = vm->swapSaveAllowed(false);
+ bool openAllowed = vm->swapLoadAllowed(false);
+
+ while (_AIMovie.isRunning()) {
+ Input input;
+ InputDevice.getInput(input, interruptFilter);
+
+ if (input.anyInput() || vm->shouldQuit() || vm->saveRequested() || vm->loadRequested()) {
+ result = false;
+ break;
+ }
+
+ vm->checkCallBacks();
+ vm->refreshDisplay();
+ g_system->delayMillis(10);
+ }
+
+ _AIMovie.stop();
+
+ vm->swapSaveAllowed(saveAllowed);
+ vm->swapLoadAllowed(openAllowed);
+
+ // This used to keep the last frame up even if the movie was interrupted.
+ // However, this only occurs in the recalibration, where interruption means skip the
+ // whole thing, so skipping causes the AI to go away even when keepLastFrame is true.
+
+ if (!(result && keepLastFrame)) {
+ _AIMovie.stopDisplaying();
+ _AIMovie.releaseMovie();
+
+ if (area == kLeftAreaSignature) {
+ _leftAreaMovie.setTime(_leftInventoryTime);
+ _leftAreaMovie.show();
+ _leftAreaMovie.redrawMovieWorld();
+ } else {
+ _rightAreaMovie.setTime(_rightBiochipTime);
+ _rightAreaMovie.show();
+ _rightAreaMovie.redrawMovieWorld();
+ }
+ }
+
+ vm->_cursor->hideUntilMoved();
+ unlockAI();
+ return result;
+}
+
+// Only implemented for kMiddleAreaSignature, kInventorySignature
+void AIArea::loopAIAreaSequence(const LowerClientSignature owner, const LowerAreaSignature area, const TimeValue start, const TimeValue stop) {
+ if (area == kMiddleAreaSignature && owner == kInventorySignature && owner == _middleAreaOwner) {
+ _middleAreaMovie.stop();
+ _middleAreaMovie.setFlags(0);
+ _middleAreaMovie.setSegment(start, stop);
+ _middleAreaMovie.setFlags(kLoopTimeBase);
+ _middleAreaMovie.setTime(start);
+ _middleAreaMovie.show();
+ _middleAreaMovie.start();
+ }
+}
+
+// Only called by kInventorySignature.
+void AIArea::setLeftMovieTime(const TimeValue time) {
+ if (!_AIMovie.isSurfaceValid()) {
+ _leftAreaMovie.setTime(time);
+ _leftAreaMovie.show();
+ _leftAreaMovie.redrawMovieWorld();
+ }
+
+ _leftAreaOwner = kInventorySignature;
+ _leftInventoryTime = time;
+}
+
+void AIArea::setMiddleMovieTime(const LowerClientSignature client, const TimeValue time) {
+ if (client == kInventorySignature) {
+ _middleInventoryTime = time;
+ if (_middleAreaOwner == kBiochipSignature) {
+ BiochipItem *currentBiochip = ((PegasusEngine *)g_engine)->getCurrentBiochip();
+ if (currentBiochip && currentBiochip->isSelected())
+ currentBiochip->giveUpSharedArea();
+ }
+ } else {
+ _middleBiochipTime = time;
+ if (_middleAreaOwner == kInventorySignature) {
+ InventoryItem *currentItem = ((PegasusEngine *)g_engine)->getCurrentInventoryItem();
+ if (currentItem && currentItem->isSelected())
+ currentItem->giveUpSharedArea();
+ }
+ }
+
+ _middleAreaMovie.setSegment(0, _middleAreaMovie.getDuration());
+ _middleAreaMovie.stop();
+ _middleAreaMovie.setFlags(0);
+ _middleAreaMovie.setTime(time);
+ _middleAreaMovie.show();
+ _middleAreaMovie.redrawMovieWorld();
+ _middleAreaOwner = client;
+}
+
+// Only called by kBiochipSignature.
+void AIArea::setRightMovieTime(const TimeValue time) {
+ if (!_AIMovie.isSurfaceValid()) {
+ // Can't do it when the AI movie is up...
+ _rightAreaMovie.setTime(time);
+ _rightAreaMovie.show();
+ _rightAreaMovie.redrawMovieWorld();
+ }
+
+ _rightAreaOwner = kBiochipSignature;
+ _rightBiochipTime = time;
+}
+
+void AIArea::handleInput(const Input &input, const Hotspot *cursorSpot) {
+ if (JMPPPInput::isToggleAIMiddleInput(input))
+ toggleMiddleAreaOwner();
+ else
+ InputHandler::handleInput(input, cursorSpot);
+}
+
+void AIArea::toggleMiddleAreaOwner() {
+ if (_middleAreaOwner == kInventorySignature) {
+ BiochipItem *currentBiochip = ((PegasusEngine *)g_engine)->getCurrentBiochip();
+ if (currentBiochip) {
+ setMiddleMovieTime(kBiochipSignature, currentBiochip->getSharedAreaTime());
+ currentBiochip->takeSharedArea();
+ }
+ } else if (_middleAreaOwner == kBiochipSignature) {
+ InventoryItem *currentItem = ((PegasusEngine *)g_engine)->getCurrentInventoryItem();
+ if (currentItem) {
+ setMiddleMovieTime(kInventorySignature, currentItem->getSharedAreaTime());
+ currentItem->takeSharedArea();
+ }
+ }
+}
+
+void AIArea::activateHotspots() {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ if (_middleAreaOwner == kBiochipSignature) {
+ BiochipItem *currentBiochip = ((PegasusEngine *)g_engine)->getCurrentBiochip();
+ if (currentBiochip)
+ switch (currentBiochip->getObjectID()) {
+ case kAIBiochip:
+ ((AIChip *)currentBiochip)->activateAIHotspots();
+ break;
+ case kPegasusBiochip:
+ if (!vm->isDemo())
+ ((PegasusChip *)currentBiochip)->activatePegasusHotspots();
+ break;
+ case kOpticalBiochip:
+ ((OpticalChip *)currentBiochip)->activateOpticalHotspots();
+ break;
+ }
+ } else if (_middleAreaOwner == kInventorySignature) {
+ InventoryItem *currentItem = ((PegasusEngine *)g_engine)->getCurrentInventoryItem();
+ if (currentItem && currentItem->getObjectID() == kAirMask)
+ ((AirMask *)currentItem)->activateAirMaskHotspots();
+ }
+
+ InputHandler::activateHotspots();
+}
+
+void AIArea::clickInHotspot(const Input &input, const Hotspot *hotspot) {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ bool handled = false;
+
+ if (_middleAreaOwner == kBiochipSignature) {
+ BiochipItem *currentBiochip = ((PegasusEngine *)g_engine)->getCurrentBiochip();
+
+ if (currentBiochip) {
+ switch (currentBiochip->getObjectID()) {
+ case kAIBiochip:
+ if ((hotspot->getHotspotFlags() & kAIBiochipSpotFlag) != 0) {
+ ((AIChip *)currentBiochip)->clickInAIHotspot(hotspot->getObjectID());
+ handled = true;
+ }
+ break;
+ case kPegasusBiochip:
+ if (!vm->isDemo() && ((hotspot->getHotspotFlags() & kPegasusBiochipSpotFlag) != 0)) {
+ ((PegasusChip *)currentBiochip)->clickInPegasusHotspot();
+ handled = true;
+ }
+ break;
+ case kOpticalBiochip:
+ if ((hotspot->getHotspotFlags() & kOpticalBiochipSpotFlag) != 0) {
+ ((OpticalChip *)currentBiochip)->clickInOpticalHotspot(hotspot->getObjectID());
+ handled = true;
+ }
+ break;
+ }
+ }
+ } else if (_middleAreaOwner == kInventorySignature) {
+ InventoryItem *currentItem = ((PegasusEngine *)g_engine)->getCurrentInventoryItem();
+
+ if (currentItem) {
+ switch (currentItem->getObjectID()) {
+ case kAirMask:
+ if ((hotspot->getHotspotFlags() & kAirMaskSpotFlag) != 0) {
+ ((AirMask *)currentItem)->clickInAirMaskHotspot();
+ handled = true;
+ }
+ break;
+ }
+ }
+ }
+
+ if (!handled)
+ InputHandler::clickInHotspot(input, hotspot);
+}
+
+void AIArea::lockAIOut() {
+ if (_lockCount == 0)
+ stopIdling();
+
+ _lockCount++;
+}
+
+void AIArea::unlockAI() {
+ if (_lockCount > 0) {
+ _lockCount--;
+ if (_lockCount == 0)
+ startIdling();
+ }
+}
+
+void AIArea::forceAIUnlocked() {
+ if (_lockCount > 0) {
+ _lockCount = 1;
+ unlockAI();
+ }
+}
+
+void AIArea::checkRules() {
+ if (_lockCount == 0 && ((PegasusEngine *)g_engine)->playerAlive())
+ for (AIRuleList::iterator it = _AIRules.begin(); it != _AIRules.end(); it++)
+ if ((*it)->fireRule())
+ break;
+}
+
+void AIArea::useIdleTime() {
+ checkRules();
+}
+
+void AIArea::addAIRule(AIRule *rule) {
+ _AIRules.push_back(rule);
+}
+
+void AIArea::removeAllRules() {
+ for (AIRuleList::iterator it = _AIRules.begin(); it != _AIRules.end(); it++)
+ delete *it;
+
+ _AIRules.clear();
+}
+
+void AIArea::checkMiddleArea() {
+ BiochipItem *currentBiochip = ((PegasusEngine *)g_engine)->getCurrentBiochip();
+
+ if (currentBiochip) {
+ if (_middleAreaOwner == kBiochipSignature) {
+ switch (currentBiochip->getObjectID()) {
+ case kAIBiochip:
+ ((AIChip *)currentBiochip)->setUpAIChip();
+ break;
+ case kPegasusBiochip:
+ ((PegasusChip *)currentBiochip)->setUpPegasusChip();
+ break;
+ }
+ } else {
+ switch (currentBiochip->getObjectID()) {
+ case kAIBiochip:
+ ((AIChip *)currentBiochip)->setUpAIChipRude();
+ break;
+ case kPegasusBiochip:
+ ((PegasusChip *)currentBiochip)->setUpPegasusChipRude();
+ break;
+ }
+ }
+ }
+}
+
+TimeValue AIArea::getBigInfoTime() {
+ if (_middleAreaOwner == kInventorySignature) {
+ InventoryItem *currentItem = ((PegasusEngine *)g_engine)->getCurrentInventoryItem();
+ return currentItem->getInfoLeftTime();
+ } else if (_middleAreaOwner == kBiochipSignature) {
+ BiochipItem *currentBiochip = ((PegasusEngine *)g_engine)->getCurrentBiochip();
+ return currentBiochip->getInfoLeftTime();
+ }
+
+ return 0xffffffff;
+}
+
+void AIArea::getSmallInfoSegment(TimeValue &start, TimeValue &stop) {
+ if (_middleAreaOwner == kInventorySignature) {
+ InventoryItem *currentItem = ((PegasusEngine *)g_engine)->getCurrentInventoryItem();
+ currentItem->getInfoRightTimes(start, stop);
+ } else if (_middleAreaOwner == kBiochipSignature) {
+ BiochipItem *currentBiochip = ((PegasusEngine *)g_engine)->getCurrentBiochip();
+ currentBiochip->getInfoRightTimes(start, stop);
+ } else {
+ start = 0xffffffff;
+ stop = 0xffffffff;
+ }
+}
+
+LowerClientSignature AIArea::getMiddleAreaOwner() {
+ return _middleAreaOwner;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/ai/ai_area.h b/engines/pegasus/ai/ai_area.h
new file mode 100644
index 0000000000..806e6ef6bb
--- /dev/null
+++ b/engines/pegasus/ai/ai_area.h
@@ -0,0 +1,172 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_AI_AIAREA_H
+#define PEGASUS_AI_AIAREA_H
+
+#include "pegasus/input.h"
+#include "pegasus/movie.h"
+#include "pegasus/timers.h"
+#include "pegasus/ai/ai_rule.h"
+
+namespace Common {
+ class ReadStream;
+ class WriteStream;
+}
+
+/*
+
+ The AI area is the area at the bottom of the screen. There are three areas within
+ the AI area:
+ 1) the inventory/AI help area
+ 2) the middle area
+ 3) the biochip display area
+
+ Area 1 is used for displaying the current inventory item. When the player changes the
+ current item, either by selecting a new one in the inventory list or by picking
+ up a new item, area 1 updates to show the new item.
+
+ If the AI decides to give a message, the AI's head temporarily takes over area 1
+ for the duration of the message, then goes away, returning the area to the current
+ inventory item.
+
+ Area 2 is used to display the current inventory item's state, the current biochip's
+ state, and any extra information from the AI. The contention for this area is
+ resolved as follows:
+ -- If the AI needs to use the area while giving a message in area 1, it takes over
+ area 2 for the duration of its message.
+*** This is not true.
+ -- If the player selects a new inventory item, the inventory item's state gets
+ displayed immediately.
+ -- If the player selects a new biochip, the biochip's state info gets displayed
+ immediately.
+ -- If any auto drawing is to occur, it seizes the area as soon as the drawing is
+ to occur. For example, the mapping biochip does auto drawing every time the
+ player takes a step. The only exception to this rule is if the AI is presenting
+ a warning. When the AI seizes areas 1 and 2, it preempts all other uses.
+ Some inventory items and biochips can cause arbitrary drawing to occur in this area
+ at arbitrary times. The map biochip is one example which causes drawing when the
+ player takes a step. Another example is the poison gas canister, which flashes in
+ this area to indicate a dangerous compound.
+
+ Area 3 is used to display the current biochip. When the player changes the current
+ biochip, either by selecting a new one from the biochip list or by picking up a
+ new one, area 3 updates to show the new item. In addition, some biochips can play
+ animation in this area.
+
+*/
+
+namespace Pegasus {
+
+class AIArea : public Surface, public Idler, public InputHandler {
+public:
+ AIArea(InputHandler *);
+ virtual ~AIArea();
+
+ void writeAIRules(Common::WriteStream *stream);
+ void readAIRules(Common::ReadStream *stream);
+
+ void initAIArea();
+
+ void saveAIState();
+ void restoreAIState();
+
+ void handleInput(const Input &, const Hotspot *);
+ void activateHotspots();
+ void clickInHotspot(const Input &, const Hotspot *);
+
+ void setAIVolume(const uint16);
+
+ // There are only so many legal combinations of client/area.
+ // Here is the list of supported pairs:
+ // kInventorySignature kLeftAreaSignature
+ // kInventorySignature kMiddleAreaSignature
+ // kBiochipSignature kMiddleAreaSignature
+ // kBiochipSignature kRightAreaSignature
+ // kAISignature kLeftAreaSignature
+ // Further, the kAISignature never sets a static frame time in the left area,
+ // but only plays a sequence from the AI movie.
+ void setAIAreaToTime(const LowerClientSignature, const LowerAreaSignature, const TimeValue);
+
+ // The "Play" functions play the requested sequence synchronously.
+ void playAIAreaSequence(const LowerClientSignature, const LowerAreaSignature, const TimeValue, const TimeValue);
+
+ // For PlayAIMovie, it is assumed that the client is the AI itself.
+ // This is used to play AI messages as well as Optical Memory video.
+ // Returns true if the movie played all the way through, false if it was interrupted.
+ bool playAIMovie(const LowerAreaSignature, const Common::String &movieName, bool keepLastFrame, const InputBits);
+
+ // Loop the requested sequence indefinitely.
+ void loopAIAreaSequence(const LowerClientSignature, const LowerAreaSignature, const TimeValue, const TimeValue);
+
+ void addAIRule(AIRule *);
+
+ // Remove and delete all rules.
+ void removeAllRules();
+
+ void lockAIOut();
+ void unlockAI();
+ void forceAIUnlocked();
+
+ void checkMiddleArea();
+ void checkRules();
+
+ LowerClientSignature getMiddleAreaOwner();
+ void toggleMiddleAreaOwner();
+
+ TimeValue getBigInfoTime();
+ void getSmallInfoSegment(TimeValue &, TimeValue &);
+
+protected:
+ void useIdleTime();
+
+ void setLeftMovieTime(const TimeValue);
+ void setMiddleMovieTime(const LowerClientSignature, const TimeValue);
+ void setRightMovieTime(const TimeValue);
+
+ Movie _leftAreaMovie;
+ Movie _middleAreaMovie;
+ Movie _rightAreaMovie;
+ Movie _AIMovie;
+
+ LowerClientSignature _leftAreaOwner;
+ LowerClientSignature _middleAreaOwner;
+ LowerClientSignature _rightAreaOwner;
+
+ TimeValue _leftInventoryTime;
+ TimeValue _middleInventoryTime;
+ TimeValue _middleBiochipTime;
+ TimeValue _rightBiochipTime;
+
+ AIRuleList _AIRules;
+
+ uint _lockCount;
+};
+
+extern AIArea *g_AIArea;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/ai/ai_condition.cpp b/engines/pegasus/ai/ai_condition.cpp
new file mode 100644
index 0000000000..9fc9272566
--- /dev/null
+++ b/engines/pegasus/ai/ai_condition.cpp
@@ -0,0 +1,290 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/stream.h"
+
+#include "pegasus/energymonitor.h"
+#include "pegasus/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/ai/ai_condition.h"
+#include "pegasus/items/itemlist.h"
+#include "pegasus/items/biochips/biochipitem.h"
+#include "pegasus/items/inventory/inventoryitem.h"
+
+namespace Pegasus {
+
+AIOneChildCondition::AIOneChildCondition(AICondition *child) {
+ _child = child;
+}
+
+AIOneChildCondition::~AIOneChildCondition() {
+ delete _child;
+}
+
+void AIOneChildCondition::writeAICondition(Common::WriteStream *stream) {
+ if (_child)
+ _child->writeAICondition(stream);
+}
+
+void AIOneChildCondition::readAICondition(Common::ReadStream *stream) {
+ if (_child)
+ _child->readAICondition(stream);
+}
+
+AITwoChildrenCondition::AITwoChildrenCondition(AICondition *leftChild, AICondition *rightChild) {
+ _leftChild = leftChild;
+ _rightChild = rightChild;
+}
+
+AITwoChildrenCondition::~AITwoChildrenCondition() {
+ delete _leftChild;
+ delete _rightChild;
+}
+
+void AITwoChildrenCondition::writeAICondition(Common::WriteStream *stream) {
+ if (_leftChild)
+ _leftChild->writeAICondition(stream);
+
+ if (_rightChild)
+ _rightChild->writeAICondition(stream);
+}
+
+void AITwoChildrenCondition::readAICondition(Common::ReadStream *stream) {
+ if (_leftChild)
+ _leftChild->readAICondition(stream);
+
+ if (_rightChild)
+ _rightChild->readAICondition(stream);
+}
+
+AINotCondition::AINotCondition(AICondition* child) : AIOneChildCondition(child) {
+}
+
+bool AINotCondition::fireCondition() {
+ return _child && !_child->fireCondition();
+}
+
+AIAndCondition::AIAndCondition(AICondition *leftChild, AICondition *rightChild) : AITwoChildrenCondition(leftChild, rightChild) {
+}
+
+bool AIAndCondition::fireCondition() {
+ return _leftChild && _leftChild->fireCondition() && _rightChild && _rightChild->fireCondition();
+}
+
+AIOrCondition::AIOrCondition(AICondition *leftChild, AICondition *rightChild) : AITwoChildrenCondition(leftChild, rightChild) {
+}
+
+bool AIOrCondition::fireCondition() {
+ return (_leftChild && _leftChild->fireCondition()) || (_rightChild && _rightChild->fireCondition());
+}
+
+AITimerCondition::AITimerCondition(const TimeValue time, const TimeScale scale, const bool shouldStartTimer) {
+ _timerFuse.primeFuse(time, scale);
+ _timerFuse.setFunctor(new Common::Functor0Mem<void, AITimerCondition>(this, &AITimerCondition::fire));
+ _fired = false;
+
+ if (shouldStartTimer)
+ startTimer();
+}
+
+void AITimerCondition::startTimer() {
+ _fired = false;
+ _timerFuse.lightFuse();
+}
+
+void AITimerCondition::stopTimer() {
+ _timerFuse.stopFuse();
+}
+
+void AITimerCondition::writeAICondition(Common::WriteStream *stream) {
+ stream->writeByte(_timerFuse.isFuseLit());
+ stream->writeByte(_fired);
+ stream->writeUint32BE(_timerFuse.getTimeRemaining());
+ stream->writeUint32BE(_timerFuse.getFuseScale());
+}
+
+void AITimerCondition::readAICondition(Common::ReadStream *stream) {
+ bool running = stream->readByte();
+ _fired = stream->readByte();
+ TimeValue time = stream->readUint32BE();
+ TimeScale scale = stream->readUint32BE();
+
+ _timerFuse.stopFuse();
+ _timerFuse.primeFuse(time, scale);
+
+ if (running)
+ _timerFuse.lightFuse();
+}
+
+bool AITimerCondition::fireCondition() {
+ return _fired;
+}
+
+void AITimerCondition::fire() {
+ _fired = true;
+}
+
+AILocationCondition::AILocationCondition(uint32 maxLocations) {
+ _numLocations = 0;
+ _maxLocations = maxLocations;
+ _locations = new RoomViewID[maxLocations];
+}
+
+AILocationCondition::~AILocationCondition() {
+ delete[] _locations;
+}
+
+void AILocationCondition::addLocation(const RoomViewID location) {
+ if (_numLocations < _maxLocations)
+ _locations[_numLocations++] = location;
+}
+
+bool AILocationCondition::fireCondition() {
+ RoomViewID test = GameState.getCurrentRoomAndView(), *p;
+ uint32 i;
+
+ for (i = 0, p = _locations; i < _numLocations; i++, p++) {
+ if (test == *p) {
+ *p = MakeRoomView(kNoRoomID, kNoDirection);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void AILocationCondition::writeAICondition(Common::WriteStream *stream) {
+ stream->writeUint32BE(_maxLocations);
+ stream->writeUint32BE(_numLocations);
+
+ uint32 i;
+ RoomViewID *p;
+ for (i = 0, p = _locations; i < _numLocations; i++, p++)
+ stream->writeUint32BE(*p);
+}
+
+void AILocationCondition::readAICondition(Common::ReadStream *stream) {
+ uint32 maxLocations = stream->readUint32BE();
+
+ if (_maxLocations != maxLocations) {
+ delete[] _locations;
+ _locations = new RoomViewID[maxLocations];
+ _maxLocations = maxLocations;
+ }
+
+ _numLocations = stream->readUint32BE();
+
+ uint32 i;
+ RoomViewID *p;
+ for (i = 0, p = _locations; i < _numLocations; i++, p++)
+ *p = stream->readUint32BE();
+}
+
+AIDoorOpenedCondition::AIDoorOpenedCondition(RoomViewID doorLocation) {
+ _doorLocation = doorLocation;
+}
+
+bool AIDoorOpenedCondition::fireCondition() {
+ return GameState.getCurrentRoomAndView() == _doorLocation && GameState.isCurrentDoorOpen();
+}
+
+AIHasItemCondition::AIHasItemCondition(const ItemID item) {
+ _item = item;
+}
+
+bool AIHasItemCondition::fireCondition() {
+ return _item == kNoItemID || GameState.isTakenItemID(_item);
+}
+
+AIDoesntHaveItemCondition::AIDoesntHaveItemCondition(const ItemID item) {
+ _item = item;
+}
+
+bool AIDoesntHaveItemCondition::fireCondition() {
+ return _item == kNoItemID || !GameState.isTakenItemID(_item);
+}
+
+AICurrentItemCondition::AICurrentItemCondition(const ItemID item) {
+ _item = item;
+}
+
+bool AICurrentItemCondition::fireCondition() {
+ InventoryItem *item = ((PegasusEngine *)g_engine)->getCurrentInventoryItem();
+
+ if (_item == kNoItemID)
+ return item == 0;
+
+ return item != 0 && item->getObjectID() == _item;
+}
+
+AICurrentBiochipCondition::AICurrentBiochipCondition(const ItemID biochip) {
+ _biochip = biochip;
+}
+
+bool AICurrentBiochipCondition::fireCondition() {
+ BiochipItem *biochip = ((PegasusEngine *)g_engine)->getCurrentBiochip();
+
+ if (_biochip == kNoItemID)
+ return biochip == 0;
+
+ return biochip != 0 && biochip->getObjectID() == _biochip;
+}
+
+AIItemStateCondition::AIItemStateCondition(const ItemID item, const ItemState state) {
+ _item = item;
+ _state = state;
+}
+
+bool AIItemStateCondition::fireCondition() {
+ Item *item = g_allItems.findItemByID(_item);
+ return item != 0 && item->getItemState() == _state;
+}
+
+AIEnergyMonitorCondition::AIEnergyMonitorCondition(const int32 energyThreshold) {
+ _energyThreshold = energyThreshold;
+}
+
+bool AIEnergyMonitorCondition::fireCondition() {
+ return g_energyMonitor != 0 && g_energyMonitor->getCurrentEnergy() < _energyThreshold;
+}
+
+AILastExtraCondition::AILastExtraCondition(const ExtraID lastExtra) {
+ _lastExtra = lastExtra;
+}
+
+bool AILastExtraCondition::fireCondition() {
+ return g_neighborhood && (ExtraID)g_neighborhood->getLastExtra() == _lastExtra;
+}
+
+AICondition *makeLocationAndDoesntHaveItemCondition(const RoomID room, const DirectionConstant direction, const ItemID item) {
+ AILocationCondition *location = new AILocationCondition(1);
+ location->addLocation(MakeRoomView(room, direction));
+
+ AIDoesntHaveItemCondition *doesntHaveItem = new AIDoesntHaveItemCondition(item);
+
+ return new AIAndCondition(location, doesntHaveItem);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/ai/ai_condition.h b/engines/pegasus/ai/ai_condition.h
new file mode 100644
index 0000000000..ae85168a36
--- /dev/null
+++ b/engines/pegasus/ai/ai_condition.h
@@ -0,0 +1,287 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_AI_AICONDITION_H
+#define PEGASUS_AI_AICONDITION_H
+
+#include "pegasus/timers.h"
+
+namespace Common {
+ class ReadStream;
+ class WriteStream;
+}
+
+namespace Pegasus {
+
+/////////////////////////////////////////////
+//
+// AICondition
+
+class AICondition {
+public:
+ AICondition() {}
+ virtual ~AICondition() {}
+
+ virtual bool fireCondition() = 0;
+
+ // Only need these for conditions that are dynamic, like timer conditions...
+ // other conditions, like item related conditions, which don't change during
+ // the run of an environment, are completely initted when the environment
+ // is created.
+ virtual void writeAICondition(Common::WriteStream *) {}
+ virtual void readAICondition(Common::ReadStream *) {}
+};
+
+/////////////////////////////////////////////
+//
+// AIOneChildCondition
+
+class AIOneChildCondition : public AICondition {
+public:
+ AIOneChildCondition(AICondition *);
+ virtual ~AIOneChildCondition();
+
+ virtual void writeAICondition(Common::WriteStream *);
+ virtual void readAICondition(Common::ReadStream *);
+
+protected:
+ AICondition *_child;
+};
+
+/////////////////////////////////////////////
+//
+// AITwoChildrenCondition
+
+class AITwoChildrenCondition : public AICondition {
+public:
+ AITwoChildrenCondition(AICondition *, AICondition *);
+ virtual ~AITwoChildrenCondition();
+
+ virtual void writeAICondition(Common::WriteStream *);
+ virtual void readAICondition(Common::ReadStream *);
+
+protected:
+ AICondition *_leftChild, *_rightChild;
+};
+
+/////////////////////////////////////////////
+//
+// AINotCondition
+
+class AINotCondition : public AIOneChildCondition {
+public:
+ AINotCondition(AICondition *);
+
+ virtual bool fireCondition();
+};
+
+/////////////////////////////////////////////
+//
+// AIAndCondition
+
+class AIAndCondition : public AITwoChildrenCondition {
+public:
+ AIAndCondition(AICondition *, AICondition *);
+
+ virtual bool fireCondition();
+};
+
+/////////////////////////////////////////////
+//
+// AIOrCondition
+
+class AIOrCondition : public AITwoChildrenCondition {
+public:
+ AIOrCondition(AICondition *, AICondition *);
+
+ virtual bool fireCondition();
+};
+
+/////////////////////////////////////////////
+//
+// AITimerCondition
+
+class AITimerCondition : public AICondition {
+public:
+ AITimerCondition(const TimeValue, const TimeScale, const bool);
+
+ void startTimer();
+ void stopTimer();
+
+ virtual bool fireCondition();
+
+ virtual void writeAICondition(Common::WriteStream *);
+ virtual void readAICondition(Common::ReadStream *);
+
+protected:
+ void fire();
+
+ FuseFunction _timerFuse;
+ bool _fired;
+};
+
+/////////////////////////////////////////////
+//
+// AILocationCondition
+
+class AILocationCondition : public AICondition {
+public:
+ AILocationCondition(uint32);
+ virtual ~AILocationCondition();
+
+ void addLocation(RoomViewID);
+ virtual bool fireCondition();
+
+ virtual void writeAICondition(Common::WriteStream *);
+ virtual void readAICondition(Common::ReadStream *);
+
+protected:
+ uint32 _numLocations, _maxLocations;
+ RoomViewID *_locations;
+};
+
+/////////////////////////////////////////////
+//
+// AIDoorOpenedCondition
+
+class AIDoorOpenedCondition : public AICondition {
+public:
+ AIDoorOpenedCondition(RoomViewID);
+ virtual ~AIDoorOpenedCondition() {}
+
+ virtual bool fireCondition();
+
+protected:
+ RoomViewID _doorLocation;
+};
+
+/////////////////////////////////////////////
+//
+// AIHasItemCondition
+
+class AIHasItemCondition : public AICondition {
+public:
+ AIHasItemCondition(const ItemID);
+
+ virtual bool fireCondition();
+
+protected:
+ ItemID _item;
+};
+
+/////////////////////////////////////////////
+//
+// AIDoesntHaveItemCondition
+
+class AIDoesntHaveItemCondition : public AICondition {
+public:
+ AIDoesntHaveItemCondition(const ItemID);
+
+ virtual bool fireCondition();
+
+protected:
+ ItemID _item;
+};
+
+/////////////////////////////////////////////
+//
+// AICurrentItemCondition
+
+class AICurrentItemCondition : public AICondition {
+public:
+ AICurrentItemCondition(const ItemID);
+
+ virtual bool fireCondition();
+
+protected:
+ ItemID _item;
+};
+
+/////////////////////////////////////////////
+//
+// AICurrentBiochipCondition
+
+class AICurrentBiochipCondition : public AICondition {
+public:
+ AICurrentBiochipCondition(const ItemID);
+
+ virtual bool fireCondition();
+
+protected:
+ ItemID _biochip;
+};
+
+/////////////////////////////////////////////
+//
+// AIItemStateCondition
+
+class AIItemStateCondition : public AICondition {
+public:
+ AIItemStateCondition(const ItemID, const ItemState);
+
+ virtual bool fireCondition();
+
+protected:
+ ItemID _item;
+ ItemState _state;
+};
+
+/////////////////////////////////////////////
+//
+// AIEnergyMonitorCondition
+
+class AIEnergyMonitorCondition : public AICondition {
+public:
+ AIEnergyMonitorCondition(const int32);
+
+ virtual bool fireCondition();
+
+protected:
+ int32 _energyThreshold;
+};
+
+/////////////////////////////////////////////
+//
+// AILastExtraCondition
+
+class AILastExtraCondition : public AICondition {
+public:
+ AILastExtraCondition(const ExtraID);
+
+ virtual bool fireCondition();
+
+protected:
+ ExtraID _lastExtra;
+};
+
+/////////////////////////////////////////////
+//
+// Helper functions
+
+AICondition *makeLocationAndDoesntHaveItemCondition(const RoomID room, const DirectionConstant direction, const ItemID item);
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/ai/ai_rule.cpp b/engines/pegasus/ai/ai_rule.cpp
new file mode 100644
index 0000000000..3aaa530a4a
--- /dev/null
+++ b/engines/pegasus/ai/ai_rule.cpp
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/stream.h"
+
+#include "pegasus/ai/ai_action.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/ai/ai_condition.h"
+#include "pegasus/ai/ai_rule.h"
+
+namespace Pegasus {
+
+bool AIRule::fireRule() {
+ if (_ruleActive && _ruleCondition && _ruleAction && _ruleCondition->fireCondition()) {
+ if (g_AIArea)
+ g_AIArea->lockAIOut();
+
+ _ruleAction->performAIAction(this);
+
+ if (--_ruleAction->_actionCount <= 0)
+ deactivateRule();
+
+ if (g_AIArea)
+ g_AIArea->unlockAI();
+
+ return true;
+ }
+
+ return false;
+}
+
+void AIRule::writeAIRule(Common::WriteStream *stream) {
+ stream->writeByte(_ruleActive);
+
+ if (_ruleCondition)
+ _ruleCondition->writeAICondition(stream);
+}
+
+void AIRule::readAIRule(Common::ReadStream *stream) {
+ _ruleActive = stream->readByte();
+
+ if (_ruleCondition)
+ _ruleCondition->readAICondition(stream);
+}
+
+void AIRuleList::writeAIRules(Common::WriteStream *stream) {
+ for (AIRuleList::iterator it = begin(); it != end(); it++)
+ (*it)->writeAIRule(stream);
+}
+
+void AIRuleList::readAIRules(Common::ReadStream *stream) {
+ for (AIRuleList::iterator it = begin(); it != end(); it++)
+ (*it)->readAIRule(stream);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/ai/ai_rule.h b/engines/pegasus/ai/ai_rule.h
new file mode 100644
index 0000000000..aa2ca07332
--- /dev/null
+++ b/engines/pegasus/ai/ai_rule.h
@@ -0,0 +1,86 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_AI_AIRULE_H
+#define PEGASUS_AI_AIRULE_H
+
+#include "common/list.h"
+
+#include "pegasus/ai/ai_action.h"
+#include "pegasus/ai/ai_condition.h"
+
+namespace Common {
+ class ReadStream;
+ class WriteStream;
+}
+
+namespace Pegasus {
+
+class AICondition;
+class AIAction;
+
+class AIRule {
+public:
+ AIRule(AICondition *condition, AIAction *rule) {
+ _ruleCondition = condition;
+ _ruleAction = rule;
+ _ruleActive = true;
+ }
+
+ ~AIRule() {
+ if (_ruleCondition)
+ delete _ruleCondition;
+
+ if (_ruleAction)
+ delete _ruleAction;
+ }
+
+ bool fireRule();
+
+ void activateRule() { _ruleActive = true; }
+ void deactivateRule() { _ruleActive = false; }
+ bool isRuleActive() { return _ruleActive; }
+
+ void writeAIRule(Common::WriteStream *);
+ void readAIRule(Common::ReadStream *);
+
+protected:
+ AICondition *_ruleCondition;
+ AIAction *_ruleAction;
+ bool _ruleActive;
+};
+
+class AIRuleList : public Common::List<AIRule *> {
+public:
+ AIRuleList() {}
+ ~AIRuleList() {}
+
+ void writeAIRules(Common::WriteStream *);
+ void readAIRules(Common::ReadStream *);
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/compass.cpp b/engines/pegasus/compass.cpp
new file mode 100644
index 0000000000..5de8b91b11
--- /dev/null
+++ b/engines/pegasus/compass.cpp
@@ -0,0 +1,82 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/compass.h"
+
+namespace Pegasus {
+
+Compass *g_compass = 0;
+
+Compass::Compass() : FaderAnimation(kCompassID) {
+ // Initialize it to east...
+ setFaderValue(90);
+ g_compass = this;
+}
+
+Compass::~Compass() {
+ g_compass = 0;
+}
+
+void Compass::initCompass() {
+ if (!isCompassValid()) {
+ Common::Rect r;
+ _compassImage.initFromPICTFile("Images/Compass/Compass");
+ _compassImage.getSurfaceBounds(r);
+ r.right = kCompassWidth;
+ setBounds(r);
+ }
+}
+
+void Compass::deallocateCompass() {
+ _compassImage.deallocateSurface();
+}
+
+void Compass::setFaderValue(const int32 angle) {
+ int16 a = angle % 360;
+
+ if (a < 0)
+ a += 360;
+
+ FaderAnimation::setFaderValue(a);
+}
+
+void Compass::draw(const Common::Rect &r1) {
+ if (_compassImage.isSurfaceValid()) {
+ Common::Rect bounds;
+ getBounds(bounds);
+
+ Common::Rect r2;
+ _compassImage.getSurfaceBounds(r2);
+
+ CoordType width = r2.width();
+ CoordType offsetH = width / 10 - bounds.width() / 2 + (getFaderValue() * width) / 450 - bounds.left;
+ CoordType offsetV = -bounds.top;
+ r2 = r1;
+ r2.translate(offsetH, offsetV);
+ _compassImage.drawImage(r2, r1);
+ }
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/compass.h b/engines/pegasus/compass.h
new file mode 100644
index 0000000000..67a8e06294
--- /dev/null
+++ b/engines/pegasus/compass.h
@@ -0,0 +1,58 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_COMPASS_H
+#define PEGASUS_COMPASS_H
+
+#include "pegasus/fader.h"
+#include "pegasus/surface.h"
+
+namespace Pegasus {
+
+// Compass is defined with 0 as north, 90 east, 180 south, 270 west.
+// Clockwise rotation increases the angle, counterclockwise rotation decreases the angle.
+
+class Compass : public FaderAnimation {
+public:
+ Compass();
+ virtual ~Compass();
+
+ void initCompass();
+ void deallocateCompass();
+ bool isCompassValid() const { return _compassImage.isSurfaceValid(); }
+
+ void setFaderValue(const int32);
+
+protected:
+ void draw(const Common::Rect &);
+
+ Frame _compassImage;
+};
+
+extern Compass *g_compass;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/console.cpp b/engines/pegasus/console.cpp
new file mode 100644
index 0000000000..64bd0ba5f2
--- /dev/null
+++ b/engines/pegasus/console.cpp
@@ -0,0 +1,102 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/console.h"
+#include "pegasus/interface.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/neighborhood/neighborhood.h"
+
+namespace Pegasus {
+
+PegasusConsole::PegasusConsole(PegasusEngine *vm) : GUI::Debugger(), _vm(vm) {
+ DCmd_Register("die", WRAP_METHOD(PegasusConsole, Cmd_Die));
+
+ // These functions are non-demo specific
+ if (!_vm->isDemo())
+ DCmd_Register("jump", WRAP_METHOD(PegasusConsole, Cmd_Jump));
+}
+
+PegasusConsole::~PegasusConsole() {
+}
+
+bool PegasusConsole::Cmd_Die(int argc, const char **argv) {
+ if (argc == 1) {
+ DebugPrintf("Usage: die <death reason>\n");
+ return true;
+ }
+
+ int reason = atoi(argv[1]);
+
+ bool invalidReason = (reason == 0 || reason > kPlayerWonGame);
+
+ if (!invalidReason && _vm->isDemo())
+ invalidReason = (reason != kDeathFallOffCliff) && (reason != kDeathEatenByDinosaur) &&
+ (reason != kDeathStranded) && (reason != kPlayerWonGame);
+
+
+ if (invalidReason) {
+ DebugPrintf("Invalid death reason %d\n", reason);
+ return true;
+ }
+
+ _vm->die(atoi(argv[1]));
+ return false;
+}
+
+bool PegasusConsole::Cmd_Jump(int argc, const char **argv) {
+ if (!g_interface) {
+ // TODO
+ DebugPrintf("Cannot jump without interface set up\n");
+ return true;
+ }
+
+ // TODO: Default room/direction for each neighborhood
+
+ if (argc < 4) {
+ DebugPrintf("Usage: jump <neighborhood> <room> <direction>\n");
+ return true;
+ }
+
+ NeighborhoodID neighborhood = (NeighborhoodID)atoi(argv[1]);
+ RoomID room = (RoomID)atoi(argv[2]);
+ DirectionConstant direction = (DirectionConstant)atoi(argv[3]);
+
+ if ((neighborhood < kCaldoriaID || neighborhood > kNoradDeltaID || neighborhood == kFinalTSAID) &&
+ neighborhood != kNoradSubChaseID) {
+ DebugPrintf("Invalid neighborhood %d", neighborhood);
+ return true;
+ }
+
+ // No real way to check room validity at this point
+
+ if (direction > kWest) {
+ DebugPrintf("Invalid direction %d", direction);
+ return true;
+ }
+
+ // Here we go!
+ // TODO: Can't clear menu since the engine is paused
+ _vm->jumpToNewEnvironment(neighborhood, room, direction);
+ return false;
+}
+
+} // End of namespace Pegasus
diff --git a/devtools/create_teenagent/md5.h b/engines/pegasus/console.h
index 3746521002..f00ee25294 100644
--- a/devtools/create_teenagent/md5.h
+++ b/engines/pegasus/console.h
@@ -20,21 +20,27 @@
*
*/
-#ifndef COMMON_MD5_H
-#define COMMON_MD5_H
+#ifndef PEGASUS_CONSOLE_H
+#define PEGASUS_CONSOLE_H
-#include "util.h"
+#include "gui/debugger.h"
-typedef struct {
- uint32 total[2];
- uint32 state[4];
- uint8 buffer[64];
-} md5_context;
+namespace Pegasus {
-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]);
+class PegasusEngine;
-bool md5_file(const char *name, uint8 digest[16], uint32 length = 0);
+class PegasusConsole : public GUI::Debugger {
+public:
+ PegasusConsole(PegasusEngine *vm);
+ virtual ~PegasusConsole();
+
+private:
+ bool Cmd_Die(int argc, const char **argv);
+ bool Cmd_Jump(int argc, const char **argv);
+
+ PegasusEngine *_vm;
+};
+
+} // End of namespace Pegasus
#endif
diff --git a/engines/pegasus/constants.h b/engines/pegasus/constants.h
new file mode 100644
index 0000000000..f81d2197ac
--- /dev/null
+++ b/engines/pegasus/constants.h
@@ -0,0 +1,729 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_CONSTANTS_H
+#define PEGASUS_CONSTANTS_H
+
+#include "common/endian.h"
+#include "common/rect.h"
+
+#include "pegasus/types.h"
+
+namespace Pegasus {
+
+// TODO: Organize these
+
+static const GameID kGameIDNothing = -1;
+
+static const ActorID kNoActorID = kGameIDNothing;
+static const ActorID kPlayerID = 0;
+static const ItemID kNoItemID = kGameIDNothing;
+static const RoomID kNoRoomID = kGameIDNothing;
+static const ExtraID kNoExtraID = 0xFFFFFFFF;
+static const NeighborhoodID kNoNeighborhoodID = kGameIDNothing;
+static const AlternateID kNoAlternateID = 0;
+static const GameMenuCommand kMenuCmdNoCommand = 0;
+
+static const HotSpotActivationID kActivateHotSpotAlways = 0;
+static const HotSpotActivationID kActivateHotSpotNever = -1;
+
+static const ItemState kNoItemState = -1;
+
+static const DirectionConstant kNoDirection = 0xFF;
+static const DirectionConstant kNorth = 0;
+static const DirectionConstant kSouth = 1;
+static const DirectionConstant kEast = 2;
+static const DirectionConstant kWest = 3;
+
+static const TurnDirection kNoTurn = 0xFF;
+static const TurnDirection kTurnLeft = 0;
+static const TurnDirection kTurnRight = 1;
+static const TurnDirection kTurnUp = 2;
+static const TurnDirection kTurnDown = 3;
+static const TurnDirection kMaxTurns = 4;
+
+static const GameMode kNoMode = -1;
+static const GameMode kModeNavigation = 0;
+static const GameMode kLastGameShellMode = kModeNavigation;
+
+static const CanMoveForwardReason kCanMoveForward = 0;
+static const CanMoveForwardReason kCantMoveBlocked = kCanMoveForward + 1;
+static const CanMoveForwardReason kCantMoveDoorClosed = kCantMoveBlocked + 1;
+static const CanMoveForwardReason kCantMoveDoorLocked = kCantMoveDoorClosed + 1;
+static const CanMoveForwardReason kCantMoveLastReason = kCantMoveDoorLocked;
+
+static const CanTurnReason kCanTurn = 0;
+static const CanTurnReason kCantTurnNoTurn = kCanTurn + 1;
+static const CanTurnReason kCantTurnLastReason = kCantTurnNoTurn;
+
+static const CanOpenDoorReason kCanOpenDoor = 0;
+static const CanOpenDoorReason kCantOpenNoDoor = kCanOpenDoor + 1;
+static const CanOpenDoorReason kCantOpenLocked = kCantOpenNoDoor + 1;
+static const CanOpenDoorReason kCantOpenAlreadyOpen = kCantOpenLocked + 1;
+static const CanOpenDoorReason kCantOpenLastReason = kCantOpenAlreadyOpen;
+
+static const DisplayElementID kNoDisplayElement = -1;
+static const DisplayElementID kHighestReservedElementID = -2;
+
+static const DisplayElementID kCursorID = kHighestReservedElementID;
+static const DisplayElementID kLoadScreenID = kCursorID - 1;
+
+static const DisplayOrder kMinAvailableOrder = 0;
+static const DisplayOrder kMaxAvailableOrder = 999998;
+static const DisplayOrder kLoadScreenOrder = 900000;
+static const DisplayOrder kCursorOrder = 1000000;
+
+static const HotSpotID kNoHotSpotID = -1;
+static const HotSpotFlags kNoHotSpotFlags = 0;
+static const HotSpotFlags kAllHotSpotFlags = ~kNoHotSpotFlags;
+
+static const NotificationFlags kNoNotificationFlags = 0;
+
+static const DisplayElementID kCurrentDragSpriteID = 1000;
+
+static const TimeScale kDefaultTimeScale = 600;
+
+// Ticks per second.
+
+static const TimeScale kOneTickPerSecond = 1;
+static const TimeScale kTwoTicksPerSecond = 2;
+static const TimeScale kFifteenTicksPerSecond = 15;
+static const TimeScale kThirtyTicksPerSecond = 30;
+static const TimeScale kSixtyTicksPerSecond = 60;
+static const TimeScale kMovieTicksPerSecond = 600;
+
+// These times are in seconds.
+
+static const TimeValue kOneSecond = 1;
+static const TimeValue kTwoSeconds = 2;
+static const TimeValue kThreeSeconds = 3;
+static const TimeValue kFourSeconds = 4;
+static const TimeValue kFiveSeconds = 5;
+static const TimeValue kSixSeconds = 6;
+static const TimeValue kSevenSeconds = 7;
+static const TimeValue kEightSeconds = 8;
+static const TimeValue kNineSeconds = 9;
+static const TimeValue kTenSeconds = 10;
+static const TimeValue kElevenSeconds = 11;
+static const TimeValue kTwelveSeconds = 12;
+static const TimeValue kThirteenSeconds = 13;
+static const TimeValue kFourteenSeconds = 14;
+static const TimeValue kFifteenSeconds = 15;
+static const TimeValue kSixteenSeconds = 16;
+static const TimeValue kSeventeenSeconds = 17;
+static const TimeValue kEighteenSeconds = 18;
+static const TimeValue kNineteenSeconds = 19;
+static const TimeValue kTwentySeconds = 20;
+static const TimeValue kThirtySeconds = 30;
+static const TimeValue kFortySeconds = 40;
+static const TimeValue kFiftySeconds = 50;
+static const TimeValue kSixtySeconds = 60;
+static const TimeValue kOneMinute = 60;
+static const TimeValue kTwoMinutes = kOneMinute * 2;
+static const TimeValue kThreeMinutes = kOneMinute * 3;
+static const TimeValue kFourMinutes = kOneMinute * 4;
+static const TimeValue kFiveMinutes = kOneMinute * 5;
+static const TimeValue kSixMinutes = kOneMinute * 6;
+static const TimeValue kSevenMinutes = kOneMinute * 7;
+static const TimeValue kEightMinutes = kOneMinute * 8;
+static const TimeValue kNineMinutes = kOneMinute * 9;
+static const TimeValue kTenMinutes = kOneMinute * 10;
+static const TimeValue kElevenMinutes = kOneMinute * 11;
+static const TimeValue kTwelveMinutes = kOneMinute * 12;
+static const TimeValue kThirteenMinutes = kOneMinute * 13;
+static const TimeValue kFourteenMinutes = kOneMinute * 14;
+static const TimeValue kFifteenMinutes = kOneMinute * 15;
+static const TimeValue kSixteenMinutes = kOneMinute * 16;
+static const TimeValue kSeventeenMinutes = kOneMinute * 17;
+static const TimeValue kEighteenMinutes = kOneMinute * 18;
+static const TimeValue kNineteenMinutes = kOneMinute * 19;
+static const TimeValue kTwentyMinutes = kOneMinute * 20;
+static const TimeValue kThirtyMinutes = kOneMinute * 30;
+static const TimeValue kFortyMinutes = kOneMinute * 40;
+static const TimeValue kFiftyMinutes = kOneMinute * 50;
+static const TimeValue kOneHour = kOneMinute * 60;
+static const TimeValue kTwoHours = kOneHour * 2;
+
+// Common times.
+
+static const TimeValue kHalfSecondPerTwoTicks = kTwoTicksPerSecond / 2;
+static const TimeValue kHalfSecondPerThirtyTicks = kThirtyTicksPerSecond / 2;
+static const TimeValue kHalfSecondPerSixtyTicks = kSixtyTicksPerSecond / 2;
+
+static const TimeValue kOneSecondPerTwoTicks = kTwoTicksPerSecond;
+static const TimeValue kOneSecondPerThirtyTicks = kThirtyTicksPerSecond;
+static const TimeValue kOneSecondPerSixtyTicks = kSixtyTicksPerSecond;
+
+static const TimeValue kOneMinutePerFifteenTicks = kOneMinute * kFifteenTicksPerSecond;
+static const TimeValue kFiveMinutesPerFifteenTicks = kFiveMinutes * kFifteenTicksPerSecond;
+static const TimeValue kTenMinutesPerFifteenTicks = kTenMinutes * kFifteenTicksPerSecond;
+
+static const TimeValue kOneMinutePerThirtyTicks = kOneMinute * kThirtyTicksPerSecond;
+static const TimeValue kFiveMinutesPerThirtyTicks = kFiveMinutes * kThirtyTicksPerSecond;
+static const TimeValue kTenMinutesPerThirtyTicks = kTenMinutes * kThirtyTicksPerSecond;
+
+static const TimeValue kOneMinutePerSixtyTicks = kOneMinute * kSixtyTicksPerSecond;
+static const TimeValue kFiveMinutesPerSixtyTicks = kFiveMinutes * kSixtyTicksPerSecond;
+static const TimeValue kTenMinutesPerSixtyTicks = kTenMinutes * kSixtyTicksPerSecond;
+
+// Time in seconds you can hang around Caldoria without going to work...
+static const TimeValue kLateWarning2TimeLimit = kFiveMinutes;
+static const TimeValue kLateWarning3TimeLimit = kTenMinutes;
+
+static const TimeValue kSinclairShootsTimeLimit = kThreeMinutes;
+static const TimeValue kCardBombCountDownTime = kTwelveSeconds;
+
+static const TimeValue kOxyMaskFullTime = kThirtyMinutes;
+
+static const TimeValue kTSAUncreatedTimeLimit = kFiveMinutes;
+static const TimeValue kRipTimeLimit = kTenMinutesPerFifteenTicks;
+static const TimeScale kRipTimeScale = kFifteenTicksPerSecond;
+
+static const TimeValue kIntroTimeOut = kThirtySeconds;
+
+static const TimeValue kMarsRobotPatienceLimit = kFifteenSeconds;
+static const TimeValue kLockFreezeTimeLmit = kFifteenSeconds;
+static const TimeValue kSpaceChaseTimeLimit = kTenMinutes;
+static const TimeValue kVacuumSurvivalTimeLimit = kThirtySeconds;
+static const TimeValue kColorMatchingTimeLimit = kFourMinutes;
+static const TimeScale kJunkTimeScale = kFifteenTicksPerSecond;
+static const TimeValue kJunkDropBaseTime = kFiveSeconds;
+static const TimeValue kJunkDropSlopTime = kThreeSeconds;
+static const TimeValue kJunkTravelTime = kTenSeconds * kJunkTimeScale;
+static const TimeValue kCollisionReboundTime = kOneSecond * kJunkTimeScale;
+static const TimeValue kWeaponReboundTime = kTwoSeconds * kJunkTimeScale;
+
+static const TimeValue kGawkAtRobotTime = kTenSeconds;
+static const TimeValue kGawkAtRobotTime2 = kThirteenSeconds;
+static const TimeValue kPlasmaImpactTime = kTwoSeconds;
+
+static const TimeValue kNoradAirMaskTimeLimit = kOneMinute + kFifteenSeconds;
+
+static const NotificationID kNeighborhoodNotificationID = 1;
+static const NotificationID kLastNeighborhoodNotificationID = kNeighborhoodNotificationID;
+
+static const NotificationFlags kNeighborhoodMovieCompletedFlag = 1;
+static const NotificationFlags kMoveForwardCompletedFlag = kNeighborhoodMovieCompletedFlag << 1;
+static const NotificationFlags kStrideCompletedFlag = kMoveForwardCompletedFlag << 1;
+static const NotificationFlags kTurnCompletedFlag = kStrideCompletedFlag << 1;
+static const NotificationFlags kSpotCompletedFlag = kTurnCompletedFlag << 1;
+static const NotificationFlags kDoorOpenCompletedFlag = kSpotCompletedFlag << 1;
+static const NotificationFlags kExtraCompletedFlag = kDoorOpenCompletedFlag << 1;
+static const NotificationFlags kSpotSoundCompletedFlag = kExtraCompletedFlag << 1;
+static const NotificationFlags kDelayCompletedFlag = kSpotSoundCompletedFlag << 1;
+static const NotificationFlags kActionRequestCompletedFlag = kDelayCompletedFlag << 1;
+static const NotificationFlags kDeathExtraCompletedFlag = kActionRequestCompletedFlag << 1;
+static const NotificationFlags kLastNeighborhoodNotificationFlag = kDeathExtraCompletedFlag;
+
+static const NotificationFlags kNeighborhoodFlags = kNeighborhoodMovieCompletedFlag |
+ kMoveForwardCompletedFlag |
+ kStrideCompletedFlag |
+ kTurnCompletedFlag |
+ kSpotCompletedFlag |
+ kDoorOpenCompletedFlag |
+ kExtraCompletedFlag |
+ kSpotSoundCompletedFlag |
+ kDelayCompletedFlag |
+ kActionRequestCompletedFlag |
+ kDeathExtraCompletedFlag;
+
+static const uint32 kPegasusPrimeCreator = MKTAG('J', 'P', 'P', 'P');
+static const uint32 kPegasusPrimeContinueType = MKTAG('P', 'P', 'C', 'T');
+
+static const uint32 kPegasusPrimeDisk1GameType = MKTAG('P', 'P', 'G', '1');
+static const uint32 kPegasusPrimeDisk2GameType = MKTAG('P', 'P', 'G', '2');
+static const uint32 kPegasusPrimeDisk3GameType = MKTAG('P', 'P', 'G', '3');
+static const uint32 kPegasusPrimeDisk4GameType = MKTAG('P', 'P', 'G', '4');
+
+// We only support one of the save versions; the rest are from betas
+// and we are not supporting them.
+static const uint32 kPegasusPrimeVersion = 0x00009019;
+
+static const char kNormalSave = 0;
+static const char kContinueSave = 1;
+
+// Display IDs.
+
+static const DisplayElementID kNavMovieID = 1;
+static const DisplayElementID kTurnPushID = 2;
+
+static const DisplayElementID kMaxGameShellDisplayID = kTurnPushID;
+
+// Display ordering.
+
+static const DisplayOrder kNavLayer = 10000;
+static const DisplayOrder kNavMovieOrder = kNavLayer;
+static const DisplayOrder kTurnPushOrder = kNavMovieOrder + 1;
+
+/////////////////////////////////////////////
+//
+// Display IDs.
+
+static const DisplayElementID kScreenDimmerID = kMaxGameShellDisplayID + 1;
+static const DisplayElementID kInterface1ID = kScreenDimmerID + 1;
+static const DisplayElementID kInterface2ID = kInterface1ID + 1;
+static const DisplayElementID kInterface3ID = kInterface2ID + 1;
+static const DisplayElementID kInterface4ID = kInterface3ID + 1;
+static const DisplayElementID kDateID = kInterface4ID + 1;
+static const DisplayElementID kCompassID = kDateID + 1;
+static const DisplayElementID kInventoryPushID = kCompassID + 1;
+static const DisplayElementID kInventoryLidID = kInventoryPushID + 1;
+static const DisplayElementID kBiochipPushID = kInventoryLidID + 1;
+static const DisplayElementID kBiochipLidID = kBiochipPushID + 1;
+static const DisplayElementID kEnergyBarID = kBiochipLidID + 1;
+static const DisplayElementID kWarningLightID = kEnergyBarID + 1;
+static const DisplayElementID kAILeftAreaID = kWarningLightID + 1;
+static const DisplayElementID kAIMiddleAreaID = kAILeftAreaID + 1;
+static const DisplayElementID kAIRightAreaID = kAIMiddleAreaID + 1;
+static const DisplayElementID kAIMovieID = kAIRightAreaID + 1;
+static const DisplayElementID kInventoryDropHighlightID = kAIMovieID + 1;
+static const DisplayElementID kBiochipDropHighlightID = kInventoryDropHighlightID + 1;
+
+static const DisplayElementID kDraggingSpriteID = 1000;
+
+static const DisplayElementID kCroppedMovieID = 2000;
+
+static const DisplayElementID kNeighborhoodDisplayID = 3000;
+
+static const DisplayElementID kItemPictureBaseID = 5000;
+
+static const CoordType kNavAreaLeft = 64;
+static const CoordType kNavAreaTop = 64;
+
+static const CoordType kBackground1Left = 0;
+static const CoordType kBackground1Top = 64;
+
+static const CoordType kBackground2Left = 0;
+static const CoordType kBackground2Top = 0;
+
+static const CoordType kBackground3Left = 576;
+static const CoordType kBackground3Top = 64;
+
+static const CoordType kBackground4Left = 0;
+static const CoordType kBackground4Top = 320;
+
+static const CoordType kOverviewControllerLeft = 540;
+static const CoordType kOverviewControllerTop = 348;
+
+static const CoordType kSwapLeft = 194;
+static const CoordType kSwapTop = 116;
+
+static const CoordType kSwapHiliteLeft = 200;
+static const CoordType kSwapHiliteTop = 206;
+
+static const CoordType kDateLeft = 136;
+static const CoordType kDateTop = 44;
+
+static const CoordType kCompassLeft = 222;
+static const CoordType kCompassTop = 42;
+static const CoordType kCompassWidth = 92;
+
+static const CoordType kInventoryPushLeft = 74;
+static const CoordType kInventoryPushTop = 92;
+
+static const CoordType kInventoryLidLeft = 74;
+static const CoordType kInventoryLidTop = 316;
+
+static const CoordType kBiochipPushLeft = 362;
+static const CoordType kBiochipPushTop = 192;
+
+static const CoordType kBiochipLidLeft = 362;
+static const CoordType kBiochipLidTop = 316;
+
+static const CoordType kInventoryDropLeft = 0;
+static const CoordType kInventoryDropTop = 320;
+static const CoordType kInventoryDropRight = 232;
+static const CoordType kInventoryDropBottom = 480;
+
+static const CoordType kBiochipDropLeft = 302;
+static const CoordType kBiochipDropTop = 320;
+static const CoordType kBiochipDropRight = 640;
+static const CoordType kBiochipDropBottom = 480;
+
+static const CoordType kFinalMessageLeft = kInventoryPushLeft + 1;
+static const CoordType kFinalMessageTop = kInventoryPushTop + 24;
+
+/////////////////////////////////////////////
+//
+// Notifications.
+
+static const NotificationID kJMPDCShellNotificationID = kLastNeighborhoodNotificationID + 1;
+static const NotificationID kInterfaceNotificationID = kJMPDCShellNotificationID + 1;
+static const NotificationID kAINotificationID = kInterfaceNotificationID + 1;
+static const NotificationID kNoradNotificationID = kAINotificationID + 1;
+static const NotificationID kNoradECRNotificationID = kNoradNotificationID + 1;
+static const NotificationID kNoradFillingStationNotificationID = kNoradECRNotificationID + 1;
+static const NotificationID kNoradPressureNotificationID = kNoradFillingStationNotificationID + 1;
+static const NotificationID kNoradUtilityNotificationID = kNoradPressureNotificationID + 1;
+static const NotificationID kNoradElevatorNotificationID = kNoradUtilityNotificationID + 1;
+static const NotificationID kNoradSubPlatformNotificationID = kNoradElevatorNotificationID + 1;
+static const NotificationID kSubControlNotificationID = kNoradSubPlatformNotificationID + 1;
+static const NotificationID kNoradGreenBallNotificationID = kSubControlNotificationID + 1;
+static const NotificationID kNoradGlobeNotificationID = kNoradGreenBallNotificationID + 1;
+static const NotificationID kCaldoriaVidPhoneNotificationID = kNoradGlobeNotificationID + 1;
+static const NotificationID kCaldoriaMessagesNotificationID = kCaldoriaVidPhoneNotificationID + 1;
+static const NotificationID kCaldoriaBombTimerNotificationID = kCaldoriaMessagesNotificationID + 1;
+
+// Sent to the shell by fShellNotification.
+static const NotificationFlags kGameStartingFlag = 1;
+static const NotificationFlags kNeedNewJumpFlag = kGameStartingFlag << 1;
+static const NotificationFlags kPlayerDiedFlag = kNeedNewJumpFlag << 1;
+
+static const NotificationFlags kJMPShellNotificationFlags = kGameStartingFlag |
+ kNeedNewJumpFlag |
+ kPlayerDiedFlag;
+
+// Sent to the interface.
+static const NotificationFlags kInventoryLidOpenFlag = 1;
+static const NotificationFlags kInventoryLidClosedFlag = kInventoryLidOpenFlag << 1;
+static const NotificationFlags kInventoryDrawerUpFlag = kInventoryLidClosedFlag << 1;
+static const NotificationFlags kInventoryDrawerDownFlag = kInventoryDrawerUpFlag << 1;
+static const NotificationFlags kBiochipLidOpenFlag = kInventoryDrawerDownFlag << 1;
+static const NotificationFlags kBiochipLidClosedFlag = kBiochipLidOpenFlag << 1;
+static const NotificationFlags kBiochipDrawerUpFlag = kBiochipLidClosedFlag << 1;
+static const NotificationFlags kBiochipDrawerDownFlag = kBiochipDrawerUpFlag << 1;
+
+static const NotificationFlags kInterfaceNotificationFlags = kInventoryLidOpenFlag |
+ kInventoryLidClosedFlag |
+ kInventoryDrawerUpFlag |
+ kInventoryDrawerDownFlag |
+ kBiochipLidOpenFlag |
+ kBiochipLidClosedFlag |
+ kBiochipDrawerUpFlag |
+ kBiochipDrawerDownFlag;
+
+// Hot spots.
+
+// Neighborhood hot spots.
+
+static const HotSpotID kFirstNeighborhoodSpotID = 5000;
+
+// kShellSpotFlag is a flag which marks all hot spots which belong to the shell, like
+// the current item and current biochip spots.
+static const HotSpotFlags kShellSpotFlag = 1;
+// kNeighborhoodSpotFlag is a flag which marks all hot spots which belong to a
+// neighborhood, like buttons on walls and so on.
+static const HotSpotFlags kNeighborhoodSpotFlag = kShellSpotFlag << 1;
+// kZoomInSpotFlag is a flag which marks all hot spots which indicate a zoom.
+static const HotSpotFlags kZoomInSpotFlag = kNeighborhoodSpotFlag << 1;
+// kZoomOutSpotFlag is a flag which marks all hot spots which indicate a zoom.
+static const HotSpotFlags kZoomOutSpotFlag = kZoomInSpotFlag << 1;
+
+static const HotSpotFlags kClickSpotFlag = kZoomOutSpotFlag << 1;
+static const HotSpotFlags kPlayExtraSpotFlag = kClickSpotFlag << 1;
+static const HotSpotFlags kPickUpItemSpotFlag = kPlayExtraSpotFlag << 1;
+static const HotSpotFlags kDropItemSpotFlag = kPickUpItemSpotFlag << 1;
+static const HotSpotFlags kOpenDoorSpotFlag = kDropItemSpotFlag << 1;
+
+static const HotSpotFlags kZoomSpotFlags = kZoomInSpotFlag | kZoomOutSpotFlag;
+
+static const HotSpotFlags kHighestGameShellSpotFlag = kOpenDoorSpotFlag;
+
+/////////////////////////////////////////////
+//
+// Hot spots.
+
+// Shell hot spots.
+// The shell reserves all hot spot IDs from 0 to 999
+
+static const HotSpotID kCurrentItemSpotID = 0;
+static const HotSpotID kCurrentBiochipSpotID = kCurrentItemSpotID + 1;
+
+static const HotSpotID kInventoryDropSpotID = kCurrentBiochipSpotID + 1;
+static const HotSpotID kBiochipDropSpotID = kInventoryDropSpotID + 1;
+
+static const HotSpotID kInfoReturnSpotID = kBiochipDropSpotID + 1;
+
+static const HotSpotID kAIHint1SpotID = kInfoReturnSpotID + 1;
+static const HotSpotID kAIHint2SpotID = kAIHint1SpotID + 1;
+static const HotSpotID kAIHint3SpotID = kAIHint2SpotID + 1;
+static const HotSpotID kAISolveSpotID = kAIHint3SpotID + 1;
+static const HotSpotID kAIBriefingSpotID = kAISolveSpotID + 1;
+static const HotSpotID kAIScanSpotID = kAIBriefingSpotID + 1;
+
+static const HotSpotID kPegasusRecallSpotID = kAIScanSpotID + 1;
+
+static const HotSpotID kAriesSpotID = kPegasusRecallSpotID + 1;
+static const HotSpotID kMercurySpotID = kAriesSpotID + 1;
+static const HotSpotID kPoseidonSpotID = kMercurySpotID + 1;
+
+static const HotSpotID kAirMaskToggleSpotID = kPoseidonSpotID + 1;
+
+static const HotSpotID kShuttleEnergySpotID = kAirMaskToggleSpotID + 1;
+static const HotSpotID kShuttleGravitonSpotID = kShuttleEnergySpotID + 1;
+static const HotSpotID kShuttleTractorSpotID = kShuttleGravitonSpotID + 1;
+static const HotSpotID kShuttleViewSpotID = kShuttleTractorSpotID + 1;
+static const HotSpotID kShuttleTransportSpotID = kShuttleViewSpotID + 1;
+
+// Most of these are obsolete:
+
+// kInventoryDropSpotFlag is a flag which marks hot spots which are valid drop spots
+// for inventory items.
+// static const HotSpotFlags kInventoryDropSpotFlag = kHighestGameShellSpotFlag << 1;
+
+// kBiochipDropSpotFlag is a flag which marks hot spots which are valid drop spots
+// for biochips.
+// static const HotSpotFlags kBiochipDropSpotFlag = kInventoryDropSpotFlag << 1;
+
+// kInventorySpotFlag is a flag which marks hot spots which indicate inventory items
+// in the environment.
+// static const HotSpotFlags kInventorySpotFlag = kBiochipDropSpotFlag << 1;
+
+// kBiochipSpotFlag is a flag which marks hot spots which indicate biochips
+// in the environment.
+static const HotSpotFlags kPickUpBiochipSpotFlag = kHighestGameShellSpotFlag << 1;
+static const HotSpotFlags kDropBiochipSpotFlag = kPickUpBiochipSpotFlag << 1;
+
+static const HotSpotFlags kInfoReturnSpotFlag = kDropBiochipSpotFlag << 1;
+
+// Biochip and inventory hot spot flags...
+
+static const HotSpotFlags kAIBiochipSpotFlag = kInfoReturnSpotFlag << 1;
+static const HotSpotFlags kPegasusBiochipSpotFlag = kAIBiochipSpotFlag << 1;
+static const HotSpotFlags kOpticalBiochipSpotFlag = kPegasusBiochipSpotFlag << 1;
+static const HotSpotFlags kAirMaskSpotFlag = kOpticalBiochipSpotFlag << 1;
+
+static const HotSpotFlags kJMPClickingSpotFlags = kClickSpotFlag |
+ kPlayExtraSpotFlag |
+ kOpenDoorSpotFlag |
+ kInfoReturnSpotFlag |
+ kAIBiochipSpotFlag |
+ kPegasusBiochipSpotFlag |
+ kOpticalBiochipSpotFlag |
+ kAirMaskSpotFlag;
+
+static const int32 kMainMenuID = 1;
+static const int32 kPauseMenuID = 2;
+static const int32 kCreditsMenuID = 3;
+static const int32 kDeathMenuID = 4;
+
+/////////////////////////////////////////////
+//
+// Menu commands.
+
+static const GameMenuCommand kMenuCmdOverview = kMenuCmdNoCommand + 1;
+static const GameMenuCommand kMenuCmdStartAdventure = kMenuCmdOverview + 1;
+static const GameMenuCommand kMenuCmdStartWalkthrough = kMenuCmdStartAdventure + 1;
+static const GameMenuCommand kMenuCmdRestore = kMenuCmdStartWalkthrough + 1;
+static const GameMenuCommand kMenuCmdCredits = kMenuCmdRestore + 1;
+static const GameMenuCommand kMenuCmdQuit = kMenuCmdCredits + 1;
+
+static const GameMenuCommand kMenuCmdDeathContinue = kMenuCmdQuit + 1;
+
+static const GameMenuCommand kMenuCmdDeathQuitDemo = kMenuCmdDeathContinue + 1;
+static const GameMenuCommand kMenuCmdDeathMainMenuDemo = kMenuCmdDeathQuitDemo + 1;
+
+static const GameMenuCommand kMenuCmdDeathRestore = kMenuCmdDeathMainMenuDemo + 1;
+static const GameMenuCommand kMenuCmdDeathMainMenu = kMenuCmdDeathRestore + 1;
+
+static const GameMenuCommand kMenuCmdPauseSave = kMenuCmdDeathMainMenu + 1;
+static const GameMenuCommand kMenuCmdPauseContinue = kMenuCmdPauseSave + 1;
+static const GameMenuCommand kMenuCmdPauseRestore = kMenuCmdPauseContinue + 1;
+static const GameMenuCommand kMenuCmdPauseQuit = kMenuCmdPauseRestore + 1;
+
+static const GameMenuCommand kMenuCmdCreditsMainMenu = kMenuCmdPauseQuit + 1;
+
+static const GameMenuCommand kMenuCmdCancelRestart = kMenuCmdCreditsMainMenu + 1;
+static const GameMenuCommand kMenuCmdEjectRestart = kMenuCmdCancelRestart + 1;
+
+static const TimeValue kMenuButtonHiliteTime = 20;
+static const TimeScale kMenuButtonHiliteScale = kSixtyTicksPerSecond;
+
+// PICT resources:
+
+// Warning light PICTs:
+
+static const ResIDType kLightOffID = 128;
+static const ResIDType kLightYellowID = 129;
+static const ResIDType kLightOrangeID = 130;
+static const ResIDType kLightRedID = 131;
+
+// Date PICTs:
+
+static const ResIDType kDatePrehistoricID = 138;
+static const ResIDType kDate2112ID = 139;
+static const ResIDType kDate2185ID = 140;
+static const ResIDType kDate2310ID = 141;
+static const ResIDType kDate2318ID = 142;
+
+/////////////////////////////////////////////
+//
+// Display Order
+
+static const DisplayOrder kCroppedMovieLayer = 11000;
+
+static const DisplayOrder kMonitorLayer = 12000;
+
+static const DisplayOrder kDragSpriteLayer = 15000;
+static const DisplayOrder kDragSpriteOrder = kDragSpriteLayer;
+
+static const DisplayOrder kInterfaceLayer = 20000;
+static const DisplayOrder kBackground1Order = kInterfaceLayer;
+static const DisplayOrder kBackground2Order = kBackground1Order + 1;
+static const DisplayOrder kBackground3Order = kBackground2Order + 1;
+static const DisplayOrder kBackground4Order = kBackground3Order + 1;
+static const DisplayOrder kDateOrder = kBackground4Order + 1;
+static const DisplayOrder kCompassOrder = kDateOrder + 1;
+static const DisplayOrder kEnergyBarOrder = kCompassOrder + 1;
+static const DisplayOrder kEnergyLightOrder = kEnergyBarOrder + 1;
+
+static const DisplayOrder kAILayer = 22000;
+static const DisplayOrder kAILeftAreaOrder = kAILayer;
+static const DisplayOrder kAIMiddleAreaOrder = kAILeftAreaOrder + 1;
+static const DisplayOrder kAIRightAreaOrder = kAIMiddleAreaOrder + 1;
+static const DisplayOrder kAIMovieOrder = kAIRightAreaOrder + 1;
+
+static const DisplayOrder kHilitesLayer = 23000;
+static const DisplayOrder kInventoryHiliteOrder = kHilitesLayer;
+static const DisplayOrder kBiochipHiliteOrder = kInventoryHiliteOrder + 1;
+
+static const DisplayOrder kPanelsLayer = 25000;
+static const DisplayOrder kInventoryPushOrder = kPanelsLayer;
+static const DisplayOrder kInventoryLidOrder = kInventoryPushOrder + 1;
+static const DisplayOrder kBiochipPushOrder = kInventoryLidOrder + 1;
+static const DisplayOrder kBiochipLidOrder = kBiochipPushOrder + 1;
+static const DisplayOrder kFinalMessageOrder = kBiochipLidOrder + 1;
+
+static const DisplayOrder kInfoLayer = 26000;
+static const DisplayOrder kInfoBackgroundOrder = kInfoLayer;
+static const DisplayOrder kInfoSpinOrder = kInfoBackgroundOrder + 1;
+
+static const DisplayOrder kScreenDimmerOrder = 30000;
+
+static const DisplayOrder kPauseScreenLayer = 31000;
+static const DisplayOrder kPauseMenuOrder = kPauseScreenLayer;
+static const DisplayOrder kSaveGameOrder = kPauseMenuOrder + 1;
+static const DisplayOrder kContinueOrder = kSaveGameOrder + 1;
+static const DisplayOrder kRestoreOrder = kContinueOrder + 1;
+static const DisplayOrder kSoundFXOrder = kRestoreOrder + 1;
+static const DisplayOrder kAmbienceOrder = kSoundFXOrder + 1;
+static const DisplayOrder kWalkthruOrder = kAmbienceOrder + 1;
+static const DisplayOrder kQuitToMainMenuOrder = kWalkthruOrder + 1;
+static const DisplayOrder kPauseLargeHiliteOrder = kQuitToMainMenuOrder + 1;
+static const DisplayOrder kPauseSmallHiliteOrder = kPauseLargeHiliteOrder + 1;
+
+/////////////////////////////////////////////
+//
+// Death reasons.
+enum {
+ // Caldoria
+ kDeathUncreatedInCaldoria = 1,
+ kDeathCardBomb,
+ kDeathShotBySinclair,
+ kDeathSinclairShotDelegate,
+ kDeathNuclearExplosion,
+
+ // TSA
+ kDeathUncreatedInTSA,
+ kDeathShotByTSARobots,
+
+ // Prehistoric
+ kDeathFallOffCliff,
+ kDeathEatenByDinosaur,
+ kDeathStranded,
+
+ // Norad
+ kDeathGassedInNorad,
+ kDeathArrestedInNorad,
+ kDeathWokeUpNorad,
+ kDeathSubDestroyed, // Unused
+ kDeathRobotThroughNoradDoor,
+ kDeathRobotSubControlRoom,
+
+ // Mars
+ kDeathWrongShuttleLock,
+ kDeathArrestedInMars,
+ kDeathRunOverByPod,
+ kDeathDidntGetOutOfWay,
+ kDeathReactorBurn,
+ kDeathDidntFindMarsBomb,
+ kDeathDidntDisarmMarsBomb,
+ kDeathNoMaskInMaze,
+ kDeathNoAirInMaze,
+ kDeathGroundByMazebot,
+ kDeathMissedOreBucket,
+ kDeathDidntLeaveBucket,
+ kDeathRanIntoCanyonWall, // Unused
+ kDeathRanIntoSpaceJunk,
+
+ // WSC
+ kDeathDidntStopPoison,
+ kDeathArrestedInWSC,
+ kDeathHitByPlasma,
+ kDeathShotOnCatwalk,
+
+ // Winning
+ kPlayerWonGame
+};
+
+static const CoordType kAILeftAreaLeft = 76;
+static const CoordType kAILeftAreaTop = 334;
+
+static const CoordType kAILeftAreaWidth = 96;
+static const CoordType kAILeftAreaHeight = 96;
+
+static const CoordType kAIMiddleAreaLeft = 172;
+static const CoordType kAIMiddleAreaTop = 334;
+
+static const CoordType kAIMiddleAreaWidth = 192;
+static const CoordType kAIMiddleAreaHeight = 96;
+
+static const CoordType kAIRightAreaLeft = 364;
+static const CoordType kAIRightAreaTop = 334;
+
+static const CoordType kAIRightAreaWidth = 96;
+static const CoordType kAIRightAreaHeight = 96;
+
+enum {
+ kTSAPlayerNotArrived, // initial state, must be zero
+ kTSAPlayerForcedReview, // Player must watch TBP before rip occurs.
+ kTSAPlayerDetectedRip, // Player finished TBP, rip alarm just went off.
+ kTSAPlayerNeedsHistoricalLog, // Player is instructed to get historical log
+ kTSAPlayerGotHistoricalLog,
+ kTSAPlayerInstalledHistoricalLog,
+ kTSABossSawHistoricalLog,
+ kRobotsAtCommandCenter,
+ kRobotsAtFrontDoor,
+ kRobotsAtReadyRoom,
+ kPlayerLockedInPegasus,
+ kPlayerOnWayToPrehistoric,
+ kPlayerWentToPrehistoric,
+ kPlayerOnWayToNorad,
+ kPlayerOnWayToMars,
+ kPlayerOnWayToWSC,
+ kPlayerFinishedWithTSA
+};
+
+/////////////////////////////////////////////
+//
+// Mode static constants.
+
+static const GameMode kModeInventoryPick = kLastGameShellMode + 1;
+static const GameMode kModeBiochipPick = kModeInventoryPick + 1;
+static const GameMode kModeInfoScreen = kModeBiochipPick + 1;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/cursor.cpp b/engines/pegasus/cursor.cpp
new file mode 100644
index 0000000000..5babdf34af
--- /dev/null
+++ b/engines/pegasus/cursor.cpp
@@ -0,0 +1,213 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/events.h"
+#include "common/stream.h"
+#include "common/system.h"
+#include "graphics/cursorman.h"
+#include "graphics/surface.h"
+#include "graphics/decoders/pict.h"
+
+#include "pegasus/cursor.h"
+#include "pegasus/graphics.h"
+#include "pegasus/pegasus.h"
+
+namespace Pegasus {
+
+Cursor::Cursor() {
+ _cursorObscured = false;
+ _index = -1;
+ startIdling();
+}
+
+Cursor::~Cursor() {
+ for (uint32 i = 0; i < _info.size(); i++) {
+ if (_info[i].surface) {
+ _info[i].surface->free();
+ delete _info[i].surface;
+ }
+ delete[] _info[i].palette;
+ }
+
+ stopIdling();
+}
+
+void Cursor::addCursorFrames(uint16 id) {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+ Common::SeekableReadStream *cursStream = vm->_resFork->getResource(MKTAG('C', 'u', 'r', 's'), id);
+ if (!cursStream)
+ error("Could not load cursor frames set %d", id);
+
+ uint16 frameCount = cursStream->readUint16BE();
+ for (uint16 i = 0; i < frameCount; i++) {
+ CursorInfo info;
+ info.tag = cursStream->readUint16BE();
+ info.hotspot.x = cursStream->readUint16BE();
+ info.hotspot.y = cursStream->readUint16BE();
+ info.surface = 0;
+ info.palette = 0;
+ info.colorCount = 0;
+ _info.push_back(info);
+ }
+
+ delete cursStream;
+
+ setCurrentFrameIndex(0);
+}
+
+void Cursor::setCurrentFrameIndex(int32 index) {
+ if (_index != index) {
+ _index = index;
+ if (index != -1) {
+ loadCursorImage(_info[index]);
+ CursorMan.replaceCursorPalette(_info[index].palette, 0, _info[index].colorCount);
+ CursorMan.replaceCursor((byte *)_info[index].surface->pixels, _info[index].surface->w, _info[index].surface->h, _info[index].hotspot.x, _info[index].hotspot.y, 0);
+ ((PegasusEngine *)g_engine)->_gfx->markCursorAsDirty();
+ }
+ }
+}
+
+int32 Cursor::getCurrentFrameIndex() const {
+ return _index;
+}
+
+void Cursor::show() {
+ if (!isVisible())
+ CursorMan.showMouse(true);
+
+ _cursorObscured = false;
+ ((PegasusEngine *)g_engine)->_gfx->markCursorAsDirty();
+}
+
+void Cursor::hide() {
+ CursorMan.showMouse(false);
+ setCurrentFrameIndex(0);
+ ((PegasusEngine *)g_engine)->_gfx->markCursorAsDirty();
+}
+
+void Cursor::hideUntilMoved() {
+ if (!_cursorObscured) {
+ hide();
+ _cursorObscured = true;
+ }
+}
+
+void Cursor::useIdleTime() {
+ if (g_system->getEventManager()->getMousePos() != _cursorLocation) {
+ _cursorLocation = g_system->getEventManager()->getMousePos();
+ if (_index != -1 && _cursorObscured)
+ show();
+ ((PegasusEngine *)g_engine)->_gfx->markCursorAsDirty();
+ }
+}
+
+void Cursor::getCursorLocation(Common::Point &pt) const {
+ pt = _cursorLocation;
+}
+
+bool Cursor::isVisible() {
+ return CursorMan.isVisible();
+}
+
+void Cursor::loadCursorImage(CursorInfo &cursorInfo) {
+ if (cursorInfo.surface)
+ return;
+
+ cursorInfo.surface = new Graphics::Surface();
+
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+ Common::SeekableReadStream *cicnStream = vm->_resFork->getResource(MKTAG('c', 'i', 'c', 'n'), cursorInfo.tag);
+
+ if (!cicnStream)
+ error("Failed to find color icon %d", cursorInfo.tag);
+
+ // PixMap section
+ Graphics::PICTDecoder::PixMap pixMap = Graphics::PICTDecoder::readPixMap(*cicnStream);
+
+ // Mask section
+ cicnStream->readUint32BE(); // mask baseAddr
+ uint16 maskRowBytes = cicnStream->readUint16BE(); // mask rowBytes
+ cicnStream->skip(3 * 2); // mask rect
+ /* uint16 maskHeight = */ cicnStream->readUint16BE();
+
+ // Bitmap section
+ cicnStream->readUint32BE(); // baseAddr
+ uint16 rowBytes = cicnStream->readUint16BE();
+ cicnStream->readUint16BE(); // top
+ cicnStream->readUint16BE(); // left
+ uint16 height = cicnStream->readUint16BE(); // bottom
+ cicnStream->readUint16BE(); // right
+
+ // Data section
+ cicnStream->readUint32BE(); // icon handle
+ cicnStream->skip(maskRowBytes * height); // FIXME: maskHeight doesn't work here, though the specs say it should
+ cicnStream->skip(rowBytes * height);
+
+ // Palette section
+ cicnStream->readUint32BE(); // always 0
+ cicnStream->readUint16BE(); // always 0
+ cursorInfo.colorCount = cicnStream->readUint16BE() + 1;
+
+ cursorInfo.palette = new byte[cursorInfo.colorCount * 3];
+ for (uint16 i = 0; i < cursorInfo.colorCount; i++) {
+ cicnStream->readUint16BE();
+ cursorInfo.palette[i * 3] = cicnStream->readUint16BE() >> 8;
+ cursorInfo.palette[i * 3 + 1] = cicnStream->readUint16BE() >> 8;
+ cursorInfo.palette[i * 3 + 2] = cicnStream->readUint16BE() >> 8;
+ }
+
+ // 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());
+
+ // While this looks sensible, it actually doesn't work for some cursors
+ // (ie. the 'can grab' hand)
+ //cursorInfo.surface->w = pixMap.bounds.width();
+ } else if (pixMap.pixelSize == 1) {
+ cursorInfo.surface->create(pixMap.bounds.width(), pixMap.bounds.height(), Graphics::PixelFormat::createFormatCLUT8());
+
+ for (int y = 0; y < pixMap.bounds.height(); y++) {
+ byte *line = (byte *)cursorInfo.surface->getBasePtr(0, y);
+
+ for (int x = 0; x < pixMap.bounds.width();) {
+ byte b = cicnStream->readByte();
+
+ for (int i = 0; i < 8; i++) {
+ *line++ = ((b & (1 << (7 - i))) != 0) ? 1 : 0;
+
+ if (++x == pixMap.bounds.width())
+ break;
+ }
+ }
+ }
+ } else {
+ error("Unhandled %dbpp cicn images", pixMap.pixelSize);
+ }
+
+ delete cicnStream;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/cursor.h b/engines/pegasus/cursor.h
new file mode 100644
index 0000000000..ada82e3967
--- /dev/null
+++ b/engines/pegasus/cursor.h
@@ -0,0 +1,84 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_CURSOR_H
+#define PEGASUS_CURSOR_H
+
+#include "common/array.h"
+#include "common/rect.h"
+
+#include "pegasus/timers.h"
+
+namespace Graphics {
+ struct Surface;
+}
+
+namespace Pegasus {
+
+// The original cursor code was in the graphics code directly,
+// unlike ScummVM where we have the cursor code separate. We're
+// going to go with CursorManager here and therefore not inherit
+// from the Sprite class.
+
+class Cursor : private Idler {
+public:
+ Cursor();
+ virtual ~Cursor();
+
+ void addCursorFrames(uint16 id);
+
+ void setCurrentFrameIndex(int32 index);
+ int32 getCurrentFrameIndex() const;
+
+ void show();
+ void hide();
+ void hideUntilMoved();
+ bool isVisible();
+
+ void getCursorLocation(Common::Point &) const;
+
+protected:
+ virtual void useIdleTime();
+
+private:
+ struct CursorInfo {
+ uint16 tag;
+ Common::Point hotspot;
+ Graphics::Surface *surface;
+ byte *palette;
+ uint16 colorCount;
+ };
+
+ Common::Point _cursorLocation;
+ Common::Array<CursorInfo> _info;
+ bool _cursorObscured;
+ int _index;
+
+ void loadCursorImage(CursorInfo &cursorInfo);
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/detection.cpp b/engines/pegasus/detection.cpp
new file mode 100644
index 0000000000..908005b665
--- /dev/null
+++ b/engines/pegasus/detection.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 "base/plugins.h"
+
+#include "engines/advancedDetector.h"
+#include "common/config-manager.h"
+#include "common/file.h"
+#include "common/savefile.h"
+
+#include "pegasus/pegasus.h"
+
+namespace Pegasus {
+
+struct PegasusGameDescription {
+ ADGameDescription desc;
+};
+
+bool PegasusEngine::hasFeature(EngineFeature f) const {
+ return
+ (f == kSupportsRTL)
+ || (f == kSupportsLoadingDuringRuntime)
+ || (f == kSupportsSavingDuringRuntime);
+}
+
+bool PegasusEngine::isDemo() const {
+ return (_gameDescription->desc.flags & ADGF_DEMO) != 0;
+}
+
+} // End of namespace Pegasus
+
+static const PlainGameDescriptor pegasusGames[] = {
+ {"pegasus", "The Journeyman Project: Pegasus Prime"},
+ {0, 0}
+};
+
+
+namespace Pegasus {
+
+static const PegasusGameDescription gameDescriptions[] = {
+ {
+ {
+ "pegasus",
+ "",
+ AD_ENTRY1s("JMP PP Resources", "d13a602d2498010d720a6534f097f88b", 2009943),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_MACRESFORK,
+ GUIO0()
+ },
+ },
+
+ {
+ {
+ "pegasus",
+ "Demo",
+ AD_ENTRY1s("JMP PP Resources", "d13a602d2498010d720a6534f097f88b", 360129),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_MACRESFORK|ADGF_DEMO,
+ GUIO1(GUIO_NOLAUNCHLOAD)
+ },
+ },
+
+ { AD_TABLE_END_MARKER }
+};
+
+} // End of namespace Pegasus
+
+
+class PegasusMetaEngine : public AdvancedMetaEngine {
+public:
+ PegasusMetaEngine() : AdvancedMetaEngine(Pegasus::gameDescriptions, sizeof(Pegasus::PegasusGameDescription), pegasusGames) {
+ _singleid = "pegasus";
+ }
+
+ virtual const char *getName() const {
+ return "The Journeyman Project: Pegasus Prime";
+ }
+
+ virtual const char *getOriginalCopyright() const {
+ return "The Journeyman Project: Pegasus Prime (C) Presto Studios";
+ }
+
+ virtual bool hasFeature(MetaEngineFeature f) const;
+ virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+ virtual SaveStateList listSaves(const char *target) const;
+ virtual int getMaximumSaveSlot() const { return 999; }
+ virtual void removeSaveState(const char *target, int slot) const;
+};
+
+bool PegasusMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsListSaves)
+ || (f == kSupportsLoadingDuringStartup)
+ || (f == kSupportsDeleteSave);
+}
+
+SaveStateList PegasusMetaEngine::listSaves(const char *target) const {
+ // The original had no pattern, so the user must rename theirs
+ // Note that we ignore the target because saves are compatible between
+ // all versions
+ Common::StringArray filenames = g_system->getSavefileManager()->listSavefiles("pegasus-*.sav");
+
+ SaveStateList saveList;
+ for (uint32 i = 0; i < filenames.size(); i++) {
+ // Isolate the description from the file name
+ Common::String desc = filenames[i].c_str() + 8;
+ for (int j = 0; j < 4; j++)
+ desc.deleteLastChar();
+
+ saveList.push_back(SaveStateDescriptor(i, desc));
+ }
+
+ return saveList;
+}
+
+void PegasusMetaEngine::removeSaveState(const char *target, int slot) const {
+ // See listSaves() for info on the pattern
+ Common::StringArray filenames = g_system->getSavefileManager()->listSavefiles("pegasus-*.sav");
+ g_system->getSavefileManager()->removeSavefile(filenames[slot].c_str());
+}
+
+bool PegasusMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+ const Pegasus::PegasusGameDescription *gd = (const Pegasus::PegasusGameDescription *)desc;
+
+ if (gd)
+ *engine = new Pegasus::PegasusEngine(syst, gd);
+
+ return (gd != 0);
+}
+
+#if PLUGIN_ENABLED_DYNAMIC(PEGASUS)
+ REGISTER_PLUGIN_DYNAMIC(PEGASUS, PLUGIN_TYPE_ENGINE, PegasusMetaEngine);
+#else
+ REGISTER_PLUGIN_STATIC(PEGASUS, PLUGIN_TYPE_ENGINE, PegasusMetaEngine);
+#endif
+
diff --git a/engines/pegasus/elements.cpp b/engines/pegasus/elements.cpp
new file mode 100644
index 0000000000..c84d555444
--- /dev/null
+++ b/engines/pegasus/elements.cpp
@@ -0,0 +1,568 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/macresman.h"
+#include "common/stream.h"
+
+#include "pegasus/elements.h"
+#include "pegasus/graphics.h"
+#include "pegasus/surface.h"
+
+namespace Pegasus {
+
+DisplayElement::DisplayElement(const DisplayElementID id) : IDObject(id) {
+ _elementIsDisplaying = false;
+ _elementIsVisible = false;
+ _elementOrder = 0;
+ _triggeredElement = this;
+ _nextElement = 0;
+}
+
+DisplayElement::~DisplayElement() {
+ if (isDisplaying())
+ ((PegasusEngine *)g_engine)->_gfx->removeDisplayElement(this);
+}
+
+void DisplayElement::setDisplayOrder(const DisplayOrder order) {
+ if (_elementOrder != order) {
+ _elementOrder = order;
+ if (isDisplaying()) {
+ ((PegasusEngine *)g_engine)->_gfx->removeDisplayElement(this);
+ ((PegasusEngine *)g_engine)->_gfx->addDisplayElement(this);
+ triggerRedraw();
+ }
+ }
+}
+
+void DisplayElement::startDisplaying() {
+ if (!isDisplaying()) {
+ ((PegasusEngine *)g_engine)->_gfx->addDisplayElement(this);
+ triggerRedraw();
+ }
+}
+
+void DisplayElement::stopDisplaying() {
+ if (isDisplaying()) {
+ triggerRedraw();
+ ((PegasusEngine *)g_engine)->_gfx->removeDisplayElement(this);
+ }
+}
+
+void DisplayElement::setBounds(const CoordType left, const CoordType top, const CoordType right, const CoordType bottom) {
+ setBounds(Common::Rect(left, top, right, bottom));
+}
+
+void DisplayElement::getBounds(Common::Rect &r) const {
+ r = _bounds;
+}
+
+void DisplayElement::sizeElement(const CoordType h, const CoordType v) {
+ Common::Rect newBounds = _bounds;
+ newBounds.right = _bounds.left + h;
+ newBounds.bottom = _bounds.top + v;
+ setBounds(newBounds);
+}
+
+void DisplayElement::moveElementTo(const CoordType h, const CoordType v) {
+ Common::Rect newBounds = _bounds;
+ newBounds.moveTo(h, v);
+ setBounds(newBounds);
+}
+
+void DisplayElement::moveElement(const CoordType dh, const CoordType dv) {
+ Common::Rect newBounds = _bounds;
+ newBounds.translate(dh, dv);
+ setBounds(newBounds);
+}
+
+void DisplayElement::getLocation(CoordType &h, CoordType &v) const {
+ h = _bounds.left;
+ v = _bounds.top;
+}
+
+void DisplayElement::centerElementAt(const CoordType h, const CoordType v) {
+ Common::Rect newBounds = _bounds;
+ newBounds.moveTo(h - (_bounds.width() / 2), v - (_bounds.height() / 2));
+ setBounds(newBounds);
+}
+
+void DisplayElement::getCenter(CoordType &h, CoordType &v) const {
+ h = (_bounds.left + _bounds.right) / 2;
+ v = (_bounds.top + _bounds.bottom) / 2;
+}
+
+void DisplayElement::setBounds(const Common::Rect &r) {
+ if (r != _bounds) {
+ triggerRedraw();
+ _bounds = r;
+ triggerRedraw();
+ }
+}
+
+void DisplayElement::hide() {
+ if (_elementIsVisible) {
+ triggerRedraw();
+ _elementIsVisible = false;
+ }
+}
+
+void DisplayElement::show() {
+ if (!_elementIsVisible) {
+ _elementIsVisible = true;
+ triggerRedraw();
+ }
+}
+
+// Only invalidates this element's bounding rectangle if all these conditions are true:
+// -- The triggered element is this element.
+// -- The element is displaying on the display list.
+// -- The element is visible.
+// -- The element is part of the active layer OR is one of the reserved items.
+void DisplayElement::triggerRedraw() {
+ GraphicsManager *gfx = ((PegasusEngine *)g_engine)->_gfx;
+
+ if (_triggeredElement == this) {
+ if (validToDraw(gfx->getBackOfActiveLayer(), gfx->getFrontOfActiveLayer()))
+ gfx->invalRect(_bounds);
+ } else {
+ _triggeredElement->triggerRedraw();
+ }
+}
+
+void DisplayElement::setTriggeredElement(DisplayElement *element) {
+ if (element)
+ _triggeredElement = element;
+ else
+ _triggeredElement = this;
+}
+
+bool DisplayElement::validToDraw(DisplayOrder backLayer, DisplayOrder frontLayer) {
+ return isDisplaying() && _elementIsVisible &&
+ (getObjectID() <= kHighestReservedElementID ||
+ (getDisplayOrder() >= backLayer &&
+ getDisplayOrder() <= frontLayer));
+}
+
+DropHighlight::DropHighlight(const DisplayElementID id) : DisplayElement(id) {
+ _highlightColor = 0;
+ _thickness = 2;
+ _cornerDiameter = 0;
+}
+
+void DropHighlight::draw(const Common::Rect &) {
+ Graphics::Surface *screen = ((PegasusEngine *)g_engine)->_gfx->getWorkArea();
+
+ // Since this is only used in two different ways, I'm only
+ // going to implement it in those two ways. Deal with it.
+
+ Common::Rect rect = _bounds;
+ rect.grow(-_thickness);
+ screen->frameRect(rect, _highlightColor);
+ rect.grow(1);
+ screen->frameRect(rect, _highlightColor);
+
+ if (_cornerDiameter == 8 && _thickness == 4) {
+ rect.grow(1);
+ screen->frameRect(rect, _highlightColor);
+ screen->hLine(rect.left + 1, rect.top - 1, rect.right - 2, _highlightColor);
+ screen->hLine(rect.left + 1, rect.bottom, rect.right - 2, _highlightColor);
+ screen->vLine(rect.left - 1, rect.top + 1, rect.bottom - 2, _highlightColor);
+ screen->vLine(rect.right, rect.top + 1, rect.bottom - 2, _highlightColor);
+ }
+}
+
+IdlerAnimation::IdlerAnimation(const DisplayElementID id) : Animation(id) {
+ _lastTime = 0xffffffff;
+}
+
+void IdlerAnimation::startDisplaying() {
+ if (!isDisplaying()) {
+ Animation::startDisplaying();
+ startIdling();
+ }
+}
+
+void IdlerAnimation::stopDisplaying() {
+ if (isDisplaying()) {
+ Animation::stopDisplaying();
+ stopIdling();
+ }
+}
+
+void IdlerAnimation::useIdleTime() {
+ uint32 currentTime = getTime();
+
+ if (currentTime != _lastTime) {
+ _lastTime = currentTime;
+ timeChanged(_lastTime);
+ }
+}
+
+void IdlerAnimation::timeChanged(const TimeValue) {
+ triggerRedraw();
+}
+
+FrameSequence::FrameSequence(const DisplayElementID id) : IdlerAnimation(id) {
+ _duration = 0;
+ _currentFrameNum = 0;
+ _resFork = new Common::MacResManager();
+ _numFrames = 0;
+}
+
+FrameSequence::~FrameSequence() {
+ delete _resFork;
+}
+
+void FrameSequence::useFileName(const Common::String &fileName) {
+ _resFork->open(fileName);
+}
+
+void FrameSequence::openFrameSequence() {
+ if (!_resFork->hasResFork())
+ return;
+
+ Common::SeekableReadStream *res = _resFork->getResource(MKTAG('P', 'F', 'r', 'm'), 0x80);
+
+ if (!res)
+ return;
+
+ uint32 scale = res->readUint32BE();
+ _bounds.top = res->readUint16BE();
+ _bounds.left = res->readUint16BE();
+ _bounds.bottom = res->readUint16BE();
+ _bounds.right = res->readUint16BE();
+ _numFrames = res->readUint16BE();
+ _duration = 0;
+
+ _frameTimes.clear();
+ for (uint32 i = 0; i < _numFrames; i++) {
+ TimeValue time = res->readUint32BE();
+ _duration += time;
+ _frameTimes.push_back(_duration);
+ }
+
+ setScale(scale);
+ setSegment(0, _duration);
+ setTime(0);
+ _currentFrameNum = 0;
+ newFrame(_currentFrameNum);
+ triggerRedraw();
+
+ delete res;
+}
+
+void FrameSequence::closeFrameSequence() {
+ stop();
+ _resFork->close();
+ _duration = 0;
+ _numFrames = 0;
+ _frameTimes.clear();
+}
+
+void FrameSequence::timeChanged(const TimeValue time) {
+ int16 frameNum = 0;
+ for (int16 i = _numFrames - 1; i >= 0; i--) {
+ if (_frameTimes[i] < time) {
+ frameNum = i;
+ break;
+ }
+ }
+
+ if (frameNum != _currentFrameNum) {
+ _currentFrameNum = frameNum;
+ newFrame(_currentFrameNum);
+ triggerRedraw();
+ }
+}
+
+void FrameSequence::setFrameNum(const int16 frameNum) {
+ int16 f = CLIP<int>(frameNum, 0, _numFrames);
+
+ if (_currentFrameNum != f) {
+ _currentFrameNum = f;
+ setTime(_frameTimes[f]);
+ newFrame(f);
+ triggerRedraw();
+ }
+}
+
+bool FrameSequence::isSequenceOpen() const {
+ return _numFrames != 0;
+}
+
+Sprite::Sprite(const DisplayElementID id) : DisplayElement(id) {
+ _numFrames = 0;
+ _currentFrameNum = 0xffffffff;
+ _currentFrame = 0;
+}
+
+Sprite::~Sprite() {
+ discardFrames();
+}
+
+void Sprite::discardFrames() {
+ if (!_frameArray.empty()) {
+ for (uint32 i = 0; i < _numFrames; i++) {
+ SpriteFrame *frame = _frameArray[i].frame;
+ frame->_referenceCount--;
+ if (frame->_referenceCount == 0)
+ delete frame;
+ }
+
+ _frameArray.clear();
+ _numFrames = 0;
+ _currentFrame = 0;
+ _currentFrameNum = 0xffffffff;
+ setBounds(0, 0, 0, 0);
+ }
+}
+
+void Sprite::addPICTResourceFrame(const ResIDType pictID, bool transparent, const CoordType left, const CoordType top) {
+ SpriteFrame *frame = new SpriteFrame();
+ frame->initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, pictID, transparent);
+ addFrame(frame, left, top);
+}
+
+uint32 Sprite::addFrame(SpriteFrame *frame, const CoordType left, const CoordType top) {
+ SpriteFrameRec frameRecord;
+ frameRecord.frame = frame;
+ frameRecord.frameLeft = left;
+ frameRecord.frameTop = top;
+ _frameArray.push_back(frameRecord);
+ _numFrames++;
+ frame->_referenceCount++;
+
+ Common::Rect frameBounds;
+ frame->getSurfaceBounds(frameBounds);
+
+ // 9/3/96
+ // BB Should this be + left or - left?
+ frameBounds.moveTo(_bounds.left + left, _bounds.top + top);
+
+ frameBounds.extend(_bounds);
+
+ if (_bounds != frameBounds)
+ setBounds(frameBounds);
+
+ return _numFrames - 1;
+}
+
+void Sprite::removeFrame(const uint32 frameNum) {
+ _frameArray[frameNum].frame->_referenceCount--;
+ if (_frameArray[frameNum].frame->_referenceCount == 0)
+ delete _frameArray[frameNum].frame;
+
+ // Calculate the new bounds
+ Common::Rect frameBounds;
+ for (uint32 i = 0; i < _numFrames; i++) {
+ if (i == frameNum)
+ continue;
+
+ Common::Rect r;
+ _frameArray[i].frame->getSurfaceBounds(r);
+ r.translate(_frameArray[i].frameLeft, _frameArray[i].frameTop);
+ frameBounds.extend(r);
+ }
+
+ _frameArray.remove_at(frameNum);
+
+ frameBounds.moveTo(_bounds.left, _bounds.top);
+ setBounds(frameBounds);
+
+ if (_currentFrameNum == frameNum)
+ triggerRedraw();
+ else if (_currentFrameNum != 0xffffffff && _currentFrameNum > frameNum)
+ --_currentFrameNum;
+}
+
+void Sprite::setCurrentFrameIndex(const int32 frameNum) {
+ if (frameNum < 0) {
+ if (_currentFrameNum != 0xffffffff) {
+ _currentFrameNum = 0xffffffff;
+ _currentFrame = 0;
+ triggerRedraw();
+ }
+ } else if (_numFrames > 0) {
+ uint32 f = frameNum % _numFrames;
+ if (f != _currentFrameNum) {
+ _currentFrameNum = f;
+ _currentFrame = &_frameArray[f];
+ triggerRedraw();
+ }
+ }
+}
+
+SpriteFrame *Sprite::getFrame(const int32 index) {
+ if (index < 0 || (uint32)index >= _numFrames)
+ return 0;
+
+ return _frameArray[index].frame;
+}
+
+void Sprite::draw(const Common::Rect &r) {
+ if (_currentFrame) {
+ Common::Rect frameBounds;
+ _currentFrame->frame->getSurfaceBounds(frameBounds);
+
+ frameBounds.translate(_bounds.left + _currentFrame->frameLeft, _bounds.top + _currentFrame->frameTop);
+ Common::Rect r1 = frameBounds.findIntersectingRect(r);
+
+ Common::Rect r2 = frameBounds;
+ r2.translate(-_bounds.left - _currentFrame->frameLeft, -_bounds.top - _currentFrame->frameTop);
+
+ _currentFrame->frame->drawImage(r2, r1);
+ }
+}
+
+SpriteSequence::SpriteSequence(const DisplayElementID id, const DisplayElementID spriteID) :
+ FrameSequence(id), _sprite(spriteID), _transparent(false) {
+}
+
+void SpriteSequence::openFrameSequence() {
+ if (!isSequenceOpen()) {
+ FrameSequence::openFrameSequence();
+
+ if (isSequenceOpen()) {
+ uint32 numFrames = getNumFrames();
+
+ for (uint32 i = 0; i < numFrames; ++i) {
+ SpriteFrame *frame = new SpriteFrame();
+ frame->initFromPICTResource(_resFork, i + 0x80, _transparent);
+ _sprite.addFrame(frame, 0, 0);
+ }
+
+ _sprite.setBounds(_bounds);
+ }
+ }
+}
+
+void SpriteSequence::closeFrameSequence() {
+ if (isSequenceOpen()) {
+ FrameSequence::closeFrameSequence();
+ _sprite.discardFrames();
+ }
+}
+
+void SpriteSequence::setBounds(const Common::Rect &bounds) {
+ FrameSequence::setBounds(bounds);
+ _sprite.setBounds(_bounds);
+}
+
+void SpriteSequence::draw(const Common::Rect &r) {
+ _sprite.draw(r);
+}
+
+void SpriteSequence::newFrame(const uint16 frame) {
+ _sprite.setCurrentFrameIndex(frame);
+}
+
+#define DRAW_PIXEL() \
+ if (bytesPerPixel == 2) \
+ *((uint16 *)dst) = black; \
+ else \
+ *((uint32 *)dst) = black; \
+ dst += bytesPerPixel
+
+#define SKIP_PIXEL() \
+ dst += bytesPerPixel
+
+void ScreenDimmer::draw(const Common::Rect &r) {
+ // We're going to emulate QuickDraw's srcOr+gray mode here
+ // In this mode, every other y column is all black (odd-columns).
+ // Basically, every row does three black and then one transparent
+ // repeatedly.
+
+ // The output is identical to the original
+
+ uint32 black = g_system->getScreenFormat().RGBToColor(0, 0, 0);
+ Graphics::Surface *screen = ((PegasusEngine *)g_engine)->_gfx->getWorkArea();
+ byte bytesPerPixel = g_system->getScreenFormat().bytesPerPixel;
+
+ // We're currently doing it to the whole screen to simplify the code
+
+ for (int y = 0; y < 480; y++) {
+ byte *dst = (byte *)screen->getBasePtr(0, y);
+
+ for (int x = 0; x < 640; x += 4) {
+ if (y & 1) {
+ DRAW_PIXEL();
+ DRAW_PIXEL();
+ SKIP_PIXEL();
+ DRAW_PIXEL();
+ } else {
+ SKIP_PIXEL();
+ DRAW_PIXEL();
+ DRAW_PIXEL();
+ DRAW_PIXEL();
+ }
+ }
+ }
+}
+
+#undef DRAW_PIXEL
+#undef SKIP_PIXEL
+
+SoundLevel::SoundLevel(const DisplayElementID id) : DisplayElement(id) {
+ _soundLevel = 0;
+}
+
+void SoundLevel::incrementLevel() {
+ if (_soundLevel < 12) {
+ _soundLevel++;
+ triggerRedraw();
+ }
+}
+
+void SoundLevel::decrementLevel() {
+ if (_soundLevel > 0) {
+ _soundLevel--;
+ triggerRedraw();
+ }
+}
+
+uint16 SoundLevel::getSoundLevel() {
+ return CLIP<int>(_soundLevel * 22, 0, 256);
+}
+
+void SoundLevel::setSoundLevel(uint16 level) {
+ uint16 newLevel = (level + 21) / 22;
+
+ if (newLevel != _soundLevel) {
+ _soundLevel = newLevel;
+ triggerRedraw();
+ }
+}
+
+void SoundLevel::draw(const Common::Rect &r) {
+ Common::Rect levelRect(_bounds.right + (8 * (_soundLevel - 12)), _bounds.top, _bounds.right, _bounds.bottom);
+ levelRect = r.findIntersectingRect(levelRect);
+
+ if (!levelRect.isEmpty()) {
+ Graphics::Surface *screen = ((PegasusEngine *)g_engine)->_gfx->getWorkArea();
+ screen->fillRect(levelRect, g_system->getScreenFormat().RGBToColor(0, 0, 0));
+ }
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/elements.h b/engines/pegasus/elements.h
new file mode 100644
index 0000000000..140553f675
--- /dev/null
+++ b/engines/pegasus/elements.h
@@ -0,0 +1,254 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_ELEMENTS_H
+#define PEGASUS_ELEMENTS_H
+
+#include "common/array.h"
+#include "common/rect.h"
+#include "common/str.h"
+#include "common/system.h"
+#include "graphics/surface.h"
+
+#include "pegasus/timers.h"
+#include "pegasus/util.h"
+
+namespace Common {
+ class MacResManager;
+}
+
+namespace Pegasus {
+
+class DisplayElement : public IDObject {
+friend class GraphicsManager;
+public:
+ DisplayElement(const DisplayElementID);
+ virtual ~DisplayElement();
+
+ void setDisplayOrder(const DisplayOrder);
+ DisplayOrder getDisplayOrder() const { return _elementOrder; }
+
+ bool validToDraw(DisplayOrder, DisplayOrder);
+
+ virtual void draw(const Common::Rect&) {}
+ bool isDisplaying() { return _elementIsDisplaying; }
+ virtual void startDisplaying();
+ virtual void stopDisplaying();
+
+ virtual void show();
+ virtual void hide();
+ bool isVisible() { return _elementIsVisible; }
+
+ // triggerRedraw only triggers a draw if the element is displaying and visible.
+ void triggerRedraw();
+ void setTriggeredElement(DisplayElement *);
+
+ virtual void setBounds(const CoordType, const CoordType, const CoordType, const CoordType);
+ virtual void setBounds(const Common::Rect &);
+ virtual void getBounds(Common::Rect &) const;
+ virtual void sizeElement(const CoordType, const CoordType);
+ virtual void moveElementTo(const CoordType, const CoordType);
+ virtual void moveElement(const CoordType, const CoordType);
+ virtual void getLocation(CoordType &, CoordType &) const;
+ virtual void getCenter(CoordType &, CoordType &) const;
+ virtual void centerElementAt(const CoordType, const CoordType);
+
+protected:
+ Common::Rect _bounds;
+ bool _elementIsVisible;
+ DisplayElement *_triggeredElement;
+
+ // Used only by PegasusEngine
+ bool _elementIsDisplaying;
+ DisplayOrder _elementOrder;
+ DisplayElement *_nextElement;
+};
+
+// I'm using the proper "highlight" instead of the evil
+// QuickDraw "hilite" :P (deal with it!)
+class DropHighlight : public DisplayElement {
+public:
+ DropHighlight(const DisplayElementID);
+ virtual ~DropHighlight() {}
+
+ void setHighlightColor(const uint32 &highlight) { _highlightColor = highlight; }
+ void getHighlightColor(uint32 &highlight) const { highlight = _highlightColor; }
+
+ void setHighlightThickness(const uint16 thickness) { _thickness = thickness; }
+ uint16 getHighlightThickness() const { return _thickness; }
+
+ void setHighlightCornerDiameter(const uint16 diameter) { _cornerDiameter = diameter; }
+ uint16 getHighlightCornerDiameter() const { return _cornerDiameter; }
+
+ virtual void draw(const Common::Rect&);
+
+protected:
+ uint32 _highlightColor;
+ uint16 _thickness;
+ uint16 _cornerDiameter;
+};
+
+class Animation : public DisplayElement, public DynamicElement {
+public:
+ Animation(const DisplayElementID id) : DisplayElement(id) {}
+};
+
+class IdlerAnimation : public Animation, public Idler {
+public:
+ IdlerAnimation(const DisplayElementID);
+
+ virtual void startDisplaying();
+ virtual void stopDisplaying();
+
+ TimeValue getLastTime() const { return _lastTime; }
+
+protected:
+ virtual void useIdleTime();
+ virtual void timeChanged(const TimeValue);
+
+ TimeValue _lastTime;
+};
+
+// This class reads PICT resources and plays them like a movie.
+// Assumes there is a resource of type 'PFrm' describing the time values for each
+// PICT frame, as well as the total time in the movie.
+// Assumes that PICT frames begin at PICT 128
+
+class FrameSequence : public IdlerAnimation {
+public:
+ FrameSequence(const DisplayElementID);
+ virtual ~FrameSequence();
+
+ void useFileName(const Common::String &fileName);
+
+ virtual void openFrameSequence();
+ virtual void closeFrameSequence();
+ bool isSequenceOpen() const;
+
+ uint16 getNumFrames() const { return _numFrames; }
+ virtual uint16 getFrameNum() const { return _currentFrameNum; }
+ virtual void setFrameNum(const int16);
+
+protected:
+ virtual void timeChanged(const TimeValue);
+ virtual void newFrame(const uint16) {}
+
+ Common::MacResManager *_resFork;
+ TimeValue _duration;
+
+ uint16 _numFrames;
+ Common::Array<TimeValue> _frameTimes;
+
+ uint16 _currentFrameNum;
+};
+
+class SpriteFrame;
+
+class Sprite : public DisplayElement {
+friend class SpriteFrame;
+public:
+ Sprite(const DisplayElementID);
+ virtual ~Sprite();
+
+ virtual void addPICTResourceFrame(const ResIDType, const bool, const CoordType, const CoordType);
+ virtual uint32 addFrame(SpriteFrame *, const CoordType, const CoordType);
+ virtual void removeFrame(const uint32);
+ virtual void discardFrames();
+
+ // Setting the current frame.
+ // If the index is negative, sets the current frame to NULL and hides the sprite.
+ // If the index is larger than the number of frames in the sprite, the number
+ // is treated modulo the number of frames.
+ virtual void setCurrentFrameIndex(const int32);
+ virtual uint32 getCurrentFrameIndex() const { return _currentFrameNum; }
+
+ virtual SpriteFrame *getFrame(const int32);
+
+ virtual void draw(const Common::Rect &);
+
+ uint32 getNumFrames() const { return _numFrames; }
+
+protected:
+ struct SpriteFrameRec {
+ SpriteFrame *frame;
+ CoordType frameLeft;
+ CoordType frameTop;
+ };
+
+ uint32 _numFrames;
+ uint32 _currentFrameNum;
+ SpriteFrameRec *_currentFrame;
+ Common::Array<SpriteFrameRec> _frameArray;
+};
+
+class SpriteSequence : public FrameSequence {
+public:
+ SpriteSequence(const DisplayElementID id, const DisplayElementID spriteID);
+ virtual ~SpriteSequence() {}
+
+ void useTransparent(bool transparent) { _transparent = transparent; }
+
+ virtual void openFrameSequence();
+ virtual void closeFrameSequence();
+
+ virtual void draw(const Common::Rect &);
+
+ virtual void setBounds(const Common::Rect &);
+
+protected:
+ virtual void newFrame(const uint16);
+
+ bool _transparent;
+ Sprite _sprite;
+};
+
+class ScreenDimmer : public DisplayElement {
+public:
+ ScreenDimmer() : DisplayElement(kScreenDimmerID) {}
+ virtual ~ScreenDimmer() {}
+
+ virtual void draw(const Common::Rect &);
+};
+
+class SoundLevel : public DisplayElement {
+public:
+ SoundLevel(const DisplayElementID);
+ virtual ~SoundLevel() {}
+
+ void incrementLevel();
+ void decrementLevel();
+
+ uint16 getSoundLevel();
+ void setSoundLevel(uint16);
+
+ void draw(const Common::Rect &);
+
+protected:
+ uint16 _soundLevel;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/energymonitor.cpp b/engines/pegasus/energymonitor.cpp
new file mode 100644
index 0000000000..8aa77eb341
--- /dev/null
+++ b/engines/pegasus/energymonitor.cpp
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/energymonitor.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/surface.h"
+
+namespace Pegasus {
+
+Blinker::Blinker() {
+ _sprite = 0;
+ _frame1 = -1;
+ _frame2 = -1;
+ _blinkDuration = 0;
+}
+
+void Blinker::startBlinking(Sprite *sprite, int32 frame1, int32 frame2, uint32 numBlinks, TimeValue blinkDuration, TimeScale blinkScale) {
+ stopBlinking();
+ _sprite = sprite;
+ _frame1 = frame1;
+ _frame2 = frame2;
+ _blinkDuration = blinkDuration;
+ setScale(blinkScale);
+ setSegment(0, blinkDuration * numBlinks * 2, blinkScale);
+ setTime(0);
+ start();
+}
+
+void Blinker::stopBlinking() {
+ if (_sprite) {
+ _sprite->setCurrentFrameIndex(_frame2);
+ _sprite = 0;
+ stop();
+ }
+}
+
+void Blinker::timeChanged(const TimeValue time) {
+ if (_sprite && _blinkDuration != 0) {
+ if (((time / _blinkDuration) & 1) != 0 || time == getDuration()) {
+ _sprite->setCurrentFrameIndex(_frame2);
+ if (!isRunning())
+ stopBlinking();
+ } else {
+ _sprite->setCurrentFrameIndex(_frame1);
+ }
+ }
+}
+
+static const NotificationFlags kEnergyExpiredFlag = 1;
+
+EnergyMonitor *g_energyMonitor = 0;
+
+EnergyMonitor::EnergyMonitor() : IdlerAnimation(kEnergyBarID), _energyLight(kWarningLightID) {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ _stage = kStageNoStage;
+
+ _calibrating = false;
+ _dontFlash = false;
+
+ setBounds(338, 48, 434, 54);
+
+ setDisplayOrder(kEnergyBarOrder);
+ startDisplaying();
+
+ SpriteFrame *frame = new SpriteFrame();
+ frame->initFromPICTResource(vm->_resFork, kLightOffID);
+ _energyLight.addFrame(frame, 0, 0);
+
+ frame = new SpriteFrame();
+ frame->initFromPICTResource(vm->_resFork, kLightYellowID);
+ _energyLight.addFrame(frame, 0, 0);
+
+ frame = new SpriteFrame();
+ frame->initFromPICTResource(vm->_resFork, kLightOrangeID);
+ _energyLight.addFrame(frame, 0, 0);
+
+ frame = new SpriteFrame();
+ frame->initFromPICTResource(vm->_resFork, kLightRedID);
+ _energyLight.addFrame(frame, 0, 0);
+
+ _energyLight.setBounds(540, 35, 600, 59);
+ _energyLight.setDisplayOrder(kEnergyLightOrder);
+ _energyLight.startDisplaying();
+
+ setScale(1);
+ setSegment(0, kMaxJMPEnergy);
+
+ setEnergyValue(kCasualEnergy);
+
+ g_energyMonitor = this;
+}
+
+EnergyMonitor::~EnergyMonitor() {
+ g_energyMonitor = 0;
+}
+
+void EnergyMonitor::setEnergyValue(const uint32 value) {
+ if (isRunning()) {
+ stop();
+ setTime(getStop() - value);
+ start();
+ } else {
+ setTime(getStop() - value);
+ }
+}
+
+void EnergyMonitor::startEnergyDraining() {
+ if (!isRunning()) {
+ _energyLight.show();
+ start();
+ show();
+ }
+}
+
+void EnergyMonitor::setEnergyDrainRate(Common::Rational rate) {
+ setRate(rate);
+}
+
+Common::Rational EnergyMonitor::getEnergyDrainRate() {
+ return getRate();
+}
+
+void EnergyMonitor::stopEnergyDraining() {
+ if (isRunning()) {
+ stop();
+ _energyLight.hide();
+ hide();
+ }
+}
+
+void EnergyMonitor::drainEnergy(const int32 delta) {
+ setTime(getTime() + delta);
+}
+
+int32 EnergyMonitor::getCurrentEnergy() {
+ return kMaxJMPEnergy - getTime();
+}
+
+void EnergyMonitor::timeChanged(const TimeValue currentTime) {
+ if (currentTime == getStop()) {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+ if (vm->getEnergyDeathReason() != -1)
+ vm->die(vm->getEnergyDeathReason());
+ } else {
+ uint32 currentEnergy = kMaxJMPEnergy - currentTime;
+
+ EnergyStage newStage;
+ if (currentEnergy > kWorriedEnergy)
+ newStage = kStageCasual;
+ else if (currentEnergy > kNervousEnergy)
+ newStage = kStageWorried;
+ else if (currentEnergy > kPanicStrickenEnergy)
+ newStage = kStageNervous;
+ else
+ newStage = kStagePanicStricken;
+
+ if (_stage != newStage) {
+ uint32 newFrame;
+
+ switch (newStage) {
+ case kStageCasual:
+ _barColor = g_system->getScreenFormat().RGBToColor(0x48, 0xB0, 0xD8);
+ newFrame = kFrameLightOff;
+ break;
+ case kStageWorried:
+ _barColor = g_system->getScreenFormat().RGBToColor(0xD8, 0xC0, 0x30);
+ newFrame = kFrameLightYellow;
+ break;
+ case kStageNervous:
+ _barColor = g_system->getScreenFormat().RGBToColor(0xD8, 0x78, 0x38);
+ newFrame = kFrameLightOrange;
+ break;
+ case kStagePanicStricken:
+ _barColor = g_system->getScreenFormat().RGBToColor(0xD8, 0x40, 0x38);
+ newFrame = kFrameLightRed;
+ break;
+ default:
+ error("no stage in energy monitor?");
+ break;
+ }
+
+ _stage = newStage;
+ uint32 oldFrame = _energyLight.getCurrentFrameIndex();
+
+ if (!_calibrating) {
+ if (oldFrame > newFrame || oldFrame == 0xffffffff || _dontFlash) {
+ _energyLight.setCurrentFrameIndex(newFrame);
+ _dontFlash = false;
+ } else {
+ _lightBlinker.startBlinking(&_energyLight, oldFrame, newFrame, 4, 1, 3);
+ triggerRedraw();
+ }
+ }
+ }
+
+ Common::Rect r;
+ calcLevelRect(r);
+ if (r != _levelRect) {
+ _levelRect = r;
+ triggerRedraw();
+ }
+ }
+}
+
+void EnergyMonitor::calcLevelRect(Common::Rect &r) {
+ if (getStop() == 0) {
+ r = Common::Rect();
+ } else {
+ getBounds(r);
+ r.left = r.right - r.width() * (kMaxJMPEnergy - getTime()) / getStop();
+ }
+}
+
+void EnergyMonitor::draw(const Common::Rect &r) {
+ Common::Rect r2 = r.findIntersectingRect(_levelRect);
+
+ if (!r2.isEmpty()) {
+ Graphics::Surface *screen = ((PegasusEngine *)g_engine)->_gfx->getWorkArea();
+ screen->fillRect(r2, _barColor);
+ }
+}
+
+void EnergyMonitor::calibrateEnergyBar() {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ _calibrating = true;
+
+ vm->setEnergyDeathReason(-1);
+
+ uint32 numFrames = _energyLight.getNumFrames();
+ for (uint32 i = 1; i < numFrames; i++) {
+ _energyLight.setCurrentFrameIndex(i);
+ _energyLight.show();
+ vm->delayShell(1, 3);
+ _energyLight.hide();
+ vm->delayShell(1, 3);
+ }
+
+ _energyLight.setCurrentFrameIndex(0);
+ _energyLight.hide();
+
+ show();
+ setEnergyValue(0);
+ setEnergyDrainRate(-(int32)kMaxJMPEnergy / 2);
+
+ // Make sure warning light is hidden...
+ _energyLight.hide();
+ while (getCurrentEnergy() != (int32)kMaxJMPEnergy) {
+ vm->checkCallBacks();
+ vm->refreshDisplay();
+ g_system->delayMillis(10);
+ }
+
+ vm->refreshDisplay();
+ setEnergyDrainRate(0);
+ hide();
+
+ _calibrating = false;
+}
+
+void EnergyMonitor::restoreLastEnergyValue() {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ _dontFlash = true;
+ setEnergyValue(vm->getSavedEnergyValue());
+ vm->resetEnergyDeathReason();
+}
+
+void EnergyMonitor::saveCurrentEnergyValue() {
+ ((PegasusEngine *)g_engine)->setLastEnergyValue(getCurrentEnergy());
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/energymonitor.h b/engines/pegasus/energymonitor.h
new file mode 100644
index 0000000000..02377d515a
--- /dev/null
+++ b/engines/pegasus/energymonitor.h
@@ -0,0 +1,111 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_ENERGYMONITOR_H
+#define PEGASUS_ENERGYMONITOR_H
+
+#include "pegasus/elements.h"
+
+namespace Pegasus {
+
+class Sprite;
+
+class Blinker : private IdlerTimeBase {
+public:
+ Blinker();
+ virtual ~Blinker() {}
+
+ void startBlinking(Sprite *sprite, int32 frame1, int32 frame2, uint32 numBlinks, TimeValue blinkDuration, TimeScale blinkScale);
+ void stopBlinking();
+
+protected:
+ virtual void timeChanged(const TimeValue);
+
+ Sprite *_sprite;
+ int32 _frame1;
+ int32 _frame2;
+ TimeValue _blinkDuration;
+};
+
+// Energy monitor constants.
+
+// These are in seconds.
+// Max is two hours
+static const uint32 kMaxJMPEnergy = 7200;
+
+static const uint32 kCasualEnergy = kMaxJMPEnergy * 100 / 100; // 100%
+static const uint32 kWorriedEnergy = kMaxJMPEnergy * 50 / 100; // 50%
+static const uint32 kNervousEnergy = kMaxJMPEnergy * 25 / 100; // 25%
+static const uint32 kPanicStrickenEnergy = kMaxJMPEnergy * 5 / 100; // 5%
+
+static const uint32 kFullEnergy = kCasualEnergy;
+
+static const uint32 kFrameLightOff = 0;
+static const uint32 kFrameLightYellow = 1;
+static const uint32 kFrameLightOrange = 2;
+static const uint32 kFrameLightRed = 3;
+
+static const int kEnergyDrainNormal = 1;
+static const int kMarsReactorEnergyDrainNoShield = 6;
+static const int kMarsReactorEnergyDrainWithShield = 3;
+static const int kWSCPoisonEnergyDrainWithDart = 20;
+static const int kWSCPoisonEnergyDrainNoDart = 10;
+
+class EnergyMonitor : private IdlerAnimation {
+public:
+ EnergyMonitor();
+ virtual ~EnergyMonitor();
+
+ void setEnergyValue(const uint32);
+ void startEnergyDraining();
+ void setEnergyDrainRate(Common::Rational);
+ Common::Rational getEnergyDrainRate();
+ void stopEnergyDraining();
+ void drainEnergy(const int32);
+ int32 getCurrentEnergy();
+
+ void restoreLastEnergyValue();
+ void saveCurrentEnergyValue();
+
+ void calibrateEnergyBar();
+
+protected:
+ void timeChanged(const TimeValue);
+ void calcLevelRect(Common::Rect &);
+ void draw(const Common::Rect &);
+
+ uint32 _barColor;
+ Common::Rect _levelRect;
+ EnergyStage _stage;
+ Sprite _energyLight;
+ Blinker _lightBlinker;
+ bool _calibrating, _dontFlash;
+};
+
+extern EnergyMonitor *g_energyMonitor;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/fader.cpp b/engines/pegasus/fader.cpp
new file mode 100644
index 0000000000..a2bbf22944
--- /dev/null
+++ b/engines/pegasus/fader.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/fader.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/sound.h"
+#include "pegasus/util.h"
+
+namespace Pegasus {
+
+Fader::Fader() {
+ _currentValue = 0;
+ _currentFaderMove._numKnots = 0;
+}
+
+void Fader::setFaderValue(const int32 newValue) {
+ _currentValue = newValue;
+}
+
+bool Fader::initFaderMove(const FaderMoveSpec &spec) {
+ bool faderMoves = false;
+ int32 value = 0;
+
+ if (spec._numKnots > 0) {
+ stopFader();
+ value = spec._knots[0].knotValue;
+ TimeValue startTime = spec._knots[0].knotTime;
+
+ if (startTime != 0xffffffff) {
+ if (spec._numKnots > 1) {
+ TimeValue stopTime = spec._knots[spec._numKnots - 1].knotTime;
+
+ if (spec._faderScale > 0) {
+ if (stopTime > startTime) {
+ for (uint32 i = 1; i < spec._numKnots; ++i) {
+ if (spec._knots[i - 1].knotValue != spec._knots[i].knotValue) {
+ faderMoves = true;
+ break;
+ }
+ }
+
+ if (faderMoves)
+ _currentFaderMove = spec;
+ } else if (spec._knots[spec._numKnots - 1].knotValue != value) {
+ value = spec._knots[spec._numKnots - 1].knotValue;
+ }
+ }
+ }
+ }
+ }
+
+ setFaderValue(value);
+ return faderMoves;
+}
+
+void Fader::startFader(const FaderMoveSpec &spec) {
+ if (initFaderMove(spec)) {
+ setFlags(0);
+ setScale(spec._faderScale);
+ setSegment(spec._knots[0].knotTime, spec._knots[spec._numKnots - 1].knotTime);
+ setTime(spec._knots[0].knotTime);
+ start();
+ }
+}
+
+void Fader::startFaderSync(const FaderMoveSpec &spec) {
+ if (initFaderMove(spec)) {
+ setFlags(0);
+ setScale(spec._faderScale);
+ setSegment(spec._knots[0].knotTime, spec._knots[spec._numKnots - 1].knotTime);
+ setTime(spec._knots[0].knotTime);
+ start();
+
+ while (isFading()) {
+ ((PegasusEngine *)g_engine)->checkCallBacks();
+ useIdleTime();
+ }
+
+ // Once more, for good measure, to make sure that there are no boundary
+ // condition problems.
+ useIdleTime();
+ stopFader();
+ }
+}
+
+void Fader::loopFader(const FaderMoveSpec &spec) {
+ if (initFaderMove(spec)) {
+ setFlags(kLoopTimeBase);
+ setScale(spec._faderScale);
+ setSegment(spec._knots[0].knotTime, spec._knots[spec._numKnots - 1].knotTime);
+ setTime(spec._knots[0].knotTime);
+ start();
+ }
+}
+
+void Fader::stopFader() {
+ stop();
+}
+
+void Fader::pauseFader() {
+ stopFader();
+}
+
+void Fader::continueFader() {
+ if (getTime() < getStop())
+ start();
+}
+
+void Fader::timeChanged(const TimeValue newTime) {
+ if (_currentFaderMove._numKnots != 0) {
+ uint32 i;
+ for (i = 0; i < _currentFaderMove._numKnots; i++)
+ if (_currentFaderMove._knots[i].knotTime > newTime)
+ break;
+
+ int32 newValue;
+ if (i == 0)
+ newValue = _currentFaderMove._knots[0].knotValue;
+ else if (i == _currentFaderMove._numKnots)
+ newValue = _currentFaderMove._knots[i - 1].knotValue;
+ else
+ newValue = linearInterp(_currentFaderMove._knots[i - 1].knotTime, _currentFaderMove._knots[i].knotTime, newTime, _currentFaderMove._knots[i - 1].knotValue, _currentFaderMove._knots[i].knotValue);
+
+ if (newValue != _currentValue)
+ setFaderValue(newValue);
+ }
+}
+
+void FaderMoveSpec::makeOneKnotFaderSpec(const int32 knotValue) {
+ _numKnots = 1;
+ _knots[0].knotTime = 0;
+ _knots[0].knotValue = knotValue;
+}
+
+void FaderMoveSpec::makeTwoKnotFaderSpec(const TimeScale faderScale, const TimeValue time1, const int32 value1, const TimeValue time2, const int32 value2) {
+ _numKnots = 2;
+ _faderScale = faderScale;
+ _knots[0].knotTime = time1;
+ _knots[0].knotValue = value1;
+ _knots[1].knotTime = time2;
+ _knots[1].knotValue = value2;
+}
+
+void FaderMoveSpec::insertFaderKnot(const TimeValue knotTime, const int32 knotValue) {
+ if (_numKnots != kMaxFaderKnots) {
+ uint32 index;
+ for (index = 0; index < _numKnots; index++) {
+ if (knotTime == _knots[index].knotTime) {
+ _knots[index].knotValue = knotValue;
+ return;
+ } else if (knotTime < _knots[index].knotTime) {
+ break;
+ }
+ }
+
+ for (uint32 i = _numKnots; i > index; i--)
+ _knots[i] = _knots[i - 1];
+
+ _knots[index].knotTime = knotTime;
+ _knots[index].knotValue = knotValue;
+ _numKnots++;
+ }
+}
+
+void FaderAnimation::setFaderValue(const int32 newValue) {
+ if (getFaderValue() != newValue) {
+ Fader::setFaderValue(newValue);
+ triggerRedraw();
+ }
+}
+
+SoundFader::SoundFader() {
+ _sound = 0;
+ _masterVolume = 0xff;
+}
+
+void SoundFader::attachSound(Sound *sound) {
+ if (!sound && isFading())
+ stopFader();
+
+ _sound = sound;
+}
+
+void SoundFader::setFaderValue(const int32 newVolume) {
+ if (_sound)
+ _sound->setVolume((newVolume * _masterVolume) >> 8);
+
+ _currentValue = newVolume;
+}
+
+void SoundFader::setMasterVolume(const uint16 masterVolume) {
+ _masterVolume = masterVolume;
+ setFaderValue(getFaderValue());
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/fader.h b/engines/pegasus/fader.h
new file mode 100644
index 0000000000..0a8cd549e6
--- /dev/null
+++ b/engines/pegasus/fader.h
@@ -0,0 +1,130 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_FADER_H
+#define PEGASUS_FADER_H
+
+#include "pegasus/elements.h"
+#include "pegasus/timers.h"
+
+namespace Pegasus {
+
+class Fader;
+
+class FaderMoveSpec {
+friend class Fader;
+public:
+ FaderMoveSpec() {
+ _faderScale = kDefaultTimeScale;
+ _numKnots = 0;
+ }
+
+ FaderMoveSpec(const TimeScale scale) {
+ _faderScale = scale;
+ _numKnots = 0;
+ }
+
+ void setFaderScale(const TimeScale scale) { _faderScale = scale; }
+ TimeScale getFaderScale() const { return _faderScale; }
+
+ void makeOneKnotFaderSpec(const int32);
+ void makeTwoKnotFaderSpec(const TimeScale, const TimeValue, const int32, const TimeValue, const int32);
+
+ void insertFaderKnot(const TimeValue, const int32);
+
+ uint32 getNumKnots() const { return _numKnots; }
+ TimeValue getNthKnotTime(const uint32 index) const { return _knots[index].knotTime; }
+ int32 getNthKnotValue(const uint32 index) const { return _knots[index].knotValue; }
+
+protected:
+ struct FaderKnot {
+ TimeValue knotTime;
+ int32 knotValue;
+ };
+
+ TimeScale _faderScale;
+ uint32 _numKnots;
+
+ static const uint32 kMaxFaderKnots = 20;
+ FaderKnot _knots[kMaxFaderKnots];
+};
+
+class Fader : public IdlerTimeBase {
+public:
+ Fader();
+ virtual ~Fader() {}
+
+ virtual void setFaderValue(const int32);
+ int32 getFaderValue() const { return _currentValue; }
+ virtual void startFader(const FaderMoveSpec &);
+ virtual void startFaderSync(const FaderMoveSpec &);
+ virtual void loopFader(const FaderMoveSpec &);
+ virtual void stopFader();
+ virtual bool isFading() { return isRunning(); }
+
+ void pauseFader();
+ void continueFader();
+
+ void getCurrentFaderMove(FaderMoveSpec &spec) { spec = _currentFaderMove; }
+
+protected:
+ bool initFaderMove(const FaderMoveSpec &);
+ virtual void timeChanged(const TimeValue);
+
+ int32 _currentValue;
+ FaderMoveSpec _currentFaderMove;
+};
+
+class FaderAnimation : public DisplayElement, public Fader {
+public:
+ FaderAnimation(const DisplayElementID id) : DisplayElement(id) {}
+ virtual ~FaderAnimation() {}
+
+ void setFaderValue(const int32);
+};
+
+class Sound;
+
+class SoundFader : public Fader {
+friend class Sound;
+public:
+ SoundFader();
+ virtual ~SoundFader() {}
+
+ void setFaderValue(const int32);
+
+ void setMasterVolume(const uint16);
+ uint16 getMasterVolume() const { return _masterVolume; }
+
+protected:
+ void attachSound(Sound *);
+
+ Sound *_sound;
+ uint16 _masterVolume;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/gamestate.cpp b/engines/pegasus/gamestate.cpp
new file mode 100644
index 0000000000..7a4e657e02
--- /dev/null
+++ b/engines/pegasus/gamestate.cpp
@@ -0,0 +1,2359 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/error.h"
+#include "common/stream.h"
+
+#include "pegasus/constants.h"
+#include "pegasus/gamestate.h"
+#include "pegasus/scoring.h"
+
+namespace Common {
+DECLARE_SINGLETON(Pegasus::GameStateManager);
+}
+
+namespace Pegasus {
+
+Common::Error GameStateManager::writeGameState(Common::WriteStream *stream) {
+ stream->writeUint16BE(_currentNeighborhood);
+ stream->writeUint16BE(_currentRoom);
+ stream->writeByte(_currentDirection);
+ stream->writeUint16BE(_nexNeighborhoodID);
+ stream->writeUint16BE(_nextRoomID);
+ stream->writeByte(_nextDirection);
+ stream->writeUint16BE(_lastNeighborhood);
+ stream->writeUint16BE(_lastRoom);
+ stream->writeByte(_lastDirection);
+ stream->writeUint16BE(_openDoorRoom);
+ stream->writeByte(_openDoorDirection);
+
+ _globalFlags.writeToStream(stream);
+ _scoringFlags.writeToStream(stream);
+ _itemTakenFlags.writeToStream(stream);
+
+ writeCaldoriaState(stream);
+ writeTSAState(stream);
+ writePrehistoricState(stream);
+ writeNoradState(stream);
+ writeMarsState(stream);
+ writeWSCState(stream);
+
+ if (stream->err())
+ return Common::kWritingFailed;
+
+ return Common::kNoError;
+}
+
+Common::Error GameStateManager::readGameState(Common::ReadStream *stream) {
+ _currentNeighborhood = stream->readUint16BE();
+ _currentRoom = stream->readUint16BE();
+ _currentDirection = stream->readByte();
+ _nexNeighborhoodID = stream->readUint16BE();
+ _nextRoomID = stream->readUint16BE();
+ _nextDirection = stream->readByte();
+ _lastNeighborhood = stream->readUint16BE();
+ _lastRoom = stream->readUint16BE();
+ _lastDirection = stream->readByte();
+ _openDoorRoom = stream->readUint16BE();
+ _openDoorDirection = stream->readByte();
+
+ _globalFlags.readFromStream(stream);
+ _scoringFlags.readFromStream(stream);
+ _itemTakenFlags.readFromStream(stream);
+
+ readCaldoriaState(stream);
+ readTSAState(stream);
+ readPrehistoricState(stream);
+ readNoradState(stream);
+ readMarsState(stream);
+ readWSCState(stream);
+
+ if (stream->err())
+ return Common::kReadingFailed;
+
+ return Common::kNoError;
+}
+
+void GameStateManager::resetGameState() {
+ _currentNeighborhood = kNoNeighborhoodID;
+ _currentRoom = kNoRoomID;
+ _currentDirection = kNoDirection;
+ _nexNeighborhoodID = kNoNeighborhoodID;
+ _nextRoomID = kNoRoomID;
+ _nextDirection = kNoDirection;
+ _lastNeighborhood = kNoNeighborhoodID;
+ _lastRoom = kNoRoomID;
+ _lastDirection = kNoDirection;
+ _openDoorRoom = kNoRoomID;
+ _openDoorDirection = kNoDirection;
+
+ _globalFlags.clearAllFlags();
+ _scoringFlags.clearAllFlags();
+ _itemTakenFlags.clearAllFlags();
+
+ resetCaldoriaState();
+ resetTSAState();
+ resetPrehistoricState();
+ resetNoradState();
+ resetMarsState();
+ resetWSCState();
+}
+
+void GameStateManager::getCurrentLocation(NeighborhoodID &neighborhood, RoomID &room, DirectionConstant &direction) {
+ neighborhood = _currentNeighborhood;
+ room = _currentRoom;
+ direction = _currentDirection;
+}
+
+void GameStateManager::setCurrentLocation(const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) {
+ _lastNeighborhood = _currentNeighborhood;
+ _lastRoom = _currentRoom;
+ _lastDirection = _currentDirection;
+ _currentNeighborhood = neighborhood;
+ _currentRoom = room;
+ _currentDirection = direction;
+}
+
+NeighborhoodID GameStateManager::getCurrentNeighborhood() {
+ return _currentNeighborhood;
+}
+
+void GameStateManager::setCurrentNeighborhood(const NeighborhoodID neighborhood) {
+ _lastNeighborhood = _currentNeighborhood;
+ _currentNeighborhood = neighborhood;
+}
+
+RoomID GameStateManager::getCurrentRoom() {
+ return _currentRoom;
+}
+
+void GameStateManager::setCurrentRoom(const RoomID room) {
+ _lastRoom = _currentRoom;
+ _currentRoom = room;
+}
+
+DirectionConstant GameStateManager::getCurrentDirection() {
+ return _currentDirection;
+}
+
+void GameStateManager::setCurrentDirection(const DirectionConstant direction) {
+ _lastDirection = _currentDirection;
+ _currentDirection = direction;
+}
+
+RoomViewID GameStateManager::getCurrentRoomAndView() {
+ return MakeRoomView(_currentRoom, _currentDirection);
+}
+
+void GameStateManager::getNextLocation(NeighborhoodID &neighborhood, RoomID &room, DirectionConstant &direction) {
+ neighborhood = _nexNeighborhoodID;
+ room = _nextRoomID;
+ direction = _nextDirection;
+}
+
+void GameStateManager::setNextLocation(const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) {
+ _nexNeighborhoodID = neighborhood;
+ _nextRoomID = room;
+ _nextDirection = direction;
+}
+
+NeighborhoodID GameStateManager::getNextNeighborhood() {
+ return _nexNeighborhoodID;
+}
+
+void GameStateManager::setNextNeighborhood(const NeighborhoodID neighborhood) {
+ _nexNeighborhoodID = neighborhood;
+}
+
+RoomID GameStateManager::getNextRoom() {
+ return _nextRoomID;
+}
+
+void GameStateManager::setNextRoom(const RoomID room) {
+ _nextRoomID = room;
+}
+
+DirectionConstant GameStateManager::getNextDirection() {
+ return _nextDirection;
+}
+
+void GameStateManager::setNextDirection(const DirectionConstant direction) {
+ _nextDirection = direction;
+}
+
+void GameStateManager::getLastLocation(NeighborhoodID &neighborhood, RoomID &room, DirectionConstant &direction) {
+ neighborhood = _currentNeighborhood;
+ room = _currentRoom;
+ direction = _currentDirection;
+}
+
+void GameStateManager::setLastLocation(const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) {
+ _currentNeighborhood = neighborhood;
+ _currentRoom = room;
+ _currentDirection = direction;
+}
+
+NeighborhoodID GameStateManager::getLastNeighborhood() {
+ return _lastNeighborhood;
+}
+
+void GameStateManager::setLastNeighborhood(const NeighborhoodID neighborhood) {
+ _lastNeighborhood = neighborhood;
+}
+
+RoomID GameStateManager::getLastRoom() {
+ return _lastRoom;
+}
+
+void GameStateManager::setLastRoom(const RoomID room) {
+ _lastRoom = room;
+}
+
+DirectionConstant GameStateManager::getLastDirection() {
+ return _lastDirection;
+}
+
+void GameStateManager::setLastDirection(const DirectionConstant direction) {
+ _lastDirection = direction;
+}
+
+RoomViewID GameStateManager::getLastRoomAndView() {
+ return MakeRoomView(_lastRoom, _lastDirection);
+}
+
+void GameStateManager::getOpenDoorLocation(RoomID &room, DirectionConstant &direction) {
+ room = _openDoorRoom;
+ direction = _openDoorDirection;
+}
+
+void GameStateManager::setOpenDoorLocation(const RoomID room, const DirectionConstant direction) {
+ _openDoorRoom = room;
+ _openDoorDirection = direction;
+}
+
+RoomID GameStateManager::getOpenDoorRoom() {
+ return _openDoorRoom;
+}
+
+void GameStateManager::setOpenDoorRoom(const RoomID room) {
+ _openDoorRoom = room;
+}
+
+DirectionConstant GameStateManager::getOpenDoorDirection() {
+ return _openDoorDirection;
+}
+
+void GameStateManager::setOpenDoorDirection(const DirectionConstant direction) {
+ _openDoorDirection = direction;
+}
+
+RoomViewID GameStateManager::getDoorOpenRoomAndView() {
+ return MakeRoomView(_openDoorRoom, _openDoorDirection);
+}
+
+bool GameStateManager::isCurrentDoorOpen() {
+ return _openDoorRoom == _currentRoom && _openDoorDirection == _currentDirection;
+}
+
+GameScoreType GameStateManager::getCaldoriaTSAScore() {
+ GameScoreType result = 0;
+
+ if (_scoringFlags.getFlag(kScoringSawINNFlag))
+ result += kSawINNScore;
+ if (_scoringFlags.getFlag(kScoringTookShowerFlag))
+ result += kTookShowerScore;
+ if (_scoringFlags.getFlag(kScoringFixedHairFlag))
+ result += kFixedHairScore;
+ if (_scoringFlags.getFlag(kScoringGotKeyCardFlag))
+ result += kGotKeyCardScore;
+ if (_scoringFlags.getFlag(kScoringReadPaperFlag))
+ result += kReadPaperScore;
+ if (_scoringFlags.getFlag(kScoringLookThroughTelescopeFlag))
+ result += kLookThroughTelescopeScore;
+ if (_scoringFlags.getFlag(kScoringSawCaldoriaKioskFlag))
+ result += kSawCaldoriaKioskScore;
+ if (_scoringFlags.getFlag(kScoringGoToTSAFlag))
+ result += kGoToTSAScore;
+ if (_scoringFlags.getFlag(kScoringEnterTSAFlag))
+ result += kEnterTSAScore;
+ if (_scoringFlags.getFlag(kScoringSawBust1Flag))
+ result += kSawBust1Score;
+ if (_scoringFlags.getFlag(kScoringSawBust2Flag))
+ result += kSawBust2Score;
+ if (_scoringFlags.getFlag(kScoringSawBust3Flag))
+ result += kSawBust3Score;
+ if (_scoringFlags.getFlag(kScoringSawBust4Flag))
+ result += kSawBust4Score;
+ if (_scoringFlags.getFlag(kScoringSawBust5Flag))
+ result += kSawBust5Score;
+ if (_scoringFlags.getFlag(kScoringSawBust6Flag))
+ result += kSawBust6Score;
+ if (_scoringFlags.getFlag(kScoringSawTheoryFlag))
+ result += kSawTheoryScore;
+ if (_scoringFlags.getFlag(kScoringSawBackgroundFlag))
+ result += kSawBackgroundScore;
+ if (_scoringFlags.getFlag(kScoringSawProcedureFlag))
+ result += kSawProcedureScore;
+ if (_scoringFlags.getFlag(kScoringGotJourneymanKeyFlag))
+ result += kGotJourneymanKeyScore;
+ if (_scoringFlags.getFlag(kScoringGotPegasusBiochipFlag))
+ result += kGotPegasusBiochipScore;
+ if (_scoringFlags.getFlag(kScoringGotBiosuitFlag))
+ result += kGotBiosuitScore;
+ if (_scoringFlags.getFlag(kScoringGoToPrehistoricFlag))
+ result += kGoToPrehistoricScore;
+ if (_scoringFlags.getFlag(kScoringPutLogInReaderFlag))
+ result += kPutLogInReaderScore;
+ if (_scoringFlags.getFlag(kScoringSawCaldoriaNormalFlag))
+ result += kSawCaldoriaNormalScore;
+ if (_scoringFlags.getFlag(kScoringSawCaldoriaAlteredFlag))
+ result += kSawCaldoriaAlteredScore;
+ if (_scoringFlags.getFlag(kScoringSawNoradNormalFlag))
+ result += kSawNoradNormalScore;
+ if (_scoringFlags.getFlag(kScoringSawNoradAlteredFlag))
+ result += kSawNoradAlteredScore;
+ if (_scoringFlags.getFlag(kScoringSawMarsNormalFlag))
+ result += kSawMarsNormalScore;
+ if (_scoringFlags.getFlag(kScoringSawMarsAlteredFlag))
+ result += kSawMarsAlteredScore;
+ if (_scoringFlags.getFlag(kScoringSawWSCNormalFlag))
+ result += kSawWSCNormalScore;
+ if (_scoringFlags.getFlag(kScoringSawWSCAlteredFlag))
+ result += kSawWSCAlteredScore;
+ if (_scoringFlags.getFlag(kScoringWentToReadyRoom2Flag))
+ result += kWentToReadyRoom2Score;
+ if (_scoringFlags.getFlag(kScoringWentAfterSinclairFlag))
+ result += kWentAfterSinclairScore;
+ if (_scoringFlags.getFlag(kScoringUsedCardBombFlag))
+ result += kUsedCardBombScore;
+ if (_scoringFlags.getFlag(kScoringShieldedCardBombFlag))
+ result += kShieldedCardBombScore;
+ if (_scoringFlags.getFlag(kScoringStunnedSinclairFlag))
+ result += kStunnedSinclairScore;
+ if (_scoringFlags.getFlag(kScoringDisarmedNukeFlag))
+ result += kDisarmedNukeScore;
+
+ return result;
+}
+
+GameScoreType GameStateManager::getPrehistoricScore() {
+ GameScoreType result = 0;
+
+ if (_scoringFlags.getFlag(kScoringThrewBreakerFlag))
+ result += kThrewBreakerScore;
+ if (_scoringFlags.getFlag(kScoringExtendedBridgeFlag))
+ result += kExtendedBridgeScore;
+ if (_scoringFlags.getFlag(kScoringGotHistoricalLogFlag))
+ result += kGotHistoricalLogScore;
+ if (_scoringFlags.getFlag(kScoringFinishedPrehistoricFlag))
+ result += kFinishedPrehistoricScore;
+
+ return result;
+}
+
+GameScoreType GameStateManager::getMarsScore() {
+ GameScoreType result = 0;
+
+ if (_scoringFlags.getFlag(kScoringThrownByRobotFlag))
+ result += kThrownByRobotScore;
+ if (_scoringFlags.getFlag(kScoringGotMarsCardFlag))
+ result += kGotMarsCardScore;
+ if (_scoringFlags.getFlag(kScoringSawMarsKioskFlag))
+ result += kSawMarsKioskScore;
+ if (_scoringFlags.getFlag(kScoringSawTransportMapFlag))
+ result += kSawTransportMapScore;
+ if (_scoringFlags.getFlag(kScoringGotCrowBarFlag))
+ result += kGotCrowBarScore;
+ if (_scoringFlags.getFlag(kScoringTurnedOnTransportFlag))
+ result += kTurnedOnTransportScore;
+ if (_scoringFlags.getFlag(kScoringGotOxygenMaskFlag))
+ result += kGotOxygenMaskScore;
+ if (_scoringFlags.getFlag(kScoringAvoidedRobotFlag))
+ result += kAvoidedRobotScore;
+ if (_scoringFlags.getFlag(kScoringActivatedPlatformFlag))
+ result += kActivatedPlatformScore;
+ if (_scoringFlags.getFlag(kScoringUsedLiquidNitrogenFlag))
+ result += kUsedLiquidNitrogenScore;
+ if (_scoringFlags.getFlag(kScoringUsedCrowBarFlag))
+ result += kUsedCrowBarScore;
+ if (_scoringFlags.getFlag(kScoringFoundCardBombFlag))
+ result += kFoundCardBombScore;
+ if (_scoringFlags.getFlag(kScoringDisarmedCardBombFlag))
+ result += kDisarmedCardBombScore;
+ if (_scoringFlags.getFlag(kScoringGotCardBombFlag))
+ result += kGotCardBombScore;
+ if (_scoringFlags.getFlag(kScoringThreadedMazeFlag))
+ result += kThreadedMazeScore;
+ if (_scoringFlags.getFlag(kScoringThreadedGearRoomFlag))
+ result += kThreadedGearRoomScore;
+ if (_scoringFlags.getFlag(kScoringEnteredShuttleFlag))
+ result += kEnteredShuttleScore;
+ if (_scoringFlags.getFlag(kScoringEnteredLaunchTubeFlag))
+ result += kEnteredLaunchTubeScore;
+ if (_scoringFlags.getFlag(kScoringStoppedRobotsShuttleFlag))
+ result += kStoppedRobotsShuttleScore;
+ if (_scoringFlags.getFlag(kScoringGotMarsOpMemChipFlag))
+ result += kGotMarsOpMemChipScore;
+ if (_scoringFlags.getFlag(kScoringFinishedMarsFlag))
+ result += kFinishedMarsScore;
+
+ return result;
+}
+
+GameScoreType GameStateManager::getNoradScore() {
+ GameScoreType result = 0;
+
+ if (_scoringFlags.getFlag(kScoringSawSecurityMonitorFlag))
+ result += kSawSecurityMonitorScore;
+ if (_scoringFlags.getFlag(kScoringFilledOxygenCanisterFlag))
+ result += kFilledOxygenCanisterScore;
+ if (_scoringFlags.getFlag(kScoringFilledArgonCanisterFlag))
+ result += kFilledArgonCanisterScore;
+ if (_scoringFlags.getFlag(kScoringSawUnconsciousOperatorFlag))
+ result += kSawUnconsciousOperatorScore;
+ if (_scoringFlags.getFlag(kScoringWentThroughPressureDoorFlag))
+ result += kWentThroughPressureDoorScore;
+ if (_scoringFlags.getFlag(kScoringPreppedSubFlag))
+ result += kPreppedSubScore;
+ if (_scoringFlags.getFlag(kScoringEnteredSubFlag))
+ result += kEnteredSubScore;
+ if (_scoringFlags.getFlag(kScoringExitedSubFlag))
+ result += kExitedSubScore;
+ if (_scoringFlags.getFlag(kScoringSawRobotAt54NorthFlag))
+ result += kSawRobotAt54NorthScore;
+ if (_scoringFlags.getFlag(kScoringPlayedWithClawFlag))
+ result += kPlayedWithClawScore;
+ if (_scoringFlags.getFlag(kScoringUsedRetinalChipFlag))
+ result += kUsedRetinalChipScore;
+ if (_scoringFlags.getFlag(kScoringFinishedGlobeGameFlag))
+ result += kFinishedGlobeGameScore;
+ if (_scoringFlags.getFlag(kScoringStoppedNoradRobotFlag))
+ result += kStoppedNoradRobotScore;
+ if (_scoringFlags.getFlag(kScoringGotNoradOpMemChipFlag))
+ result += kGotNoradOpMemChipScore;
+ if (_scoringFlags.getFlag(kScoringFinishedNoradFlag))
+ result += kFinishedNoradScore;
+
+ return result;
+}
+
+GameScoreType GameStateManager::getWSCScore() {
+ GameScoreType result = 0;
+
+ if (_scoringFlags.getFlag(kScoringRemovedDartFlag))
+ result += kRemovedDartScore;
+ if (_scoringFlags.getFlag(kScoringAnalyzedDartFlag))
+ result += kAnalyzedDartScore;
+ if (_scoringFlags.getFlag(kScoringBuiltAntidoteFlag))
+ result += kBuiltAntidoteScore;
+ if (_scoringFlags.getFlag(kScoringGotSinclairKeyFlag))
+ result += kGotSinclairKeyScore;
+ if (_scoringFlags.getFlag(kScoringGotArgonCanisterFlag))
+ result += kGotArgonCanisterScore;
+ if (_scoringFlags.getFlag(kScoringGotNitrogenCanisterFlag))
+ result += kGotNitrogenCanisterScore;
+ if (_scoringFlags.getFlag(kScoringPlayedWithMessagesFlag))
+ result += kPlayedWithMessagesScore;
+ if (_scoringFlags.getFlag(kScoringSawMorphExperimentFlag))
+ result += kSawMorphExperimentScore;
+ if (_scoringFlags.getFlag(kScoringEnteredSinclairOfficeFlag))
+ result += kEnteredSinclairOfficeScore;
+ if (_scoringFlags.getFlag(kScoringSawBrochureFlag))
+ result += kSawBrochureScore;
+ if (_scoringFlags.getFlag(kScoringSawSinclairEntry1Flag))
+ result += kSawSinclairEntry1Score;
+ if (_scoringFlags.getFlag(kScoringSawSinclairEntry2Flag))
+ result += kSawSinclairEntry2Score;
+ if (_scoringFlags.getFlag(kScoringSawSinclairEntry3Flag))
+ result += kSawSinclairEntry3Score;
+ if (_scoringFlags.getFlag(kScoringSawWSCDirectoryFlag))
+ result += kSawWSCDirectoryScore;
+ if (_scoringFlags.getFlag(kScoringUsedCrowBarInWSCFlag))
+ result += kUsedCrowBarInWSCScore;
+ if (_scoringFlags.getFlag(kScoringFinishedPlasmaDodgeFlag))
+ result += kFinishedPlasmaDodgeScore;
+ if (_scoringFlags.getFlag(kScoringOpenedCatwalkFlag))
+ result += kOpenedCatwalkScore;
+ if (_scoringFlags.getFlag(kScoringStoppedWSCRobotFlag))
+ result += kStoppedWSCRobotScore;
+ if (_scoringFlags.getFlag(kScoringGotWSCOpMemChipFlag))
+ result += kGotWSCOpMemChipScore;
+ if (_scoringFlags.getFlag(kScoringFinishedWSCFlag))
+ result += kFinishedWSCScore;
+
+ return result;
+}
+
+GameScoreType GameStateManager::getGandhiScore() {
+ GameScoreType result = 0;
+
+ if (_scoringFlags.getFlag(kScoringMarsGandhiFlag))
+ result += kMarsGandhiScore;
+ if (_scoringFlags.getFlag(kScoringNoradGandhiFlag))
+ result += kNoradGandhiScore;
+ if (_scoringFlags.getFlag(kScoringWSCGandhiFlag))
+ result += kWSCGandhiScore;
+
+ return result;
+}
+
+GameScoreType GameStateManager::getTotalScore() {
+ return getCaldoriaTSAScore() +
+ getPrehistoricScore() +
+ getMarsScore() +
+ getNoradScore() +
+ getWSCScore() +
+ getGandhiScore();
+}
+
+/////////////////////////////////////////////
+//
+// Caldoria data
+
+void GameStateManager::writeCaldoriaState(Common::WriteStream *stream) {
+ _caldoriaFlags.writeToStream(stream);
+ stream->writeUint32BE(_caldoriaFuseTimeLimit);
+}
+
+void GameStateManager::readCaldoriaState(Common::ReadStream *stream) {
+ _caldoriaFlags.readFromStream(stream);
+ _caldoriaFuseTimeLimit = stream->readUint32BE();
+}
+
+void GameStateManager::resetCaldoriaState() {
+ _caldoriaFlags.clearAllFlags();
+ _caldoriaFuseTimeLimit = 0;
+}
+
+/////////////////////////////////////////////
+//
+// TSA data
+
+void GameStateManager::writeTSAState(Common::WriteStream *stream) {
+ _TSAFlags.writeToStream(stream);
+ stream->writeUint32BE(_TSARipTimerTime);
+ stream->writeUint32BE(_TSAFuseTimeLimit);
+ stream->writeByte(_TSAState);
+ stream->writeByte(_T0BMonitorMode);
+ stream->writeUint32BE(_T0BMonitorStart);
+}
+
+void GameStateManager::readTSAState(Common::ReadStream *stream) {
+ _TSAFlags.readFromStream(stream);
+ _TSARipTimerTime = stream->readUint32BE();
+ _TSAFuseTimeLimit = stream->readUint32BE();
+ _TSAState = stream->readByte();
+ _T0BMonitorMode = stream->readByte();
+ _T0BMonitorStart = stream->readUint32BE();
+}
+
+void GameStateManager::resetTSAState() {
+ _TSAFlags.clearAllFlags();
+ _TSAState = 0;
+ _T0BMonitorMode = 0;
+ _T0BMonitorStart = 0;
+ _TSARipTimerTime = 0;
+ _TSAFuseTimeLimit = kTSAUncreatedTimeLimit;
+}
+
+/////////////////////////////////////////////
+//
+// Prehistoric data
+
+void GameStateManager::writePrehistoricState(Common::WriteStream *stream) {
+ _prehistoricFlags.writeToStream(stream);
+}
+
+void GameStateManager::readPrehistoricState(Common::ReadStream *stream) {
+ _prehistoricFlags.readFromStream(stream);
+}
+
+void GameStateManager::resetPrehistoricState() {
+ _prehistoricFlags.clearAllFlags();
+}
+
+/////////////////////////////////////////////
+//
+// Norad data
+
+void GameStateManager::writeNoradState(Common::WriteStream *stream) {
+ _noradFlags.writeToStream(stream);
+ stream->writeUint16BE(_noradSubRoomPressure);
+ stream->writeByte(_noradSubPrepState);
+}
+
+void GameStateManager::readNoradState(Common::ReadStream *stream) {
+ _noradFlags.readFromStream(stream);
+ _noradSubRoomPressure = stream->readUint16BE();
+ _noradSubPrepState = (NoradSubPrepState)stream->readByte();
+}
+
+void GameStateManager::resetNoradState() {
+ _noradFlags.clearAllFlags();
+ _noradSubRoomPressure = 9;
+ _noradSubPrepState = kSubNotPrepped;
+}
+
+/////////////////////////////////////////////
+//
+// Mars data
+
+void GameStateManager::writeMarsState(Common::WriteStream *stream) {
+ _marsFlags.writeToStream(stream);
+}
+
+void GameStateManager::readMarsState(Common::ReadStream *stream) {
+ _marsFlags.readFromStream(stream);
+}
+
+void GameStateManager::resetMarsState() {
+ _marsFlags.clearAllFlags();
+}
+
+/////////////////////////////////////////////
+//
+// WSC data
+
+void GameStateManager::writeWSCState(Common::WriteStream *stream) {
+ _WSCFlags.writeToStream(stream);
+}
+
+void GameStateManager::readWSCState(Common::ReadStream *stream) {
+ _WSCFlags.readFromStream(stream);
+}
+
+void GameStateManager::resetWSCState() {
+ _WSCFlags.clearAllFlags();
+}
+
+void GameStateManager::setScoringSawINN(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawINNFlag, flag);
+}
+
+void GameStateManager::setScoringTookShower(const bool flag) {
+ _scoringFlags.setFlag(kScoringTookShowerFlag, flag);
+}
+
+void GameStateManager::setScoringFixedHair(const bool flag) {
+ _scoringFlags.setFlag(kScoringFixedHairFlag, flag);
+}
+
+void GameStateManager::setScoringGotKeyCard(const bool flag) {
+ _scoringFlags.setFlag(kScoringGotKeyCardFlag, flag);
+}
+
+void GameStateManager::setScoringReadPaper(const bool flag) {
+ _scoringFlags.setFlag(kScoringReadPaperFlag, flag);
+}
+
+void GameStateManager::setScoringLookThroughTelescope(const bool flag) {
+ _scoringFlags.setFlag(kScoringLookThroughTelescopeFlag, flag);
+}
+
+void GameStateManager::setScoringSawCaldoriaKiosk(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawCaldoriaKioskFlag, flag);
+}
+
+void GameStateManager::setScoringGoToTSA(const bool flag) {
+ _scoringFlags.setFlag(kScoringGoToTSAFlag, flag);
+}
+
+void GameStateManager::setScoringEnterTSA(const bool flag) {
+ _scoringFlags.setFlag(kScoringEnterTSAFlag, flag);
+}
+
+void GameStateManager::setScoringSawBust1(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawBust1Flag, flag);
+}
+
+void GameStateManager::setScoringSawBust2(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawBust2Flag, flag);
+}
+
+void GameStateManager::setScoringSawBust3(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawBust3Flag, flag);
+}
+
+void GameStateManager::setScoringSawBust4(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawBust4Flag, flag);
+}
+
+void GameStateManager::setScoringSawBust5(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawBust5Flag, flag);
+}
+
+void GameStateManager::setScoringSawBust6(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawBust6Flag, flag);
+}
+
+void GameStateManager::setScoringSawTheory(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawTheoryFlag, flag);
+}
+
+void GameStateManager::setScoringSawBackground(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawBackgroundFlag, flag);
+}
+
+void GameStateManager::setScoringSawProcedure(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawProcedureFlag, flag);
+}
+
+void GameStateManager::setScoringGotJourneymanKey(const bool flag) {
+ _scoringFlags.setFlag(kScoringGotJourneymanKeyFlag, flag);
+}
+
+void GameStateManager::setScoringGotPegasusBiochip(const bool flag) {
+ _scoringFlags.setFlag(kScoringGotPegasusBiochipFlag, flag);
+}
+
+void GameStateManager::setScoringGotBiosuit(const bool flag) {
+ _scoringFlags.setFlag(kScoringGotBiosuitFlag, flag);
+}
+
+void GameStateManager::setScoringGoToPrehistoric(const bool flag) {
+ _scoringFlags.setFlag(kScoringGoToPrehistoricFlag, flag);
+}
+
+void GameStateManager::setScoringPutLogInReader(const bool flag) {
+ _scoringFlags.setFlag(kScoringPutLogInReaderFlag, flag);
+}
+
+void GameStateManager::setScoringSawCaldoriaNormal(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawCaldoriaNormalFlag, flag);
+}
+
+void GameStateManager::setScoringSawCaldoriaAltered(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawCaldoriaAlteredFlag, flag);
+}
+
+void GameStateManager::setScoringSawNoradNormal(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawNoradNormalFlag, flag);
+}
+
+void GameStateManager::setScoringSawNoradAltered(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawNoradAlteredFlag, flag);
+}
+
+void GameStateManager::setScoringSawMarsNormal(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawMarsNormalFlag, flag);
+}
+
+void GameStateManager::setScoringSawMarsAltered(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawMarsAlteredFlag, flag);
+}
+
+void GameStateManager::setScoringSawWSCNormal(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawWSCNormalFlag, flag);
+}
+
+void GameStateManager::setScoringSawWSCAltered(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawWSCAlteredFlag, flag);
+}
+
+void GameStateManager::setScoringWentToReadyRoom2(const bool flag) {
+ _scoringFlags.setFlag(kScoringWentToReadyRoom2Flag, flag);
+}
+
+void GameStateManager::setScoringWentAfterSinclair(const bool flag) {
+ _scoringFlags.setFlag(kScoringWentAfterSinclairFlag, flag);
+}
+
+void GameStateManager::setScoringUsedCardBomb(const bool flag) {
+ _scoringFlags.setFlag(kScoringUsedCardBombFlag, flag);
+}
+
+void GameStateManager::setScoringShieldedCardBomb(const bool flag) {
+ _scoringFlags.setFlag(kScoringShieldedCardBombFlag, flag);
+}
+
+void GameStateManager::setScoringStunnedSinclair(const bool flag) {
+ _scoringFlags.setFlag(kScoringStunnedSinclairFlag, flag);
+}
+
+void GameStateManager::setScoringDisarmedNuke(const bool flag) {
+ _scoringFlags.setFlag(kScoringDisarmedNukeFlag, flag);
+}
+
+void GameStateManager::setScoringThrewBreaker(const bool flag) {
+ _scoringFlags.setFlag(kScoringThrewBreakerFlag, flag);
+}
+
+void GameStateManager::setScoringExtendedBridge(const bool flag) {
+ _scoringFlags.setFlag(kScoringExtendedBridgeFlag, flag);
+}
+
+void GameStateManager::setScoringGotHistoricalLog(const bool flag) {
+ _scoringFlags.setFlag(kScoringGotHistoricalLogFlag, flag);
+}
+
+void GameStateManager::setScoringFinishedPrehistoric(const bool flag) {
+ _scoringFlags.setFlag(kScoringFinishedPrehistoricFlag, flag);
+}
+
+void GameStateManager::setScoringThrownByRobot(const bool flag) {
+ _scoringFlags.setFlag(kScoringThrownByRobotFlag, flag);
+}
+
+void GameStateManager::setScoringGotMarsCard(const bool flag) {
+ _scoringFlags.setFlag(kScoringGotMarsCardFlag, flag);
+}
+
+void GameStateManager::setScoringSawMarsKiosk(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawMarsKioskFlag, flag);
+}
+
+void GameStateManager::setScoringSawTransportMap(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawTransportMapFlag, flag);
+}
+
+void GameStateManager::setScoringGotCrowBar(const bool flag) {
+ _scoringFlags.setFlag(kScoringGotCrowBarFlag, flag);
+}
+
+void GameStateManager::setScoringTurnedOnTransport(const bool flag) {
+ _scoringFlags.setFlag(kScoringTurnedOnTransportFlag, flag);
+}
+
+void GameStateManager::setScoringGotOxygenMask(const bool flag) {
+ _scoringFlags.setFlag(kScoringGotOxygenMaskFlag, flag);
+}
+
+void GameStateManager::setScoringAvoidedRobot(const bool flag) {
+ _scoringFlags.setFlag(kScoringAvoidedRobotFlag, flag);
+}
+
+void GameStateManager::setScoringActivatedPlatform(const bool flag) {
+ _scoringFlags.setFlag(kScoringActivatedPlatformFlag, flag);
+}
+
+void GameStateManager::setScoringUsedLiquidNitrogen(const bool flag) {
+ _scoringFlags.setFlag(kScoringUsedLiquidNitrogenFlag, flag);
+}
+
+void GameStateManager::setScoringUsedCrowBar(const bool flag) {
+ _scoringFlags.setFlag(kScoringUsedCrowBarFlag, flag);
+}
+
+void GameStateManager::setScoringFoundCardBomb(const bool flag) {
+ _scoringFlags.setFlag(kScoringFoundCardBombFlag, flag);
+}
+
+void GameStateManager::setScoringDisarmedCardBomb(const bool flag) {
+ _scoringFlags.setFlag(kScoringDisarmedCardBombFlag, flag);
+}
+
+void GameStateManager::setScoringGotCardBomb(const bool flag) {
+ _scoringFlags.setFlag(kScoringGotCardBombFlag, flag);
+}
+
+void GameStateManager::setScoringThreadedMaze(const bool flag) {
+ _scoringFlags.setFlag(kScoringThreadedMazeFlag, flag);
+}
+
+void GameStateManager::setScoringThreadedGearRoom(const bool flag) {
+ _scoringFlags.setFlag(kScoringThreadedGearRoomFlag, flag);
+}
+
+void GameStateManager::setScoringEnteredShuttle(const bool flag) {
+ _scoringFlags.setFlag(kScoringEnteredShuttleFlag, flag);
+}
+
+void GameStateManager::setScoringEnteredLaunchTube(const bool flag) {
+ _scoringFlags.setFlag(kScoringEnteredLaunchTubeFlag, flag);
+}
+
+void GameStateManager::setScoringStoppedRobotsShuttle(const bool flag) {
+ _scoringFlags.setFlag(kScoringStoppedRobotsShuttleFlag, flag);
+}
+
+void GameStateManager::setScoringGotMarsOpMemChip(const bool flag) {
+ _scoringFlags.setFlag(kScoringGotMarsOpMemChipFlag, flag);
+}
+
+void GameStateManager::setScoringFinishedMars(const bool flag) {
+ _scoringFlags.setFlag(kScoringFinishedMarsFlag, flag);
+}
+
+void GameStateManager::setScoringSawSecurityMonitor(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawSecurityMonitorFlag, flag);
+}
+
+void GameStateManager::setScoringFilledOxygenCanister(const bool flag) {
+ _scoringFlags.setFlag(kScoringFilledOxygenCanisterFlag, flag);
+}
+
+void GameStateManager::setScoringFilledArgonCanister(const bool flag) {
+ _scoringFlags.setFlag(kScoringFilledArgonCanisterFlag, flag);
+}
+
+void GameStateManager::setScoringSawUnconsciousOperator(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawUnconsciousOperatorFlag, flag);
+}
+
+void GameStateManager::setScoringWentThroughPressureDoor(const bool flag) {
+ _scoringFlags.setFlag(kScoringWentThroughPressureDoorFlag, flag);
+}
+
+void GameStateManager::setScoringPreppedSub(const bool flag) {
+ _scoringFlags.setFlag(kScoringPreppedSubFlag, flag);
+}
+
+void GameStateManager::setScoringEnteredSub(const bool flag) {
+ _scoringFlags.setFlag(kScoringEnteredSubFlag, flag);
+}
+
+void GameStateManager::setScoringExitedSub(const bool flag) {
+ _scoringFlags.setFlag(kScoringExitedSubFlag, flag);
+}
+
+void GameStateManager::setScoringSawRobotAt54North(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawRobotAt54NorthFlag, flag);
+}
+
+void GameStateManager::setScoringPlayedWithClaw(const bool flag) {
+ _scoringFlags.setFlag(kScoringPlayedWithClawFlag, flag);
+}
+
+void GameStateManager::setScoringUsedRetinalChip(const bool flag) {
+ _scoringFlags.setFlag(kScoringUsedRetinalChipFlag, flag);
+}
+
+void GameStateManager::setScoringFinishedGlobeGame(const bool flag) {
+ _scoringFlags.setFlag(kScoringFinishedGlobeGameFlag, flag);
+}
+
+void GameStateManager::setScoringStoppedNoradRobot(const bool flag) {
+ _scoringFlags.setFlag(kScoringStoppedNoradRobotFlag, flag);
+}
+
+void GameStateManager::setScoringGotNoradOpMemChip(const bool flag) {
+ _scoringFlags.setFlag(kScoringGotNoradOpMemChipFlag, flag);
+}
+
+void GameStateManager::setScoringFinishedNorad(const bool flag) {
+ _scoringFlags.setFlag(kScoringFinishedNoradFlag, flag);
+}
+
+void GameStateManager::setScoringRemovedDart(const bool flag) {
+ _scoringFlags.setFlag(kScoringRemovedDartFlag, flag);
+}
+
+void GameStateManager::setScoringAnalyzedDart(const bool flag) {
+ _scoringFlags.setFlag(kScoringAnalyzedDartFlag, flag);
+}
+
+void GameStateManager::setScoringBuiltAntidote(const bool flag) {
+ _scoringFlags.setFlag(kScoringBuiltAntidoteFlag, flag);
+}
+
+void GameStateManager::setScoringGotSinclairKey(const bool flag) {
+ _scoringFlags.setFlag(kScoringGotSinclairKeyFlag, flag);
+}
+
+void GameStateManager::setScoringGotArgonCanister(const bool flag) {
+ _scoringFlags.setFlag(kScoringGotArgonCanisterFlag, flag);
+}
+
+void GameStateManager::setScoringGotNitrogenCanister(const bool flag) {
+ _scoringFlags.setFlag(kScoringGotNitrogenCanisterFlag, flag);
+}
+
+void GameStateManager::setScoringPlayedWithMessages(const bool flag) {
+ _scoringFlags.setFlag(kScoringPlayedWithMessagesFlag, flag);
+}
+
+void GameStateManager::setScoringSawMorphExperiment(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawMorphExperimentFlag, flag);
+}
+
+void GameStateManager::setScoringEnteredSinclairOffice(const bool flag) {
+ _scoringFlags.setFlag(kScoringEnteredSinclairOfficeFlag, flag);
+}
+
+void GameStateManager::setScoringSawBrochure(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawBrochureFlag, flag);
+}
+
+void GameStateManager::setScoringSawSinclairEntry1(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawSinclairEntry1Flag, flag);
+}
+
+void GameStateManager::setScoringSawSinclairEntry2(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawSinclairEntry2Flag, flag);
+}
+
+void GameStateManager::setScoringSawSinclairEntry3(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawSinclairEntry3Flag, flag);
+}
+
+void GameStateManager::setScoringSawWSCDirectory(const bool flag) {
+ _scoringFlags.setFlag(kScoringSawWSCDirectoryFlag, flag);
+}
+
+void GameStateManager::setScoringUsedCrowBarInWSC(const bool flag) {
+ _scoringFlags.setFlag(kScoringUsedCrowBarInWSCFlag, flag);
+}
+
+void GameStateManager::setScoringFinishedPlasmaDodge(const bool flag) {
+ _scoringFlags.setFlag(kScoringFinishedPlasmaDodgeFlag, flag);
+}
+
+void GameStateManager::setScoringOpenedCatwalk(const bool flag) {
+ _scoringFlags.setFlag(kScoringOpenedCatwalkFlag, flag);
+}
+
+void GameStateManager::setScoringStoppedWSCRobot(const bool flag) {
+ _scoringFlags.setFlag(kScoringStoppedWSCRobotFlag, flag);
+}
+
+void GameStateManager::setScoringGotWSCOpMemChip(const bool flag) {
+ _scoringFlags.setFlag(kScoringGotWSCOpMemChipFlag, flag);
+}
+
+void GameStateManager::setScoringFinishedWSC(const bool flag) {
+ _scoringFlags.setFlag(kScoringFinishedWSCFlag, flag);
+}
+
+void GameStateManager::setScoringMarsGandhi(const bool flag) {
+ _scoringFlags.setFlag(kScoringMarsGandhiFlag, flag);
+}
+
+void GameStateManager::setScoringNoradGandhi(const bool flag) {
+ _scoringFlags.setFlag(kScoringNoradGandhiFlag, flag);
+}
+
+void GameStateManager::setScoringWSCGandhi(const bool flag) {
+ _scoringFlags.setFlag(kScoringWSCGandhiFlag, flag);
+}
+
+bool GameStateManager::getScoringSawINN() {
+ return _scoringFlags.getFlag(kScoringSawINNFlag);
+}
+
+bool GameStateManager::getScoringTookShower() {
+ return _scoringFlags.getFlag(kScoringTookShowerFlag);
+}
+
+bool GameStateManager::getScoringFixedHair() {
+ return _scoringFlags.getFlag(kScoringFixedHairFlag);
+}
+
+bool GameStateManager::getScoringGotKeyCard() {
+ return _scoringFlags.getFlag(kScoringGotKeyCardFlag);
+}
+
+bool GameStateManager::getScoringReadPaper() {
+ return _scoringFlags.getFlag(kScoringReadPaperFlag);
+}
+
+bool GameStateManager::getScoringLookThroughTelescope() {
+ return _scoringFlags.getFlag(kScoringLookThroughTelescopeFlag);
+}
+
+bool GameStateManager::getScoringSawCaldoriaKiosk() {
+ return _scoringFlags.getFlag(kScoringSawCaldoriaKioskFlag);
+}
+
+bool GameStateManager::getScoringGoToTSA() {
+ return _scoringFlags.getFlag(kScoringGoToTSAFlag);
+}
+
+bool GameStateManager::getScoringEnterTSA() {
+ return _scoringFlags.getFlag(kScoringEnterTSAFlag);
+}
+
+bool GameStateManager::getScoringSawBust1() {
+ return _scoringFlags.getFlag(kScoringSawBust1Flag);
+}
+
+bool GameStateManager::getScoringSawBust2() {
+ return _scoringFlags.getFlag(kScoringSawBust2Flag);
+}
+
+bool GameStateManager::getScoringSawBust3() {
+ return _scoringFlags.getFlag(kScoringSawBust3Flag);
+}
+
+bool GameStateManager::getScoringSawBust4() {
+ return _scoringFlags.getFlag(kScoringSawBust4Flag);
+}
+
+bool GameStateManager::getScoringSawBust5() {
+ return _scoringFlags.getFlag(kScoringSawBust5Flag);
+}
+
+bool GameStateManager::getScoringSawBust6() {
+ return _scoringFlags.getFlag(kScoringSawBust6Flag);
+}
+
+bool GameStateManager::getScoringSawTheory() {
+ return _scoringFlags.getFlag(kScoringSawTheoryFlag);
+}
+
+bool GameStateManager::getScoringSawBackground() {
+ return _scoringFlags.getFlag(kScoringSawBackgroundFlag);
+}
+
+bool GameStateManager::getScoringSawProcedure() {
+ return _scoringFlags.getFlag(kScoringSawProcedureFlag);
+}
+
+bool GameStateManager::getScoringGotJourneymanKey() {
+ return _scoringFlags.getFlag(kScoringGotJourneymanKeyFlag);
+}
+
+bool GameStateManager::getScoringGotPegasusBiochip() {
+ return _scoringFlags.getFlag(kScoringGotPegasusBiochipFlag);
+}
+
+bool GameStateManager::getScoringGotBiosuit() {
+ return _scoringFlags.getFlag(kScoringGotBiosuitFlag);
+}
+
+bool GameStateManager::getScoringGoToPrehistoric() {
+ return _scoringFlags.getFlag(kScoringGoToPrehistoricFlag);
+}
+
+bool GameStateManager::getScoringPutLogInReader() {
+ return _scoringFlags.getFlag(kScoringPutLogInReaderFlag);
+}
+
+bool GameStateManager::getScoringSawCaldoriaNormal() {
+ return _scoringFlags.getFlag(kScoringSawCaldoriaNormalFlag);
+}
+
+bool GameStateManager::getScoringSawCaldoriaAltered() {
+ return _scoringFlags.getFlag(kScoringSawCaldoriaAlteredFlag);
+}
+
+bool GameStateManager::getScoringSawNoradNormal() {
+ return _scoringFlags.getFlag(kScoringSawNoradNormalFlag);
+}
+
+bool GameStateManager::getScoringSawNoradAltered() {
+ return _scoringFlags.getFlag(kScoringSawNoradAlteredFlag);
+}
+
+bool GameStateManager::getScoringSawMarsNormal() {
+ return _scoringFlags.getFlag(kScoringSawMarsNormalFlag);
+}
+
+bool GameStateManager::getScoringSawMarsAltered() {
+ return _scoringFlags.getFlag(kScoringSawMarsAlteredFlag);
+}
+
+bool GameStateManager::getScoringSawWSCNormal() {
+ return _scoringFlags.getFlag(kScoringSawWSCNormalFlag);
+}
+
+bool GameStateManager::getScoringSawWSCAltered() {
+ return _scoringFlags.getFlag(kScoringSawWSCAlteredFlag);
+}
+
+bool GameStateManager::getScoringWentToReadyRoom2() {
+ return _scoringFlags.getFlag(kScoringWentToReadyRoom2Flag);
+}
+
+bool GameStateManager::getScoringWentAfterSinclair() {
+ return _scoringFlags.getFlag(kScoringWentAfterSinclairFlag);
+}
+
+bool GameStateManager::getScoringUsedCardBomb() {
+ return _scoringFlags.getFlag(kScoringUsedCardBombFlag);
+}
+
+bool GameStateManager::getScoringShieldedCardBomb() {
+ return _scoringFlags.getFlag(kScoringShieldedCardBombFlag);
+}
+
+bool GameStateManager::getScoringStunnedSinclair() {
+ return _scoringFlags.getFlag(kScoringStunnedSinclairFlag);
+}
+
+bool GameStateManager::getScoringDisarmedNuke() {
+ return _scoringFlags.getFlag(kScoringDisarmedNukeFlag);
+}
+
+bool GameStateManager::getScoringThrewBreaker() {
+ return _scoringFlags.getFlag(kScoringThrewBreakerFlag);
+}
+
+bool GameStateManager::getScoringExtendedBridge() {
+ return _scoringFlags.getFlag(kScoringExtendedBridgeFlag);
+}
+
+bool GameStateManager::getScoringGotHistoricalLog() {
+ return _scoringFlags.getFlag(kScoringGotHistoricalLogFlag);
+}
+
+bool GameStateManager::getScoringFinishedPrehistoric() {
+ return _scoringFlags.getFlag(kScoringFinishedPrehistoricFlag);
+}
+
+bool GameStateManager::getScoringThrownByRobot() {
+ return _scoringFlags.getFlag(kScoringThrownByRobotFlag);
+}
+
+bool GameStateManager::getScoringGotMarsCard() {
+ return _scoringFlags.getFlag(kScoringGotMarsCardFlag);
+}
+
+bool GameStateManager::getScoringSawMarsKiosk() {
+ return _scoringFlags.getFlag(kScoringSawMarsKioskFlag);
+}
+
+bool GameStateManager::getScoringSawTransportMap() {
+ return _scoringFlags.getFlag(kScoringSawTransportMapFlag);
+}
+
+bool GameStateManager::getScoringGotCrowBar() {
+ return _scoringFlags.getFlag(kScoringGotCrowBarFlag);
+}
+
+bool GameStateManager::getScoringTurnedOnTransport() {
+ return _scoringFlags.getFlag(kScoringTurnedOnTransportFlag);
+}
+
+bool GameStateManager::getScoringGotOxygenMask() {
+ return _scoringFlags.getFlag(kScoringGotOxygenMaskFlag);
+}
+
+bool GameStateManager::getScoringAvoidedRobot() {
+ return _scoringFlags.getFlag(kScoringAvoidedRobotFlag);
+}
+
+bool GameStateManager::getScoringActivatedPlatform() {
+ return _scoringFlags.getFlag(kScoringActivatedPlatformFlag);
+}
+
+bool GameStateManager::getScoringUsedLiquidNitrogen() {
+ return _scoringFlags.getFlag(kScoringUsedLiquidNitrogenFlag);
+}
+
+bool GameStateManager::getScoringUsedCrowBar() {
+ return _scoringFlags.getFlag(kScoringUsedCrowBarFlag);
+}
+
+bool GameStateManager::getScoringFoundCardBomb() {
+ return _scoringFlags.getFlag(kScoringFoundCardBombFlag);
+}
+
+bool GameStateManager::getScoringDisarmedCardBomb() {
+ return _scoringFlags.getFlag(kScoringDisarmedCardBombFlag);
+}
+
+bool GameStateManager::getScoringGotCardBomb() {
+ return _scoringFlags.getFlag(kScoringGotCardBombFlag);
+}
+
+bool GameStateManager::getScoringThreadedMaze() {
+ return _scoringFlags.getFlag(kScoringThreadedMazeFlag);
+}
+
+bool GameStateManager::getScoringThreadedGearRoom() {
+ return _scoringFlags.getFlag(kScoringThreadedGearRoomFlag);
+}
+
+bool GameStateManager::getScoringEnteredShuttle() {
+ return _scoringFlags.getFlag(kScoringEnteredShuttleFlag);
+}
+
+bool GameStateManager::getScoringEnteredLaunchTube() {
+ return _scoringFlags.getFlag(kScoringEnteredLaunchTubeFlag);
+}
+
+bool GameStateManager::getScoringStoppedRobotsShuttle() {
+ return _scoringFlags.getFlag(kScoringStoppedRobotsShuttleFlag);
+}
+
+bool GameStateManager::getScoringGotMarsOpMemChip() {
+ return _scoringFlags.getFlag(kScoringGotMarsOpMemChipFlag);
+}
+
+bool GameStateManager::getScoringFinishedMars() {
+ return _scoringFlags.getFlag(kScoringFinishedMarsFlag);
+}
+
+bool GameStateManager::getScoringSawSecurityMonitor() {
+ return _scoringFlags.getFlag(kScoringSawSecurityMonitorFlag);
+}
+
+bool GameStateManager::getScoringFilledOxygenCanister() {
+ return _scoringFlags.getFlag(kScoringFilledOxygenCanisterFlag);
+}
+
+bool GameStateManager::getScoringFilledArgonCanister() {
+ return _scoringFlags.getFlag(kScoringFilledArgonCanisterFlag);
+}
+
+bool GameStateManager::getScoringSawUnconsciousOperator() {
+ return _scoringFlags.getFlag(kScoringSawUnconsciousOperatorFlag);
+}
+
+bool GameStateManager::getScoringWentThroughPressureDoor() {
+ return _scoringFlags.getFlag(kScoringWentThroughPressureDoorFlag);
+}
+
+bool GameStateManager::getScoringPreppedSub() {
+ return _scoringFlags.getFlag(kScoringPreppedSubFlag);
+}
+
+bool GameStateManager::getScoringEnteredSub() {
+ return _scoringFlags.getFlag(kScoringEnteredSubFlag);
+}
+
+bool GameStateManager::getScoringExitedSub() {
+ return _scoringFlags.getFlag(kScoringExitedSubFlag);
+}
+
+bool GameStateManager::getScoringSawRobotAt54North() {
+ return _scoringFlags.getFlag(kScoringSawRobotAt54NorthFlag);
+}
+
+bool GameStateManager::getScoringPlayedWithClaw() {
+ return _scoringFlags.getFlag(kScoringPlayedWithClawFlag);
+}
+
+bool GameStateManager::getScoringUsedRetinalChip() {
+ return _scoringFlags.getFlag(kScoringUsedRetinalChipFlag);
+}
+
+bool GameStateManager::getScoringFinishedGlobeGame() {
+ return _scoringFlags.getFlag(kScoringFinishedGlobeGameFlag);
+}
+
+bool GameStateManager::getScoringStoppedNoradRobot() {
+ return _scoringFlags.getFlag(kScoringStoppedNoradRobotFlag);
+}
+
+bool GameStateManager::getScoringGotNoradOpMemChip() {
+ return _scoringFlags.getFlag(kScoringGotNoradOpMemChipFlag);
+}
+
+bool GameStateManager::getScoringFinishedNorad() {
+ return _scoringFlags.getFlag(kScoringFinishedNoradFlag);
+}
+
+bool GameStateManager::getScoringRemovedDart() {
+ return _scoringFlags.getFlag(kScoringRemovedDartFlag);
+}
+
+bool GameStateManager::getScoringAnalyzedDart() {
+ return _scoringFlags.getFlag(kScoringAnalyzedDartFlag);
+}
+
+bool GameStateManager::getScoringBuiltAntidote() {
+ return _scoringFlags.getFlag(kScoringBuiltAntidoteFlag);
+}
+
+bool GameStateManager::getScoringGotSinclairKey() {
+ return _scoringFlags.getFlag(kScoringGotSinclairKeyFlag);
+}
+
+bool GameStateManager::getScoringGotArgonCanister() {
+ return _scoringFlags.getFlag(kScoringGotArgonCanisterFlag);
+}
+
+bool GameStateManager::getScoringGotNitrogenCanister() {
+ return _scoringFlags.getFlag(kScoringGotNitrogenCanisterFlag);
+}
+
+bool GameStateManager::getScoringPlayedWithMessages() {
+ return _scoringFlags.getFlag(kScoringPlayedWithMessagesFlag);
+}
+
+bool GameStateManager::getScoringSawMorphExperiment() {
+ return _scoringFlags.getFlag(kScoringSawMorphExperimentFlag);
+}
+
+bool GameStateManager::getScoringEnteredSinclairOffice() {
+ return _scoringFlags.getFlag(kScoringEnteredSinclairOfficeFlag);
+}
+
+bool GameStateManager::getScoringSawBrochure() {
+ return _scoringFlags.getFlag(kScoringSawBrochureFlag);
+}
+
+bool GameStateManager::getScoringSawSinclairEntry1() {
+ return _scoringFlags.getFlag(kScoringSawSinclairEntry1Flag);
+}
+
+bool GameStateManager::getScoringSawSinclairEntry2() {
+ return _scoringFlags.getFlag(kScoringSawSinclairEntry2Flag);
+}
+
+bool GameStateManager::getScoringSawSinclairEntry3() {
+ return _scoringFlags.getFlag(kScoringSawSinclairEntry3Flag);
+}
+
+bool GameStateManager::getScoringSawWSCDirectory() {
+ return _scoringFlags.getFlag(kScoringSawWSCDirectoryFlag);
+}
+
+bool GameStateManager::getScoringUsedCrowBarInWSC() {
+ return _scoringFlags.getFlag(kScoringUsedCrowBarInWSCFlag);
+}
+
+bool GameStateManager::getScoringFinishedPlasmaDodge() {
+ return _scoringFlags.getFlag(kScoringFinishedPlasmaDodgeFlag);
+}
+
+bool GameStateManager::getScoringOpenedCatwalk() {
+ return _scoringFlags.getFlag(kScoringOpenedCatwalkFlag);
+}
+
+bool GameStateManager::getScoringStoppedWSCRobot() {
+ return _scoringFlags.getFlag(kScoringStoppedWSCRobotFlag);
+}
+
+bool GameStateManager::getScoringGotWSCOpMemChip() {
+ return _scoringFlags.getFlag(kScoringGotWSCOpMemChipFlag);
+}
+
+bool GameStateManager::getScoringFinishedWSC() {
+ return _scoringFlags.getFlag(kScoringFinishedWSCFlag);
+}
+
+bool GameStateManager::getScoringMarsGandhi() {
+ return _scoringFlags.getFlag(kScoringMarsGandhiFlag);
+}
+
+bool GameStateManager::getScoringNoradGandhi() {
+ return _scoringFlags.getFlag(kScoringNoradGandhiFlag);
+}
+
+bool GameStateManager::getScoringWSCGandhi() {
+ return _scoringFlags.getFlag(kScoringWSCGandhiFlag);
+}
+
+void GameStateManager::setWalkthroughMode(bool value) {
+ _globalFlags.setFlag(kGlobalWalkthroughFlag, value);
+}
+
+bool GameStateManager::getWalkthroughMode() {
+ return _globalFlags.getFlag(kGlobalWalkthroughFlag);
+}
+
+void GameStateManager::setShieldOn(bool value) {
+ _globalFlags.setFlag(kGlobalShieldOnFlag, value);
+}
+
+bool GameStateManager::getShieldOn() {
+ return _globalFlags.getFlag(kGlobalShieldOnFlag);
+}
+
+void GameStateManager::setEasterEgg(bool value) {
+ _globalFlags.setFlag(kGlobalEasterEggFlag, value);
+}
+
+bool GameStateManager::getEasterEgg() {
+ return _globalFlags.getFlag(kGlobalEasterEggFlag);
+}
+
+void GameStateManager::setBeenToWSC(bool value) {
+ _globalFlags.setFlag(kGlobalBeenToWSCFlag, value);
+}
+
+bool GameStateManager::getBeenToWSC() {
+ return _globalFlags.getFlag(kGlobalBeenToWSCFlag);
+}
+
+void GameStateManager::setBeenToMars(bool value) {
+ _globalFlags.setFlag(kGlobalBeenToMarsFlag, value);
+}
+
+bool GameStateManager::getBeenToMars() {
+ return _globalFlags.getFlag(kGlobalBeenToMarsFlag);
+}
+
+void GameStateManager::setBeenToNorad(bool value) {
+ _globalFlags.setFlag(kGlobalBeenToNoradFlag, value);
+}
+
+bool GameStateManager::getBeenToNorad() {
+ return _globalFlags.getFlag(kGlobalBeenToNoradFlag);
+}
+
+void GameStateManager::setWSCFinished(bool value) {
+ _globalFlags.setFlag(kGlobalWSCFinishedFlag, value);
+}
+
+bool GameStateManager::getWSCFinished() {
+ return _globalFlags.getFlag(kGlobalWSCFinishedFlag);
+}
+
+void GameStateManager::setMarsFinished(bool value) {
+ _globalFlags.setFlag(kGlobalMarsFinishedFlag, value);
+}
+
+bool GameStateManager::getMarsFinished() {
+ return _globalFlags.getFlag(kGlobalMarsFinishedFlag);
+}
+
+void GameStateManager::setNoradFinished(bool value) {
+ _globalFlags.setFlag(kGlobalNoradFinishedFlag, value);
+}
+
+bool GameStateManager::getNoradFinished() {
+ return _globalFlags.getFlag(kGlobalNoradFinishedFlag);
+}
+
+bool GameStateManager::allTimeZonesFinished() {
+ return getWSCFinished() && getMarsFinished() && getNoradFinished();
+}
+
+void GameStateManager::setTakenItemID(ItemID id, bool value) {
+ _itemTakenFlags.setFlag(id, value);
+}
+
+bool GameStateManager::isTakenItemID(ItemID id) {
+ return _itemTakenFlags.getFlag(id);
+}
+
+void GameStateManager::setTakenItem(Item *item, bool value) {
+ setTakenItemID(item->getObjectID(), value);
+}
+
+bool GameStateManager::isTakenItem(Item *item) {
+ return isTakenItemID(item->getObjectID());
+}
+
+void GameStateManager::setCaldoriaFuseTimeLimit(const TimeValue timeLimit) {
+ _caldoriaFuseTimeLimit = timeLimit;
+}
+
+TimeValue GameStateManager::getCaldoriaFuseTimeLimit() {
+ return _caldoriaFuseTimeLimit;
+}
+
+void GameStateManager::setCaldoriaSeenPullback(bool value) {
+ _caldoriaFlags.setFlag(kCaldoriaSeenPullbackFlag, value);
+}
+
+bool GameStateManager::getCaldoriaSeenPullback() {
+ return _caldoriaFlags.getFlag(kCaldoriaSeenPullbackFlag);
+}
+
+void GameStateManager::setCaldoriaMadeOJ(bool value) {
+ _caldoriaFlags.setFlag(kCaldoriaMadeOJFlag, value);
+}
+
+bool GameStateManager::getCaldoriaMadeOJ() {
+ return _caldoriaFlags.getFlag(kCaldoriaMadeOJFlag);
+}
+
+void GameStateManager::setCaldoriaWokenUp(bool value) {
+ _caldoriaFlags.setFlag(kCaldoriaWokenUpFlag, value);
+}
+
+bool GameStateManager::getCaldoriaWokenUp() {
+ return _caldoriaFlags.getFlag(kCaldoriaWokenUpFlag);
+}
+
+void GameStateManager::setCaldoriaDidRecalibration(bool value) {
+ _caldoriaFlags.setFlag(kCaldoriaDidRecalibrationFlag, value);
+}
+
+bool GameStateManager::getCaldoriaDidRecalibration() {
+ return _caldoriaFlags.getFlag(kCaldoriaDidRecalibrationFlag);
+}
+
+void GameStateManager::setCaldoriaSeenSinclairInElevator(bool value) {
+ _caldoriaFlags.setFlag(kCaldoriaSeenSinclairInElevatorFlag, value);
+}
+
+bool GameStateManager::getCaldoriaSeenSinclairInElevator() {
+ return _caldoriaFlags.getFlag(kCaldoriaSeenSinclairInElevatorFlag);
+}
+
+void GameStateManager::setCaldoriaINNAnnouncing(bool value) {
+ _caldoriaFlags.setFlag(kCaldoriaINNAnnouncingFlag, value);
+}
+
+bool GameStateManager::getCaldoriaINNAnnouncing() {
+ return _caldoriaFlags.getFlag(kCaldoriaINNAnnouncingFlag);
+}
+
+void GameStateManager::setCaldoriaSeenINN(bool value) {
+ _caldoriaFlags.setFlag(kCaldoriaSeenINNFlag, value);
+}
+
+bool GameStateManager::getCaldoriaSeenINN() {
+ return _caldoriaFlags.getFlag(kCaldoriaSeenINNFlag);
+}
+
+void GameStateManager::setCaldoriaSeenMessages(bool value) {
+ _caldoriaFlags.setFlag(kCaldoriaSeenMessagesFlag, value);
+}
+
+bool GameStateManager::getCaldoriaSeenMessages() {
+ return _caldoriaFlags.getFlag(kCaldoriaSeenMessagesFlag);
+}
+
+void GameStateManager::setCaldoriaSinclairShot(bool value) {
+ _caldoriaFlags.setFlag(kCaldoriaSinclairShotFlag, value);
+}
+
+bool GameStateManager::getCaldoriaSinclairShot() {
+ return _caldoriaFlags.getFlag(kCaldoriaSinclairShotFlag);
+}
+
+void GameStateManager::setCaldoriaBombDisarmed(bool value) {
+ _caldoriaFlags.setFlag(kCaldoriaBombDisarmedFlag, value);
+}
+
+bool GameStateManager::getCaldoriaBombDisarmed() {
+ return _caldoriaFlags.getFlag(kCaldoriaBombDisarmedFlag);
+}
+
+void GameStateManager::setCaldoriaRoofDoorOpen(bool value) {
+ _caldoriaFlags.setFlag(kCaldoriaRoofDoorOpenFlag, value);
+}
+
+bool GameStateManager::getCaldoriaRoofDoorOpen() {
+ return _caldoriaFlags.getFlag(kCaldoriaRoofDoorOpenFlag);
+}
+
+void GameStateManager::setCaldoriaDoneHygiene(bool value) {
+ _caldoriaFlags.setFlag(kCaldoriaDoneHygieneFlag, value);
+}
+
+bool GameStateManager::getCaldoriaDoneHygiene() {
+ return _caldoriaFlags.getFlag(kCaldoriaDoneHygieneFlag);
+}
+
+void GameStateManager::setCaldoriaSawVoiceAnalysis(bool value) {
+ _caldoriaFlags.setFlag(kCaldoriaSawVoiceAnalysisFlag, value);
+}
+
+bool GameStateManager::getCaldoriaSawVoiceAnalysis() {
+ return _caldoriaFlags.getFlag(kCaldoriaSawVoiceAnalysisFlag);
+}
+
+void GameStateManager::setCaldoriaDoorBombed(bool value) {
+ _caldoriaFlags.setFlag(kCaldoriaDoorBombedFlag, value);
+}
+
+bool GameStateManager::getCaldoriaDoorBombed() {
+ return _caldoriaFlags.getFlag(kCaldoriaDoorBombedFlag);
+}
+
+void GameStateManager::setCaldoriaGunAimed(bool value) {
+ _caldoriaFlags.setFlag(kCaldoriaGunAimedFlag, value);
+}
+
+bool GameStateManager::getCaldoriaGunAimed() {
+ return _caldoriaFlags.getFlag(kCaldoriaGunAimedFlag);
+}
+
+void GameStateManager::setRipTimerTime(TimeValue limit) {
+ _TSARipTimerTime = limit;
+}
+
+TimeValue GameStateManager::getRipTimerTime() {
+ return _TSARipTimerTime;
+}
+
+void GameStateManager::setTSAFuseTimeLimit(TimeValue limit) {
+ _TSAFuseTimeLimit = limit;
+}
+
+TimeValue GameStateManager::getTSAFuseTimeLimit() {
+ return _TSAFuseTimeLimit;
+}
+
+void GameStateManager::setTSAState(byte state) {
+ _TSAState = state;
+}
+
+byte GameStateManager::getTSAState() {
+ return _TSAState;
+}
+
+void GameStateManager::setT0BMonitorMode(byte mode) {
+ _T0BMonitorMode = mode;
+}
+
+byte GameStateManager::getT0BMonitorMode() {
+ return _T0BMonitorMode;
+}
+
+void GameStateManager::setT0BMonitorStart(TimeValue start) {
+ _T0BMonitorStart = start;
+}
+
+TimeValue GameStateManager::getT0BMonitorStart() {
+ return _T0BMonitorStart;
+}
+
+void GameStateManager::setTSAIDedAtDoor(bool value) {
+ _TSAFlags.setFlag(kTSAIDedAtDoorFlag, value);
+}
+
+bool GameStateManager::getTSAIDedAtDoor() {
+ return _TSAFlags.getFlag(kTSAIDedAtDoorFlag);
+}
+
+void GameStateManager::setTSA0BZoomedIn(bool value) {
+ _TSAFlags.setFlag(kTSA0BZoomedInFlag, value);
+}
+
+bool GameStateManager::getTSA0BZoomedIn() {
+ return _TSAFlags.getFlag(kTSA0BZoomedInFlag);
+}
+
+void GameStateManager::setTSAFrontDoorUnlockedOutside(bool value) {
+ _TSAFlags.setFlag(kTSAFrontDoorUnlockedOutsideFlag, value);
+}
+
+bool GameStateManager::getTSAFrontDoorUnlockedOutside() {
+ return _TSAFlags.getFlag(kTSAFrontDoorUnlockedOutsideFlag);
+}
+
+void GameStateManager::setTSAFrontDoorUnlockedInside(bool value) {
+ _TSAFlags.setFlag(kTSAFrontDoorUnlockedInsideFlag, value);
+}
+
+bool GameStateManager::getTSAFrontDoorUnlockedInside() {
+ return _TSAFlags.getFlag(kTSAFrontDoorUnlockedInsideFlag);
+}
+
+void GameStateManager::setTSASeenRobotGreeting(bool value) {
+ _TSAFlags.setFlag(kTSASeenRobotGreetingFlag, value);
+}
+
+bool GameStateManager::getTSASeenRobotGreeting() {
+ return _TSAFlags.getFlag(kTSASeenRobotGreetingFlag);
+}
+
+void GameStateManager::setTSASeenTheory(bool value) {
+ _TSAFlags.setFlag(kTSASeenTheoryFlag, value);
+}
+
+bool GameStateManager::getTSASeenTheory() {
+ return _TSAFlags.getFlag(kTSASeenTheoryFlag);
+}
+
+void GameStateManager::setTSASeenBackground(bool value) {
+ _TSAFlags.setFlag(kTSASeenBackgroundFlag, value);
+}
+
+bool GameStateManager::getTSASeenBackground() {
+ return _TSAFlags.getFlag(kTSASeenBackgroundFlag);
+}
+
+void GameStateManager::setTSASeenProcedure(bool value) {
+ _TSAFlags.setFlag(kTSASeenProcedureFlag, value);
+}
+
+bool GameStateManager::getTSASeenProcedure() {
+ return _TSAFlags.getFlag(kTSASeenProcedureFlag);
+}
+
+void GameStateManager::setTSASeenAgent3AtDoor(bool value) {
+ _TSAFlags.setFlag(kTSASeenAgent3AtDoorFlag, value);
+}
+
+bool GameStateManager::getTSASeenAgent3AtDoor() {
+ return _TSAFlags.getFlag(kTSASeenAgent3AtDoorFlag);
+}
+
+void GameStateManager::setTSACommandCenterLocked(bool value) {
+ _TSAFlags.setFlag(kTSACommandCenterLockedFlag, value);
+}
+
+bool GameStateManager::getTSACommandCenterLocked() {
+ return _TSAFlags.getFlag(kTSACommandCenterLockedFlag);
+}
+
+void GameStateManager::setTSASeenCaldoriaNormal(bool value) {
+ _TSAFlags.setFlag(kTSASeenCaldoriaNormalFlag, value);
+}
+
+bool GameStateManager::getTSASeenCaldoriaNormal() {
+ return _TSAFlags.getFlag(kTSASeenCaldoriaNormalFlag);
+}
+
+void GameStateManager::setTSASeenCaldoriaAltered(bool value) {
+ _TSAFlags.setFlag(kTSASeenCaldoriaAlteredFlag, value);
+}
+
+bool GameStateManager::getTSASeenCaldoriaAltered() {
+ return _TSAFlags.getFlag(kTSASeenCaldoriaAlteredFlag);
+}
+
+void GameStateManager::setTSASeenNoradNormal(bool value) {
+ _TSAFlags.setFlag(kTSASeenNoradNormalFlag, value);
+}
+
+bool GameStateManager::getTSASeenNoradNormal() {
+ return _TSAFlags.getFlag(kTSASeenNoradNormalFlag);
+}
+
+void GameStateManager::setTSASeenNoradAltered(bool value) {
+ _TSAFlags.setFlag(kTSASeenNoradAlteredFlag, value);
+}
+
+bool GameStateManager::getTSASeenNoradAltered() {
+ return _TSAFlags.getFlag(kTSASeenNoradAlteredFlag);
+}
+
+void GameStateManager::setTSASeenMarsNormal(bool value) {
+ _TSAFlags.setFlag(kTSASeenMarsNormalFlag, value);
+}
+
+bool GameStateManager::getTSASeenMarsNormal() {
+ return _TSAFlags.getFlag(kTSASeenMarsNormalFlag);
+}
+
+void GameStateManager::setTSASeenMarsAltered(bool value) {
+ _TSAFlags.setFlag(kTSASeenMarsAlteredFlag, value);
+}
+
+bool GameStateManager::getTSASeenMarsAltered() {
+ return _TSAFlags.getFlag(kTSASeenMarsAlteredFlag);
+}
+
+void GameStateManager::setTSASeenWSCNormal(bool value) {
+ _TSAFlags.setFlag(kTSASeenWSCNormalFlag, value);
+}
+
+bool GameStateManager::getTSASeenWSCNormal() {
+ return _TSAFlags.getFlag(kTSASeenWSCNormalFlag);
+}
+
+void GameStateManager::setTSASeenWSCAltered(bool value) {
+ _TSAFlags.setFlag(kTSASeenWSCAlteredFlag, value);
+}
+
+bool GameStateManager::getTSASeenWSCAltered() {
+ return _TSAFlags.getFlag(kTSASeenWSCAlteredFlag);
+}
+
+void GameStateManager::setTSABiosuitOn(bool value) {
+ _TSAFlags.setFlag(kTSABiosuitOnFlag, value);
+}
+
+bool GameStateManager::getTSABiosuitOn() {
+ return _TSAFlags.getFlag(kTSABiosuitOnFlag);
+}
+
+void GameStateManager::setPrehistoricTriedToExtendBridge(bool value) {
+ _prehistoricFlags.setFlag(kPrehistoricTriedToExtendBridgeFlag, value);
+}
+
+bool GameStateManager::getPrehistoricTriedToExtendBridge() {
+ return _prehistoricFlags.getFlag(kPrehistoricTriedToExtendBridgeFlag);
+}
+
+void GameStateManager::setPrehistoricSeenTimeStream(bool value) {
+ _prehistoricFlags.setFlag(kPrehistoricSeenTimeStreamFlag, value);
+}
+
+bool GameStateManager::getPrehistoricSeenTimeStream() {
+ return _prehistoricFlags.getFlag(kPrehistoricSeenTimeStreamFlag);
+}
+
+void GameStateManager::setPrehistoricSeenFlyer1(bool value) {
+ _prehistoricFlags.setFlag(kPrehistoricSeenFlyer1Flag, value);
+}
+
+bool GameStateManager::getPrehistoricSeenFlyer1() {
+ return _prehistoricFlags.getFlag(kPrehistoricSeenFlyer1Flag);
+}
+
+void GameStateManager::setPrehistoricSeenFlyer2(bool value) {
+ _prehistoricFlags.setFlag(kPrehistoricSeenFlyer2Flag, value);
+}
+
+bool GameStateManager::getPrehistoricSeenFlyer2() {
+ return _prehistoricFlags.getFlag(kPrehistoricSeenFlyer2Flag);
+}
+
+void GameStateManager::setPrehistoricSeenBridgeZoom(bool value) {
+ _prehistoricFlags.setFlag(kPrehistoricSeenBridgeZoomFlag, value);
+}
+
+bool GameStateManager::getPrehistoricSeenBridgeZoom() {
+ return _prehistoricFlags.getFlag(kPrehistoricSeenBridgeZoomFlag);
+}
+
+void GameStateManager::setPrehistoricBreakerThrown(bool value) {
+ _prehistoricFlags.setFlag(kPrehistoricBreakerThrownFlag, value);
+}
+
+bool GameStateManager::getPrehistoricBreakerThrown() {
+ return _prehistoricFlags.getFlag(kPrehistoricBreakerThrownFlag);
+}
+
+void GameStateManager::setNoradSeenTimeStream(bool value) {
+ _noradFlags.setFlag(kNoradSeenTimeStreamFlag, value);
+}
+
+bool GameStateManager::getNoradSeenTimeStream() {
+ return _noradFlags.getFlag(kNoradSeenTimeStreamFlag);
+}
+
+void GameStateManager::setNoradGassed(bool value) {
+ _noradFlags.setFlag(kNoradGassedFlag, value);
+}
+
+bool GameStateManager::getNoradGassed() {
+ return _noradFlags.getFlag(kNoradGassedFlag);
+}
+
+void GameStateManager::setNoradFillingStationOn(bool value) {
+ _noradFlags.setFlag(kNoradFillingStationOnFlag, value);
+}
+
+bool GameStateManager::getNoradFillingStationOn() {
+ return _noradFlags.getFlag(kNoradFillingStationOnFlag);
+}
+
+void GameStateManager::setNoradN22MessagePlayed(bool value) {
+ _noradFlags.setFlag(kNoradN22MessagePlayedFlag, value);
+}
+
+bool GameStateManager::getNoradN22MessagePlayed() {
+ return _noradFlags.getFlag(kNoradN22MessagePlayedFlag);
+}
+
+void GameStateManager::setNoradPlayedGlobeGame(bool value) {
+ _noradFlags.setFlag(kNoradPlayedGlobeGameFlag, value);
+}
+
+bool GameStateManager::getNoradPlayedGlobeGame() {
+ return _noradFlags.getFlag(kNoradPlayedGlobeGameFlag);
+}
+
+void GameStateManager::setNoradBeatRobotWithClaw(bool value) {
+ _noradFlags.setFlag(kNoradBeatRobotWithClawFlag, value);
+}
+
+bool GameStateManager::getNoradBeatRobotWithClaw() {
+ return _noradFlags.getFlag(kNoradBeatRobotWithClawFlag);
+}
+
+void GameStateManager::setNoradBeatRobotWithDoor(bool value) {
+ _noradFlags.setFlag(kNoradBeatRobotWithDoorFlag, value);
+}
+
+bool GameStateManager::getNoradBeatRobotWithDoor() {
+ return _noradFlags.getFlag(kNoradBeatRobotWithDoorFlag);
+}
+
+void GameStateManager::setNoradRetScanGood(bool value) {
+ _noradFlags.setFlag(kNoradRetScanGoodFlag, value);
+}
+
+bool GameStateManager::getNoradRetScanGood() {
+ return _noradFlags.getFlag(kNoradRetScanGoodFlag);
+}
+
+void GameStateManager::setNoradWaitingForLaser(bool value) {
+ _noradFlags.setFlag(kNoradWaitingForLaserFlag, value);
+}
+
+bool GameStateManager::getNoradWaitingForLaser() {
+ return _noradFlags.getFlag(kNoradWaitingForLaserFlag);
+}
+
+void GameStateManager::setNoradSubRoomPressure(uint16 pressure) {
+ _noradSubRoomPressure = pressure;
+}
+
+uint16 GameStateManager::getNoradSubRoomPressure() {
+ return _noradSubRoomPressure;
+}
+
+void GameStateManager::setNoradSubPrepState(NoradSubPrepState state) {
+ _noradSubPrepState = state;
+}
+
+NoradSubPrepState GameStateManager::getNoradSubPrepState() {
+ return _noradSubPrepState;
+}
+
+void GameStateManager::setNoradArrivedFromSub(bool value) {
+ _noradFlags.setFlag(kNoradArrivedFromSubFlag, value);
+}
+
+bool GameStateManager::getNoradArrivedFromSub() {
+ return _noradFlags.getFlag(kNoradArrivedFromSubFlag);
+}
+
+void GameStateManager::setMarsSeenTimeStream(bool value) {
+ _marsFlags.setFlag(kMarsSeenTimeStreamFlag, value);
+}
+
+bool GameStateManager::getMarsSeenTimeStream() {
+ return _marsFlags.getFlag(kMarsSeenTimeStreamFlag);
+}
+
+void GameStateManager::setMarsHeardUpperPodMessage(bool value) {
+ _marsFlags.setFlag(kMarsHeardUpperPodMessageFlag, value);
+}
+
+bool GameStateManager::getMarsHeardUpperPodMessage() {
+ return _marsFlags.getFlag(kMarsHeardUpperPodMessageFlag);
+}
+
+void GameStateManager::setMarsRobotThrownPlayer(bool value) {
+ _marsFlags.setFlag(kMarsRobotThrownPlayerFlag, value);
+}
+
+bool GameStateManager::getMarsRobotThrownPlayer() {
+ return _marsFlags.getFlag(kMarsRobotThrownPlayerFlag);
+}
+
+void GameStateManager::setMarsHeardCheckInMessage(bool value) {
+ _marsFlags.setFlag(kMarsHeardCheckInMessageFlag, value);
+}
+
+bool GameStateManager::getMarsHeardCheckInMessage() {
+ return _marsFlags.getFlag(kMarsHeardCheckInMessageFlag);
+}
+
+void GameStateManager::setMarsPodAtUpperPlatform(bool value) {
+ _marsFlags.setFlag(kMarsPodAtUpperPlatformFlag, value);
+}
+
+bool GameStateManager::getMarsPodAtUpperPlatform() {
+ return _marsFlags.getFlag(kMarsPodAtUpperPlatformFlag);
+}
+
+void GameStateManager::setMarsSeenThermalScan(bool value) {
+ _marsFlags.setFlag(kMarsSeenThermalScanFlag, value);
+}
+
+bool GameStateManager::getMarsSeenThermalScan() {
+ return _marsFlags.getFlag(kMarsSeenThermalScanFlag);
+}
+
+void GameStateManager::setMarsArrivedBelow(bool value) {
+ _marsFlags.setFlag(kMarsArrivedBelowFlag, value);
+}
+
+bool GameStateManager::getMarsArrivedBelow() {
+ return _marsFlags.getFlag(kMarsArrivedBelowFlag);
+}
+
+void GameStateManager::setMarsSeenRobotAtReactor(bool value) {
+ _marsFlags.setFlag(kMarsSeenRobotAtReactorFlag, value);
+}
+
+bool GameStateManager::getMarsSeenRobotAtReactor() {
+ return _marsFlags.getFlag(kMarsSeenRobotAtReactorFlag);
+}
+
+void GameStateManager::setMarsAvoidedReactorRobot(bool value) {
+ _marsFlags.setFlag(kMarsAvoidedReactorRobotFlag, value);
+}
+
+bool GameStateManager::getMarsAvoidedReactorRobot() {
+ return _marsFlags.getFlag(kMarsAvoidedReactorRobotFlag);
+}
+
+void GameStateManager::setMarsSecurityDown(bool value) {
+ _marsFlags.setFlag(kMarsSecurityDownFlag, value);
+}
+
+bool GameStateManager::getMarsSecurityDown() {
+ return _marsFlags.getFlag(kMarsSecurityDownFlag);
+}
+
+void GameStateManager::setMarsInAirlock(bool value) {
+ _marsFlags.setFlag(kMarsInAirlockFlag, value);
+}
+
+bool GameStateManager::getMarsInAirlock() {
+ return _marsFlags.getFlag(kMarsInAirlockFlag);
+}
+
+void GameStateManager::setMarsAirlockOpen(bool value) {
+ _marsFlags.setFlag(kMarsAirlockOpenFlag, value);
+}
+
+bool GameStateManager::getMarsAirlockOpen() {
+ return _marsFlags.getFlag(kMarsAirlockOpenFlag);
+}
+
+void GameStateManager::setMarsMaskOnFiller(bool value) {
+ _marsFlags.setFlag(kMarsMaskOnFillerFlag, value);
+}
+
+bool GameStateManager::getMarsMaskOnFiller() {
+ return _marsFlags.getFlag(kMarsMaskOnFillerFlag);
+}
+
+void GameStateManager::setMarsLockFrozen(bool value) {
+ _marsFlags.setFlag(kMarsLockFrozenFlag, value);
+}
+
+bool GameStateManager::getMarsLockFrozen() {
+ return _marsFlags.getFlag(kMarsLockFrozenFlag);
+}
+
+void GameStateManager::setMarsLockBroken(bool value) {
+ _marsFlags.setFlag(kMarsLockBrokenFlag, value);
+}
+
+bool GameStateManager::getMarsLockBroken() {
+ return _marsFlags.getFlag(kMarsLockBrokenFlag);
+}
+
+void GameStateManager::setMarsMazeDoorPair1(bool value) {
+ _marsFlags.setFlag(kMarsMazeDoorPair1Flag, value);
+}
+
+bool GameStateManager::getMarsMazeDoorPair1() {
+ return _marsFlags.getFlag(kMarsMazeDoorPair1Flag);
+}
+
+void GameStateManager::setMarsMazeDoorPair2(bool value) {
+ _marsFlags.setFlag(kMarsMazeDoorPair2Flag, value);
+}
+
+bool GameStateManager::getMarsMazeDoorPair2() {
+ return _marsFlags.getFlag(kMarsMazeDoorPair2Flag);
+}
+
+void GameStateManager::setMarsMazeDoorPair3(bool value) {
+ _marsFlags.setFlag(kMarsMazeDoorPair3Flag, value);
+}
+
+bool GameStateManager::getMarsMazeDoorPair3() {
+ return _marsFlags.getFlag(kMarsMazeDoorPair3Flag);
+}
+
+void GameStateManager::setMarsSawRobotLeave(bool value) {
+ _marsFlags.setFlag(kMarsSawRobotLeaveFlag, value);
+}
+
+bool GameStateManager::getMarsSawRobotLeave() {
+ return _marsFlags.getFlag(kMarsSawRobotLeaveFlag);
+}
+
+void GameStateManager::setMarsHitRobotWithCannon(bool flag) {
+ _marsFlags.setFlag(kMarsHitRobotWithCannonFlag, flag);
+}
+
+bool GameStateManager::getMarsHitRobotWithCannon() {
+ return _marsFlags.getFlag(kMarsHitRobotWithCannonFlag);
+}
+
+void GameStateManager::setMarsReadyForShuttleTransport(bool value) {
+ _marsFlags.setFlag(kMarsReadyForShuttleTransportFlag, value);
+}
+
+bool GameStateManager::getMarsReadyForShuttleTransport() {
+ return _marsFlags.getFlag(kMarsReadyForShuttleTransportFlag);
+}
+
+void GameStateManager::setMarsFinishedCanyonChase(bool flag) {
+ _marsFlags.setFlag(kMarsFinishedCanyonChaseFlag, flag);
+}
+
+bool GameStateManager::getMarsFinishedCanyonChase() {
+ return _marsFlags.getFlag(kMarsFinishedCanyonChaseFlag);
+}
+
+void GameStateManager::setMarsThreadedMaze(bool flag) {
+ _marsFlags.setFlag(kMarsThreadedMazeFlag, flag);
+}
+
+bool GameStateManager::getMarsThreadedMaze() {
+ return _marsFlags.getFlag(kMarsThreadedMazeFlag);
+}
+
+void GameStateManager::setWSCSeenTimeStream(bool value) {
+ _WSCFlags.setFlag(kWSCSeenTimeStreamFlag, value);
+}
+
+bool GameStateManager::getWSCSeenTimeStream() {
+ return _WSCFlags.getFlag(kWSCSeenTimeStreamFlag);
+}
+
+void GameStateManager::setWSCPoisoned(bool value) {
+ _WSCFlags.setFlag(kWSCPoisonedFlag, value);
+}
+
+bool GameStateManager::getWSCPoisoned() {
+ return _WSCFlags.getFlag(kWSCPoisonedFlag);
+}
+
+void GameStateManager::setWSCAnsweredAboutDart(bool value) {
+ _WSCFlags.setFlag(kWSCAnsweredAboutDartFlag, value);
+}
+
+bool GameStateManager::getWSCAnsweredAboutDart() {
+ return _WSCFlags.getFlag(kWSCAnsweredAboutDartFlag);
+}
+
+void GameStateManager::setWSCRemovedDart(bool value) {
+ _WSCFlags.setFlag(kWSCRemovedDartFlag, value);
+}
+
+bool GameStateManager::getWSCRemovedDart() {
+ return _WSCFlags.getFlag(kWSCRemovedDartFlag);
+}
+
+void GameStateManager::setWSCAnalyzerOn(bool value) {
+ _WSCFlags.setFlag(kWSCAnalyzerOnFlag, value);
+}
+
+bool GameStateManager::getWSCAnalyzerOn() {
+ return _WSCFlags.getFlag(kWSCAnalyzerOnFlag);
+}
+
+void GameStateManager::setWSCDartInAnalyzer(bool value) {
+ _WSCFlags.setFlag(kWSCDartInAnalyzerFlag, value);
+}
+
+bool GameStateManager::getWSCDartInAnalyzer() {
+ return _WSCFlags.getFlag(kWSCDartInAnalyzerFlag);
+}
+
+void GameStateManager::setWSCAnalyzedDart(bool value) {
+ _WSCFlags.setFlag(kWSCAnalyzedDartFlag, value);
+}
+
+bool GameStateManager::getWSCAnalyzedDart() {
+ return _WSCFlags.getFlag(kWSCAnalyzedDartFlag);
+}
+
+void GameStateManager::setWSCSawMorph(bool value) {
+ _WSCFlags.setFlag(kWSCSawMorphFlag, value);
+}
+
+bool GameStateManager::getWSCSawMorph() {
+ return _WSCFlags.getFlag(kWSCSawMorphFlag);
+}
+
+void GameStateManager::setWSCDesignedAntidote(bool value) {
+ _WSCFlags.setFlag(kWSCDesignedAntidoteFlag, value);
+}
+
+bool GameStateManager::getWSCDesignedAntidote() {
+ return _WSCFlags.getFlag(kWSCDesignedAntidoteFlag);
+}
+
+void GameStateManager::setWSCPickedUpAntidote(bool value) {
+ _WSCFlags.setFlag(kWSCPickedUpAntidoteFlag, value);
+}
+
+bool GameStateManager::getWSCPickedUpAntidote() {
+ return _WSCFlags.getFlag(kWSCPickedUpAntidoteFlag);
+}
+
+void GameStateManager::setWSCOfficeMessagesOpen(bool value) {
+ _WSCFlags.setFlag(kWSCOfficeMessagesOpenFlag, value);
+}
+
+bool GameStateManager::getWSCOfficeMessagesOpen() {
+ return _WSCFlags.getFlag(kWSCOfficeMessagesOpenFlag);
+}
+
+void GameStateManager::setWSCSeenNerd(bool value) {
+ _WSCFlags.setFlag(kWSCSeenNerdFlag, value);
+}
+
+bool GameStateManager::getWSCSeenNerd() {
+ return _WSCFlags.getFlag(kWSCSeenNerdFlag);
+}
+
+void GameStateManager::setWSCHeardPage1(bool value) {
+ _WSCFlags.setFlag(kWSCHeardPage1Flag, value);
+}
+
+bool GameStateManager::getWSCHeardPage1() {
+ return _WSCFlags.getFlag(kWSCHeardPage1Flag);
+}
+
+void GameStateManager::setWSCHeardPage2(bool value) {
+ _WSCFlags.setFlag(kWSCHeardPage2Flag, value);
+}
+
+bool GameStateManager::getWSCHeardPage2() {
+ return _WSCFlags.getFlag(kWSCHeardPage2Flag);
+}
+
+void GameStateManager::setWSCHeardCheckIn(bool value) {
+ _WSCFlags.setFlag(kWSCHeardCheckInFlag, value);
+}
+
+bool GameStateManager::getWSCHeardCheckIn() {
+ return _WSCFlags.getFlag(kWSCHeardCheckInFlag);
+}
+
+void GameStateManager::setWSCDidPlasmaDodge(bool value) {
+ _WSCFlags.setFlag(kWSCDidPlasmaDodgeFlag, value);
+}
+
+bool GameStateManager::getWSCDidPlasmaDodge() {
+ return _WSCFlags.getFlag(kWSCDidPlasmaDodgeFlag);
+}
+
+void GameStateManager::setWSCSeenSinclairLecture(bool value) {
+ _WSCFlags.setFlag(kWSCSeenSinclairLectureFlag, value);
+}
+
+bool GameStateManager::getWSCSeenSinclairLecture() {
+ return _WSCFlags.getFlag(kWSCSeenSinclairLectureFlag);
+}
+
+void GameStateManager::setWSCBeenAtWSC93(bool value) {
+ _WSCFlags.setFlag(kWSCBeenAtWSC93Flag, value);
+}
+
+bool GameStateManager::getWSCBeenAtWSC93() {
+ return _WSCFlags.getFlag(kWSCBeenAtWSC93Flag);
+}
+
+void GameStateManager::setWSCCatwalkDark(bool value) {
+ _WSCFlags.setFlag(kWSCCatwalkDarkFlag, value);
+}
+
+bool GameStateManager::getWSCCatwalkDark() {
+ return _WSCFlags.getFlag(kWSCCatwalkDarkFlag);
+}
+
+void GameStateManager::setWSCRobotDead(bool value) {
+ _WSCFlags.setFlag(kWSCRobotDeadFlag, value);
+}
+
+bool GameStateManager::getWSCRobotDead() {
+ return _WSCFlags.getFlag(kWSCRobotDeadFlag);
+}
+
+void GameStateManager::setWSCRobotGone(bool value) {
+ _WSCFlags.setFlag(kWSCRobotGoneFlag, value);
+}
+
+bool GameStateManager::getWSCRobotGone() {
+ return _WSCFlags.getFlag(kWSCRobotGoneFlag);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/gamestate.h b/engines/pegasus/gamestate.h
new file mode 100644
index 0000000000..dd47bd6e51
--- /dev/null
+++ b/engines/pegasus/gamestate.h
@@ -0,0 +1,886 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_GAMESTATE_H
+#define PEGASUS_GAMESTATE_H
+
+#include "common/singleton.h"
+#include "common/util.h"
+
+#include "pegasus/types.h"
+#include "pegasus/util.h"
+#include "pegasus/items/item.h"
+
+namespace Common {
+ class Error;
+ class ReadStream;
+ class WriteStream;
+}
+
+namespace Pegasus {
+
+// The only things saved in here are things which get written out to a saved game file...
+
+enum {
+ kGlobalWalkthroughFlag,
+ kGlobalShieldOnFlag,
+ kGlobalEasterEggFlag,
+ kGlobalBeenToWSCFlag,
+ kGlobalBeenToMarsFlag,
+ kGlobalBeenToNoradFlag,
+ kGlobalWSCFinishedFlag,
+ kGlobalMarsFinishedFlag,
+ kGlobalNoradFinishedFlag,
+ kNumGlobalFlags
+};
+
+enum {
+ kScoringSawINNFlag,
+ kScoringTookShowerFlag,
+ kScoringFixedHairFlag,
+ kScoringGotKeyCardFlag,
+ kScoringReadPaperFlag,
+ kScoringLookThroughTelescopeFlag,
+ kScoringSawCaldoriaKioskFlag,
+ kScoringGoToTSAFlag,
+ kScoringEnterTSAFlag,
+ kScoringSawBust1Flag,
+ kScoringSawBust2Flag,
+ kScoringSawBust3Flag,
+ kScoringSawBust4Flag,
+ kScoringSawBust5Flag,
+ kScoringSawBust6Flag,
+ kScoringSawTheoryFlag,
+ kScoringSawBackgroundFlag,
+ kScoringSawProcedureFlag,
+ kScoringGotJourneymanKeyFlag,
+ kScoringGotPegasusBiochipFlag,
+ kScoringGotBiosuitFlag,
+ kScoringGoToPrehistoricFlag,
+ kScoringPutLogInReaderFlag,
+ kScoringSawCaldoriaNormalFlag,
+ kScoringSawCaldoriaAlteredFlag,
+ kScoringSawNoradNormalFlag,
+ kScoringSawNoradAlteredFlag,
+ kScoringSawMarsNormalFlag,
+ kScoringSawMarsAlteredFlag,
+ kScoringSawWSCNormalFlag,
+ kScoringSawWSCAlteredFlag,
+ kScoringWentToReadyRoom2Flag,
+ kScoringWentAfterSinclairFlag,
+ kScoringUsedCardBombFlag,
+ kScoringShieldedCardBombFlag,
+ kScoringStunnedSinclairFlag,
+ kScoringDisarmedNukeFlag,
+
+ kScoringThrewBreakerFlag,
+ kScoringExtendedBridgeFlag,
+ kScoringGotHistoricalLogFlag,
+ kScoringFinishedPrehistoricFlag,
+
+ kScoringThrownByRobotFlag,
+ kScoringGotMarsCardFlag,
+ kScoringSawMarsKioskFlag,
+ kScoringSawTransportMapFlag,
+ kScoringGotCrowBarFlag,
+ kScoringTurnedOnTransportFlag,
+ kScoringGotOxygenMaskFlag,
+ kScoringAvoidedRobotFlag,
+ kScoringActivatedPlatformFlag,
+ kScoringUsedLiquidNitrogenFlag,
+ kScoringUsedCrowBarFlag,
+ kScoringFoundCardBombFlag,
+ kScoringDisarmedCardBombFlag,
+ kScoringGotCardBombFlag,
+ kScoringThreadedMazeFlag,
+ kScoringThreadedGearRoomFlag,
+ kScoringEnteredShuttleFlag,
+ kScoringEnteredLaunchTubeFlag,
+ kScoringStoppedRobotsShuttleFlag,
+ kScoringGotMarsOpMemChipFlag,
+ kScoringFinishedMarsFlag,
+
+ kScoringSawSecurityMonitorFlag,
+ kScoringFilledOxygenCanisterFlag,
+ kScoringFilledArgonCanisterFlag,
+ kScoringSawUnconsciousOperatorFlag,
+ kScoringWentThroughPressureDoorFlag,
+ kScoringPreppedSubFlag,
+ kScoringEnteredSubFlag,
+ kScoringExitedSubFlag,
+ kScoringSawRobotAt54NorthFlag,
+ kScoringPlayedWithClawFlag,
+ kScoringUsedRetinalChipFlag,
+ kScoringFinishedGlobeGameFlag,
+ kScoringStoppedNoradRobotFlag,
+ kScoringGotNoradOpMemChipFlag,
+ kScoringFinishedNoradFlag,
+
+ kScoringRemovedDartFlag,
+ kScoringAnalyzedDartFlag,
+ kScoringBuiltAntidoteFlag,
+ kScoringGotSinclairKeyFlag,
+ kScoringGotArgonCanisterFlag,
+ kScoringGotNitrogenCanisterFlag,
+ kScoringPlayedWithMessagesFlag,
+ kScoringSawMorphExperimentFlag,
+ kScoringEnteredSinclairOfficeFlag,
+ kScoringSawBrochureFlag,
+ kScoringSawSinclairEntry1Flag,
+ kScoringSawSinclairEntry2Flag,
+ kScoringSawSinclairEntry3Flag,
+ kScoringSawWSCDirectoryFlag,
+ kScoringUsedCrowBarInWSCFlag,
+ kScoringFinishedPlasmaDodgeFlag,
+ kScoringOpenedCatwalkFlag,
+ kScoringStoppedWSCRobotFlag,
+ kScoringGotWSCOpMemChipFlag,
+ kScoringFinishedWSCFlag,
+
+ kScoringMarsGandhiFlag,
+ kScoringNoradGandhiFlag,
+ kScoringWSCGandhiFlag,
+
+ kNumScoringFlags
+};
+
+enum {
+ kCaldoriaSeenPullbackFlag,
+ kCaldoriaMadeOJFlag,
+ kCaldoriaWokenUpFlag,
+ kCaldoriaDidRecalibrationFlag,
+ kCaldoriaSeenSinclairInElevatorFlag,
+ kCaldoriaINNAnnouncingFlag,
+ kCaldoriaSeenINNFlag,
+ kCaldoriaSeenMessagesFlag,
+ kCaldoriaSinclairShotFlag,
+ kCaldoriaBombDisarmedFlag,
+ kCaldoriaRoofDoorOpenFlag,
+ kCaldoriaDoneHygieneFlag,
+ kCaldoriaSawVoiceAnalysisFlag,
+ kCaldoriaDoorBombedFlag,
+ kCaldoriaGunAimedFlag,
+ kNumCaldoriaFlags
+};
+
+enum {
+ kCaldoriaNoFuseRunning,
+ kCaldoriaDoorBombFuseRunning,
+ kCaldoriaSinclairFuseRunning
+};
+
+enum {
+ kTSAIDedAtDoorFlag,
+ kTSA0BZoomedInFlag,
+ kTSAFrontDoorUnlockedOutsideFlag,
+ kTSAFrontDoorUnlockedInsideFlag,
+ kTSASeenRobotGreetingFlag,
+ kTSASeenTheoryFlag,
+ kTSASeenBackgroundFlag,
+ kTSASeenProcedureFlag,
+ kTSASeenAgent3AtDoorFlag,
+ kTSACommandCenterLockedFlag,
+ kTSASeenCaldoriaNormalFlag,
+ kTSASeenCaldoriaAlteredFlag,
+ kTSASeenNoradNormalFlag,
+ kTSASeenNoradAlteredFlag,
+ kTSASeenMarsNormalFlag,
+ kTSASeenMarsAlteredFlag,
+ kTSASeenWSCNormalFlag,
+ kTSASeenWSCAlteredFlag,
+ kTSABiosuitOnFlag,
+ kNumTSAFlags
+};
+
+enum {
+ kPrehistoricTriedToExtendBridgeFlag,
+ kPrehistoricSeenTimeStreamFlag,
+ kPrehistoricSeenFlyer1Flag,
+ kPrehistoricSeenFlyer2Flag,
+ kPrehistoricSeenBridgeZoomFlag,
+ kPrehistoricBreakerThrownFlag,
+ kNumPrehistoricFlags
+};
+
+enum {
+ kNoradSeenTimeStreamFlag,
+ kNoradGassedFlag,
+ kNoradFillingStationOnFlag,
+ kNoradN22MessagePlayedFlag,
+ kNoradArrivedFromSubFlag,
+ kNoradWaitingForLaserFlag,
+ kNoradRetScanGoodFlag,
+ kNoradPlayedGlobeGameFlag,
+ kNoradBeatRobotWithClawFlag,
+ kNoradBeatRobotWithDoorFlag,
+ kNumNoradFlags
+};
+
+enum {
+ kMarsSeenTimeStreamFlag,
+ kMarsHeardUpperPodMessageFlag,
+ kMarsRobotThrownPlayerFlag,
+ kMarsHeardCheckInMessageFlag,
+ kMarsPodAtUpperPlatformFlag,
+ kMarsSeenThermalScanFlag,
+ kMarsArrivedBelowFlag,
+ kMarsSeenRobotAtReactorFlag,
+ kMarsAvoidedReactorRobotFlag,
+ kMarsInAirlockFlag,
+ kMarsAirlockOpenFlag,
+ kMarsMaskOnFillerFlag,
+ kMarsLockFrozenFlag,
+ kMarsLockBrokenFlag,
+ kMarsMazeDoorPair1Flag,
+ kMarsMazeDoorPair2Flag,
+ kMarsMazeDoorPair3Flag,
+ kMarsSawRobotLeaveFlag,
+ kMarsSecurityDownFlag,
+ kMarsHitRobotWithCannonFlag,
+ kMarsReadyForShuttleTransportFlag,
+ kMarsFinishedCanyonChaseFlag,
+ kMarsThreadedMazeFlag,
+ kNumMarsFlags
+};
+
+enum {
+ kWSCSeenTimeStreamFlag,
+ kWSCPoisonedFlag,
+ kWSCAnsweredAboutDartFlag,
+ kWSCRemovedDartFlag,
+ kWSCAnalyzerOnFlag,
+ kWSCDartInAnalyzerFlag,
+ kWSCAnalyzedDartFlag,
+ kWSCSawMorphFlag,
+ kWSCDesignedAntidoteFlag,
+ kWSCPickedUpAntidoteFlag,
+ kWSCOfficeMessagesOpenFlag,
+ kWSCSeenNerdFlag,
+ kWSCHeardPage1Flag,
+ kWSCHeardPage2Flag,
+ kWSCHeardCheckInFlag,
+ kWSCDidPlasmaDodgeFlag,
+ kWSCSeenSinclairLectureFlag,
+ kWSCBeenAtWSC93Flag,
+ kWSCCatwalkDarkFlag,
+ kWSCRobotDeadFlag,
+ kWSCRobotGoneFlag,
+ kNumWSCFlags
+};
+
+class GameStateManager : public Common::Singleton<GameStateManager> {
+public:
+ GameStateManager() { resetGameState(); }
+
+ // Base game state
+ Common::Error writeGameState(Common::WriteStream *stream);
+ Common::Error readGameState(Common::ReadStream *stream);
+
+ void resetGameState();
+
+ void getCurrentLocation(NeighborhoodID &neighborhood, RoomID &room, DirectionConstant &direction);
+ void setCurrentLocation(const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction);
+
+ NeighborhoodID getCurrentNeighborhood();
+ void setCurrentNeighborhood(const NeighborhoodID neighborhood);
+ RoomID getCurrentRoom();
+ void setCurrentRoom(const RoomID room);
+ DirectionConstant getCurrentDirection();
+ void setCurrentDirection(const DirectionConstant direction);
+
+ RoomViewID getCurrentRoomAndView();
+
+ void getNextLocation(NeighborhoodID &neighborhood, RoomID &room, DirectionConstant &direction);
+ void setNextLocation(const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction);
+
+ NeighborhoodID getNextNeighborhood();
+ void setNextNeighborhood(const NeighborhoodID neighborhood);
+ RoomID getNextRoom();
+ void setNextRoom(const RoomID room);
+ DirectionConstant getNextDirection();
+ void setNextDirection(const DirectionConstant direction);
+
+ void getLastLocation(NeighborhoodID &neighborhood, RoomID &room, DirectionConstant &direction);
+ void setLastLocation(const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction);
+
+ NeighborhoodID getLastNeighborhood();
+ void setLastNeighborhood(const NeighborhoodID neighborhood);
+ RoomID getLastRoom();
+ void setLastRoom(const RoomID room);
+ DirectionConstant getLastDirection();
+ void setLastDirection(const DirectionConstant direction);
+
+ RoomViewID getLastRoomAndView();
+
+ void getOpenDoorLocation(RoomID &room, DirectionConstant &direction);
+ void setOpenDoorLocation(const RoomID room, const DirectionConstant direction);
+ RoomID getOpenDoorRoom();
+ void setOpenDoorRoom(const RoomID room);
+ DirectionConstant getOpenDoorDirection();
+ void setOpenDoorDirection(const DirectionConstant direction);
+
+ RoomViewID getDoorOpenRoomAndView();
+
+ bool isCurrentDoorOpen();
+
+ // Pegasus Prime
+
+ // Scoring...
+ // Scoring "Set" functions.
+ // Caldoria/TSA scoring
+ void setScoringSawINN(const bool = true);
+ void setScoringTookShower(const bool = true);
+ void setScoringFixedHair(const bool = true);
+ void setScoringGotKeyCard(const bool = true);
+ void setScoringReadPaper(const bool = true);
+ void setScoringLookThroughTelescope(const bool = true);
+ void setScoringSawCaldoriaKiosk(const bool = true);
+ void setScoringGoToTSA(const bool = true);
+ void setScoringEnterTSA(const bool = true);
+ void setScoringSawBust1(const bool = true);
+ void setScoringSawBust2(const bool = true);
+ void setScoringSawBust3(const bool = true);
+ void setScoringSawBust4(const bool = true);
+ void setScoringSawBust5(const bool = true);
+ void setScoringSawBust6(const bool = true);
+ void setScoringSawTheory(const bool = true);
+ void setScoringSawBackground(const bool = true);
+ void setScoringSawProcedure(const bool = true);
+ void setScoringGotJourneymanKey(const bool = true);
+ void setScoringGotPegasusBiochip(const bool = true);
+ void setScoringGotBiosuit(const bool = true);
+ void setScoringGoToPrehistoric(const bool = true);
+ void setScoringPutLogInReader(const bool = true);
+ void setScoringSawCaldoriaNormal(const bool = true);
+ void setScoringSawCaldoriaAltered(const bool = true);
+ void setScoringSawNoradNormal(const bool = true);
+ void setScoringSawNoradAltered(const bool = true);
+ void setScoringSawMarsNormal(const bool = true);
+ void setScoringSawMarsAltered(const bool = true);
+ void setScoringSawWSCNormal(const bool = true);
+ void setScoringSawWSCAltered(const bool = true);
+ void setScoringWentToReadyRoom2(const bool = true);
+ void setScoringWentAfterSinclair(const bool = true);
+ void setScoringUsedCardBomb(const bool = true);
+ void setScoringShieldedCardBomb(const bool = true);
+ void setScoringStunnedSinclair(const bool = true);
+ void setScoringDisarmedNuke(const bool = true);
+
+ // Prehistoric scoring
+ void setScoringThrewBreaker(const bool = true);
+ void setScoringExtendedBridge(const bool = true);
+ void setScoringGotHistoricalLog(const bool = true);
+ void setScoringFinishedPrehistoric(const bool = true);
+
+ // Mars scoring
+ void setScoringThrownByRobot(const bool = true);
+ void setScoringGotMarsCard(const bool = true);
+ void setScoringSawMarsKiosk(const bool = true);
+ void setScoringSawTransportMap(const bool = true);
+ void setScoringGotCrowBar(const bool = true);
+ void setScoringTurnedOnTransport(const bool = true);
+ void setScoringGotOxygenMask(const bool = true);
+ void setScoringAvoidedRobot(const bool = true);
+ void setScoringActivatedPlatform(const bool = true);
+ void setScoringUsedLiquidNitrogen(const bool = true);
+ void setScoringUsedCrowBar(const bool = true);
+ void setScoringFoundCardBomb(const bool = true);
+ void setScoringDisarmedCardBomb(const bool = true);
+ void setScoringGotCardBomb(const bool = true);
+ void setScoringThreadedMaze(const bool = true);
+ void setScoringThreadedGearRoom(const bool = true);
+ void setScoringEnteredShuttle(const bool = true);
+ void setScoringEnteredLaunchTube(const bool = true);
+ void setScoringStoppedRobotsShuttle(const bool = true);
+ void setScoringGotMarsOpMemChip(const bool = true);
+ void setScoringFinishedMars(const bool = true);
+
+ // Norad scoring
+ void setScoringSawSecurityMonitor(const bool = true);
+ void setScoringFilledOxygenCanister(const bool = true);
+ void setScoringFilledArgonCanister(const bool = true);
+ void setScoringSawUnconsciousOperator(const bool = true);
+ void setScoringWentThroughPressureDoor(const bool = true);
+ void setScoringPreppedSub(const bool = true);
+ void setScoringEnteredSub(const bool = true);
+ void setScoringExitedSub(const bool = true);
+ void setScoringSawRobotAt54North(const bool = true);
+ void setScoringPlayedWithClaw(const bool = true);
+ void setScoringUsedRetinalChip(const bool = true);
+ void setScoringFinishedGlobeGame(const bool = true);
+ void setScoringStoppedNoradRobot(const bool = true);
+ void setScoringGotNoradOpMemChip(const bool = true);
+ void setScoringFinishedNorad(const bool = true);
+
+ // WSC scoring
+ void setScoringRemovedDart(const bool = true);
+ void setScoringAnalyzedDart(const bool = true);
+ void setScoringBuiltAntidote(const bool = true);
+ void setScoringGotSinclairKey(const bool = true);
+ void setScoringGotArgonCanister(const bool = true);
+ void setScoringGotNitrogenCanister(const bool = true);
+ void setScoringPlayedWithMessages(const bool = true);
+ void setScoringSawMorphExperiment(const bool = true);
+ void setScoringEnteredSinclairOffice(const bool = true);
+ void setScoringSawBrochure(const bool = true);
+ void setScoringSawSinclairEntry1(const bool = true);
+ void setScoringSawSinclairEntry2(const bool = true);
+ void setScoringSawSinclairEntry3(const bool = true);
+ void setScoringSawWSCDirectory(const bool = true);
+ void setScoringUsedCrowBarInWSC(const bool = true);
+ void setScoringFinishedPlasmaDodge(const bool = true);
+ void setScoringOpenedCatwalk(const bool = true);
+ void setScoringStoppedWSCRobot(const bool = true);
+ void setScoringGotWSCOpMemChip(const bool = true);
+ void setScoringFinishedWSC(const bool = true);
+
+ // Gandhi scoring
+ void setScoringMarsGandhi(const bool = true);
+ void setScoringNoradGandhi(const bool = true);
+ void setScoringWSCGandhi(const bool = true);
+
+ // Scoring "Get" functions.
+ bool getScoringSawINN();
+ bool getScoringTookShower();
+ bool getScoringFixedHair();
+ bool getScoringGotKeyCard();
+ bool getScoringReadPaper();
+ bool getScoringLookThroughTelescope();
+ bool getScoringSawCaldoriaKiosk();
+ bool getScoringGoToTSA();
+ bool getScoringEnterTSA();
+ bool getScoringSawBust1();
+ bool getScoringSawBust2();
+ bool getScoringSawBust3();
+ bool getScoringSawBust4();
+ bool getScoringSawBust5();
+ bool getScoringSawBust6();
+ bool getScoringSawTheory();
+ bool getScoringSawBackground();
+ bool getScoringSawProcedure();
+ bool getScoringGotJourneymanKey();
+ bool getScoringGotPegasusBiochip();
+ bool getScoringGotBiosuit();
+ bool getScoringGoToPrehistoric();
+ bool getScoringPutLogInReader();
+ bool getScoringSawCaldoriaNormal();
+ bool getScoringSawCaldoriaAltered();
+ bool getScoringSawNoradNormal();
+ bool getScoringSawNoradAltered();
+ bool getScoringSawMarsNormal();
+ bool getScoringSawMarsAltered();
+ bool getScoringSawWSCNormal();
+ bool getScoringSawWSCAltered();
+ bool getScoringWentToReadyRoom2();
+ bool getScoringWentAfterSinclair();
+ bool getScoringUsedCardBomb();
+ bool getScoringShieldedCardBomb();
+ bool getScoringStunnedSinclair();
+ bool getScoringDisarmedNuke();
+ bool getScoringThrewBreaker();
+ bool getScoringExtendedBridge();
+ bool getScoringGotHistoricalLog();
+ bool getScoringFinishedPrehistoric();
+ bool getScoringThrownByRobot();
+ bool getScoringGotMarsCard();
+ bool getScoringSawMarsKiosk();
+ bool getScoringSawTransportMap();
+ bool getScoringGotCrowBar();
+ bool getScoringTurnedOnTransport();
+ bool getScoringGotOxygenMask();
+ bool getScoringAvoidedRobot();
+ bool getScoringActivatedPlatform();
+ bool getScoringUsedLiquidNitrogen();
+ bool getScoringUsedCrowBar();
+ bool getScoringFoundCardBomb();
+ bool getScoringDisarmedCardBomb();
+ bool getScoringGotCardBomb();
+ bool getScoringThreadedMaze();
+ bool getScoringThreadedGearRoom();
+ bool getScoringEnteredShuttle();
+ bool getScoringEnteredLaunchTube();
+ bool getScoringStoppedRobotsShuttle();
+ bool getScoringGotMarsOpMemChip();
+ bool getScoringFinishedMars();
+ bool getScoringSawSecurityMonitor();
+ bool getScoringFilledOxygenCanister();
+ bool getScoringFilledArgonCanister();
+ bool getScoringSawUnconsciousOperator();
+ bool getScoringWentThroughPressureDoor();
+ bool getScoringPreppedSub();
+ bool getScoringEnteredSub();
+ bool getScoringExitedSub();
+ bool getScoringSawRobotAt54North();
+ bool getScoringPlayedWithClaw();
+ bool getScoringUsedRetinalChip();
+ bool getScoringFinishedGlobeGame();
+ bool getScoringStoppedNoradRobot();
+ bool getScoringGotNoradOpMemChip();
+ bool getScoringFinishedNorad();
+ bool getScoringRemovedDart();
+ bool getScoringAnalyzedDart();
+ bool getScoringBuiltAntidote();
+ bool getScoringGotSinclairKey();
+ bool getScoringGotArgonCanister();
+ bool getScoringGotNitrogenCanister();
+ bool getScoringPlayedWithMessages();
+ bool getScoringSawMorphExperiment();
+ bool getScoringEnteredSinclairOffice();
+ bool getScoringSawBrochure();
+ bool getScoringSawSinclairEntry1();
+ bool getScoringSawSinclairEntry2();
+ bool getScoringSawSinclairEntry3();
+ bool getScoringSawWSCDirectory();
+ bool getScoringUsedCrowBarInWSC();
+ bool getScoringFinishedPlasmaDodge();
+ bool getScoringOpenedCatwalk();
+ bool getScoringStoppedWSCRobot();
+ bool getScoringGotWSCOpMemChip();
+ bool getScoringFinishedWSC();
+ bool getScoringMarsGandhi();
+ bool getScoringNoradGandhi();
+ bool getScoringWSCGandhi();
+
+ GameScoreType getCaldoriaTSAScore();
+ GameScoreType getPrehistoricScore();
+ GameScoreType getMarsScore();
+ GameScoreType getNoradScore();
+ GameScoreType getWSCScore();
+ GameScoreType getGandhiScore();
+ GameScoreType getTotalScore();
+
+ void writeCaldoriaState(Common::WriteStream *stream);
+ void readCaldoriaState(Common::ReadStream *stream);
+ void resetCaldoriaState();
+
+ void writeTSAState(Common::WriteStream *stream);
+ void readTSAState(Common::ReadStream *stream);
+ void resetTSAState();
+
+ void writePrehistoricState(Common::WriteStream *stream);
+ void readPrehistoricState(Common::ReadStream *stream);
+ void resetPrehistoricState();
+
+ void writeNoradState(Common::WriteStream *stream);
+ void readNoradState(Common::ReadStream *stream);
+ void resetNoradState();
+
+ void writeMarsState(Common::WriteStream *stream);
+ void readMarsState(Common::ReadStream *stream);
+ void resetMarsState();
+
+ void writeWSCState(Common::WriteStream *stream);
+ void readWSCState(Common::ReadStream *stream);
+ void resetWSCState();
+
+ // Globals.
+ void setWalkthroughMode(bool);
+ bool getWalkthroughMode();
+ void setShieldOn(bool);
+ bool getShieldOn();
+ void setEasterEgg(bool);
+ bool getEasterEgg();
+ void setBeenToWSC(bool value);
+ bool getBeenToWSC();
+ void setBeenToMars(bool value);
+ bool getBeenToMars();
+ void setBeenToNorad(bool value);
+ bool getBeenToNorad();
+ void setWSCFinished(bool);
+ bool getWSCFinished();
+ void setMarsFinished(bool);
+ bool getMarsFinished();
+ void setNoradFinished(bool);
+ bool getNoradFinished();
+ bool allTimeZonesFinished();
+ void setTakenItemID(ItemID, bool);
+ bool isTakenItemID(ItemID);
+ void setTakenItem(Item *, bool);
+ bool isTakenItem(Item *);
+
+ // Caldoria
+ void setCaldoriaFuseTimeLimit(const TimeValue);
+ TimeValue getCaldoriaFuseTimeLimit();
+ void setCaldoriaSeenPullback(bool);
+ bool getCaldoriaSeenPullback();
+ void setCaldoriaMadeOJ(bool);
+ bool getCaldoriaMadeOJ();
+ void setCaldoriaWokenUp(bool);
+ bool getCaldoriaWokenUp();
+ void setCaldoriaDidRecalibration(bool);
+ bool getCaldoriaDidRecalibration();
+ void setCaldoriaSeenSinclairInElevator(bool);
+ bool getCaldoriaSeenSinclairInElevator();
+ void setCaldoriaINNAnnouncing(bool);
+ bool getCaldoriaINNAnnouncing();
+ void setCaldoriaSeenINN(bool);
+ bool getCaldoriaSeenINN();
+ void setCaldoriaSeenMessages(bool);
+ bool getCaldoriaSeenMessages();
+ void setCaldoriaSinclairShot(bool);
+ bool getCaldoriaSinclairShot();
+ void setCaldoriaBombDisarmed(bool);
+ bool getCaldoriaBombDisarmed();
+ void setCaldoriaRoofDoorOpen(bool);
+ bool getCaldoriaRoofDoorOpen();
+ void setCaldoriaDoneHygiene(bool);
+ bool getCaldoriaDoneHygiene();
+ void setCaldoriaSawVoiceAnalysis(bool);
+ bool getCaldoriaSawVoiceAnalysis();
+ void setCaldoriaDoorBombed(bool);
+ bool getCaldoriaDoorBombed();
+ void setCaldoriaGunAimed(bool);
+ bool getCaldoriaGunAimed();
+
+ // TSA
+ void setRipTimerTime(TimeValue);
+ TimeValue getRipTimerTime();
+ void setTSAFuseTimeLimit(TimeValue);
+ TimeValue getTSAFuseTimeLimit();
+ void setT0BMonitorMode(byte);
+ byte getT0BMonitorMode();
+ void setTSAState(byte);
+ byte getTSAState();
+ void setT0BMonitorStart(TimeValue);
+ TimeValue getT0BMonitorStart();
+ void setTSAIDedAtDoor(bool);
+ bool getTSAIDedAtDoor();
+ void setTSA0BZoomedIn(bool);
+ bool getTSA0BZoomedIn();
+ void setTSAFrontDoorUnlockedOutside(bool);
+ bool getTSAFrontDoorUnlockedOutside();
+ void setTSAFrontDoorUnlockedInside(bool);
+ bool getTSAFrontDoorUnlockedInside();
+ void setTSASeenRobotGreeting(bool);
+ bool getTSASeenRobotGreeting();
+ void setTSASeenTheory(bool);
+ bool getTSASeenTheory();
+ void setTSASeenBackground(bool);
+ bool getTSASeenBackground();
+ void setTSASeenProcedure(bool);
+ bool getTSASeenProcedure();
+ void setTSASeenAgent3AtDoor(bool);
+ bool getTSASeenAgent3AtDoor();
+ void setTSACommandCenterLocked(bool);
+ bool getTSACommandCenterLocked();
+ void setTSASeenCaldoriaNormal(bool);
+ bool getTSASeenCaldoriaNormal();
+ void setTSASeenCaldoriaAltered(bool);
+ bool getTSASeenCaldoriaAltered();
+ void setTSASeenNoradNormal(bool);
+ bool getTSASeenNoradNormal();
+ void setTSASeenNoradAltered(bool);
+ bool getTSASeenNoradAltered();
+ void setTSASeenMarsNormal(bool);
+ bool getTSASeenMarsNormal();
+ void setTSASeenMarsAltered(bool);
+ bool getTSASeenMarsAltered();
+ void setTSASeenWSCNormal(bool);
+ bool getTSASeenWSCNormal();
+ void setTSASeenWSCAltered(bool);
+ bool getTSASeenWSCAltered();
+ void setTSABiosuitOn(bool);
+ bool getTSABiosuitOn();
+
+ // Prehistoric
+ void setPrehistoricTriedToExtendBridge(bool);
+ bool getPrehistoricTriedToExtendBridge();
+ void setPrehistoricSeenTimeStream(bool);
+ bool getPrehistoricSeenTimeStream();
+ void setPrehistoricSeenFlyer1(bool);
+ bool getPrehistoricSeenFlyer1();
+ void setPrehistoricSeenFlyer2(bool);
+ bool getPrehistoricSeenFlyer2();
+ void setPrehistoricSeenBridgeZoom(bool);
+ bool getPrehistoricSeenBridgeZoom();
+ void setPrehistoricBreakerThrown(bool);
+ bool getPrehistoricBreakerThrown();
+
+ // Norad
+ void setNoradSeenTimeStream(bool);
+ bool getNoradSeenTimeStream();
+ void setNoradGassed(bool);
+ bool getNoradGassed();
+ void setNoradFillingStationOn(bool);
+ bool getNoradFillingStationOn();
+ void setNoradN22MessagePlayed(bool);
+ bool getNoradN22MessagePlayed();
+ void setNoradPlayedGlobeGame(bool);
+ bool getNoradPlayedGlobeGame();
+ void setNoradBeatRobotWithClaw(bool);
+ bool getNoradBeatRobotWithClaw();
+ void setNoradBeatRobotWithDoor(bool);
+ bool getNoradBeatRobotWithDoor();
+ void setNoradRetScanGood(bool);
+ bool getNoradRetScanGood();
+ void setNoradWaitingForLaser(bool);
+ bool getNoradWaitingForLaser();
+ void setNoradSubRoomPressure(uint16);
+ uint16 getNoradSubRoomPressure();
+ void setNoradSubPrepState(NoradSubPrepState);
+ NoradSubPrepState getNoradSubPrepState();
+ void setNoradArrivedFromSub(bool);
+ bool getNoradArrivedFromSub();
+
+ // Mars
+ void setMarsSeenTimeStream(bool);
+ bool getMarsSeenTimeStream();
+ void setMarsHeardUpperPodMessage(bool);
+ bool getMarsHeardUpperPodMessage();
+ void setMarsRobotThrownPlayer(bool);
+ bool getMarsRobotThrownPlayer();
+ void setMarsHeardCheckInMessage(bool);
+ bool getMarsHeardCheckInMessage();
+ void setMarsPodAtUpperPlatform(bool);
+ bool getMarsPodAtUpperPlatform();
+ void setMarsSeenThermalScan(bool);
+ bool getMarsSeenThermalScan();
+ void setMarsArrivedBelow(bool);
+ bool getMarsArrivedBelow();
+ void setMarsSeenRobotAtReactor(bool);
+ bool getMarsSeenRobotAtReactor();
+ void setMarsAvoidedReactorRobot(bool);
+ bool getMarsAvoidedReactorRobot();
+ void setMarsInAirlock(bool);
+ bool getMarsInAirlock();
+ void setMarsAirlockOpen(bool);
+ bool getMarsAirlockOpen();
+ void setMarsMaskOnFiller(bool);
+ bool getMarsMaskOnFiller();
+ void setMarsLockFrozen(bool);
+ bool getMarsLockFrozen();
+ void setMarsLockBroken(bool);
+ bool getMarsLockBroken();
+ void setMarsMazeDoorPair1(bool);
+ bool getMarsMazeDoorPair1();
+ void setMarsMazeDoorPair2(bool);
+ bool getMarsMazeDoorPair2();
+ void setMarsMazeDoorPair3(bool);
+ bool getMarsMazeDoorPair3();
+ void setMarsSawRobotLeave(bool);
+ bool getMarsSawRobotLeave();
+ void setMarsSecurityDown(bool);
+ bool getMarsSecurityDown();
+ void setMarsFinishedCanyonChase(bool);
+ bool getMarsFinishedCanyonChase();
+ void setMarsThreadedMaze(bool);
+ bool getMarsThreadedMaze();
+ void setMarsHitRobotWithCannon(bool);
+ bool getMarsHitRobotWithCannon();
+ void setMarsReadyForShuttleTransport(bool);
+ bool getMarsReadyForShuttleTransport();
+
+ // WSC
+ void setWSCSeenTimeStream(bool);
+ bool getWSCSeenTimeStream();
+ void setWSCPoisoned(bool);
+ bool getWSCPoisoned();
+ void setWSCAnsweredAboutDart(bool);
+ bool getWSCAnsweredAboutDart();
+ void setWSCRemovedDart(bool);
+ bool getWSCRemovedDart();
+ void setWSCAnalyzerOn(bool);
+ bool getWSCAnalyzerOn();
+ void setWSCDartInAnalyzer(bool);
+ bool getWSCDartInAnalyzer();
+ void setWSCAnalyzedDart(bool);
+ bool getWSCAnalyzedDart();
+ void setWSCSawMorph(bool);
+ bool getWSCSawMorph();
+ void setWSCDesignedAntidote(bool);
+ bool getWSCDesignedAntidote();
+ void setWSCPickedUpAntidote(bool);
+ bool getWSCPickedUpAntidote();
+ void setWSCOfficeMessagesOpen(bool);
+ bool getWSCOfficeMessagesOpen();
+ void setWSCSeenNerd(bool);
+ bool getWSCSeenNerd();
+ void setWSCHeardPage1(bool);
+ bool getWSCHeardPage1();
+ void setWSCHeardPage2(bool);
+ bool getWSCHeardPage2();
+ void setWSCHeardCheckIn(bool);
+ bool getWSCHeardCheckIn();
+ void setWSCDidPlasmaDodge(bool);
+ bool getWSCDidPlasmaDodge();
+ void setWSCSeenSinclairLecture(bool);
+ bool getWSCSeenSinclairLecture();
+ void setWSCBeenAtWSC93(bool);
+ bool getWSCBeenAtWSC93();
+ void setWSCCatwalkDark(bool);
+ bool getWSCCatwalkDark();
+ void setWSCRobotDead(bool);
+ bool getWSCRobotDead();
+ void setWSCRobotGone(bool);
+ bool getWSCRobotGone();
+
+protected:
+ friend class Common::Singleton<SingletonBaseType>;
+
+private:
+ // Base
+ NeighborhoodID _currentNeighborhood;
+ RoomID _currentRoom;
+ DirectionConstant _currentDirection;
+ NeighborhoodID _nexNeighborhoodID;
+ RoomID _nextRoomID;
+ DirectionConstant _nextDirection;
+ NeighborhoodID _lastNeighborhood;
+ RoomID _lastRoom;
+ DirectionConstant _lastDirection;
+ RoomID _openDoorRoom;
+ DirectionConstant _openDoorDirection;
+
+ // Pegasus Prime
+ FlagsArray<byte, kNumGlobalFlags> _globalFlags;
+ FlagsArray<byte, kNumScoringFlags> _scoringFlags;
+ FlagsArray<uint32, kNumItems> _itemTakenFlags;
+
+ FlagsArray<byte, kNumCaldoriaFlags> _caldoriaFlags;
+ TimeValue _caldoriaFuseTimeLimit;
+
+ TimeValue _TSARipTimerTime;
+ TimeValue _TSAFuseTimeLimit;
+ byte _TSAState;
+ byte _T0BMonitorMode;
+ TimeValue _T0BMonitorStart;
+ FlagsArray<byte, kNumTSAFlags> _TSAFlags;
+
+ FlagsArray<byte, kNumPrehistoricFlags> _prehistoricFlags;
+
+ FlagsArray<byte, kNumNoradFlags> _noradFlags;
+ uint16 _noradSubRoomPressure;
+ NoradSubPrepState _noradSubPrepState;
+
+ FlagsArray<byte, kNumMarsFlags> _marsFlags;
+
+ FlagsArray<byte, kNumWSCFlags> _WSCFlags;
+};
+
+} // End of namespace Pegasus
+
+#define GameState (::Pegasus::GameStateManager::instance())
+
+#endif
diff --git a/engines/pegasus/graphics.cpp b/engines/pegasus/graphics.cpp
new file mode 100644
index 0000000000..8dbd678809
--- /dev/null
+++ b/engines/pegasus/graphics.cpp
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/events.h"
+#include "common/file.h"
+#include "common/textconsole.h"
+#include "engines/util.h"
+
+#include "pegasus/elements.h"
+#include "pegasus/graphics.h"
+#include "pegasus/transition.h"
+
+namespace Pegasus {
+
+GraphicsManager::GraphicsManager(PegasusEngine *vm) : _vm(vm) {
+ initGraphics(640, 480, true, NULL);
+
+ if (_vm->_system->getScreenFormat().bytesPerPixel == 1)
+ error("No true color mode available");
+
+ _backLayer = kMinAvailableOrder;
+ _frontLayer = kMaxAvailableOrder;
+ _firstDisplayElement = _lastDisplayElement = 0;
+ _workArea.create(640, 480, _vm->_system->getScreenFormat());
+ _modifiedScreen = false;
+ _curSurface = &_workArea;
+ _erase = false;
+ _updatesEnabled = true;
+ _screenFader = new ScreenFader();
+}
+
+GraphicsManager::~GraphicsManager() {
+ _workArea.free();
+ delete _screenFader;
+}
+
+void GraphicsManager::invalRect(const Common::Rect &rect) {
+ // We're using a simpler algorithm for dirty rect handling than the original
+ // The original was way too overcomplicated for what we need here now.
+
+ if (_dirtyRect.width() == 0 || _dirtyRect.height() == 0) {
+ // We have no dirty rect, so this is now our dirty rect
+ _dirtyRect = rect;
+ } else {
+ // Expand our dirty rect to include rect
+ _dirtyRect.extend(rect);
+ }
+
+ // Sanity check: clip our rect to the screen
+ _dirtyRect.right = MIN<int>(640, _dirtyRect.right);
+ _dirtyRect.bottom = MIN<int>(480, _dirtyRect.bottom);
+}
+
+void GraphicsManager::addDisplayElement(DisplayElement *newElement) {
+ newElement->_elementOrder = CLIP<int>(newElement->_elementOrder, kMinAvailableOrder, kMaxAvailableOrder);
+
+ if (_firstDisplayElement) {
+ DisplayElement *runner = _firstDisplayElement;
+ DisplayElement *lastRunner = 0;
+
+ // Search for first element whose display order is greater than
+ // the new element's and add the new element just before it.
+ while (runner) {
+ if (newElement->_elementOrder < runner->_elementOrder) {
+ if (lastRunner) {
+ lastRunner->_nextElement = newElement;
+ newElement->_nextElement = runner;
+ } else {
+ newElement->_nextElement = _firstDisplayElement;
+ _firstDisplayElement = newElement;
+ }
+ break;
+ }
+ lastRunner = runner;
+ runner = runner->_nextElement;
+ }
+
+ // If got here and runner == NULL, we ran through the whole list without
+ // inserting, so add at the end.
+ if (!runner) {
+ _lastDisplayElement->_nextElement = newElement;
+ _lastDisplayElement = newElement;
+ }
+ } else {
+ _firstDisplayElement = newElement;
+ _lastDisplayElement = newElement;
+ }
+
+ newElement->_elementIsDisplaying = true;
+}
+
+void GraphicsManager::removeDisplayElement(DisplayElement *oldElement) {
+ if (!_firstDisplayElement)
+ return;
+
+ if (oldElement == _firstDisplayElement) {
+ if (oldElement == _lastDisplayElement) {
+ _firstDisplayElement = 0;
+ _lastDisplayElement = 0;
+ } else {
+ _firstDisplayElement = oldElement->_nextElement;
+ }
+
+ invalRect(oldElement->_bounds);
+ } else {
+ // Scan list for element.
+ // If we get here, we know that the list has at least one item, and it
+ // is not the first item, so we can skip it.
+ DisplayElement *runner = _firstDisplayElement->_nextElement;
+ DisplayElement *lastRunner = _firstDisplayElement;
+
+ while (runner) {
+ if (runner == oldElement) {
+ lastRunner->_nextElement = runner->_nextElement;
+
+ if (oldElement == _lastDisplayElement)
+ _lastDisplayElement = lastRunner;
+
+ invalRect(oldElement->_bounds);
+ break;
+ }
+
+ lastRunner = runner;
+ runner = runner->_nextElement;
+ }
+ }
+
+ oldElement->_nextElement = 0;
+ oldElement->_elementIsDisplaying = false;
+}
+
+void GraphicsManager::updateDisplay() {
+ bool screenDirty = false;
+
+ if (!_dirtyRect.isEmpty()) {
+ // Fill the dirty area with black if erase mode is enabled
+ if (_erase)
+ _workArea.fillRect(_dirtyRect, _workArea.format.RGBToColor(0, 0, 0));
+
+ for (DisplayElement *runner = _firstDisplayElement; runner != 0; runner = runner->_nextElement) {
+ Common::Rect bounds;
+ runner->getBounds(bounds);
+
+ // TODO: Better logic; it does a bit more work than it probably needs to
+ // but it should work fine for now.
+ if (bounds.intersects(_dirtyRect) && runner->validToDraw(_backLayer, _frontLayer)) {
+ runner->draw(bounds);
+ screenDirty = true;
+ }
+ }
+
+ // Copy only the dirty rect to the screen
+ if (screenDirty)
+ g_system->copyRectToScreen((byte *)_workArea.getBasePtr(_dirtyRect.left, _dirtyRect.top), _workArea.pitch, _dirtyRect.left, _dirtyRect.top, _dirtyRect.width(), _dirtyRect.height());
+
+ // Clear the dirty rect
+ _dirtyRect = Common::Rect();
+ }
+
+ if (_updatesEnabled && (screenDirty || _modifiedScreen))
+ g_system->updateScreen();
+
+ _modifiedScreen = false;
+}
+
+void GraphicsManager::clearScreen() {
+ Graphics::Surface *screen = g_system->lockScreen();
+ screen->fillRect(Common::Rect(0, 0, 640, 480), g_system->getScreenFormat().RGBToColor(0, 0, 0));
+ g_system->unlockScreen();
+ _modifiedScreen = true;
+}
+
+DisplayElement *GraphicsManager::findDisplayElement(const DisplayElementID id) {
+ DisplayElement *runner = _firstDisplayElement;
+
+ while (runner) {
+ if (runner->getObjectID() == id)
+ return runner;
+ runner = runner->_nextElement;
+ }
+
+ return 0;
+}
+
+void GraphicsManager::doFadeOutSync(const TimeValue time, const TimeScale scale, bool isBlack) {
+ _updatesEnabled = false;
+ _screenFader->doFadeOutSync(time, scale, isBlack);
+}
+
+void GraphicsManager::doFadeInSync(const TimeValue time, const TimeScale scale, bool isBlack) {
+ _screenFader->doFadeInSync(time, scale, isBlack);
+ _updatesEnabled = true;
+}
+
+void GraphicsManager::markCursorAsDirty() {
+ _modifiedScreen = true;
+}
+
+void GraphicsManager::newShakePoint(int32 index1, int32 index2, int32 maxRadius) {
+ int32 index3 = (index1 + index2) >> 1;
+
+ if (maxRadius == 0) {
+ _shakeOffsets[index3].x = ((_shakeOffsets[index1].x + _shakeOffsets[index2].x) >> 1);
+ _shakeOffsets[index3].y = ((_shakeOffsets[index1].y + _shakeOffsets[index2].y) >> 1);
+ } else {
+ double angle = (int32)(_vm->getRandomNumber(360 - 1) * 3.1415926535 / 180);
+ int32 radius = maxRadius;
+ _shakeOffsets[index3].x = (int32)(((_shakeOffsets[index1].x + _shakeOffsets[index2].x) >> 1) +
+ cos(angle) / 2 * radius);
+ _shakeOffsets[index3].y = (int32)(((_shakeOffsets[index1].y + _shakeOffsets[index2].y) >> 1) +
+ sin(angle) * radius);
+ }
+
+ if (index1 < index3 - 1)
+ newShakePoint(index1, index3, maxRadius * 2 / 3);
+
+ if (index3 < index2 - 1)
+ newShakePoint(index3, index2, maxRadius * 2 / 3);
+}
+
+void GraphicsManager::shakeTheWorld(TimeValue duration, TimeScale scale) {
+ if (duration == 0 || scale == 0)
+ return;
+
+ _shakeOffsets[0].x = 0;
+ _shakeOffsets[0].y = 0;
+ _shakeOffsets[(kMaxShakeOffsets - 1) / 4].x = 0;
+ _shakeOffsets[(kMaxShakeOffsets - 1) / 4].y = 0;
+ _shakeOffsets[(kMaxShakeOffsets - 1) / 2].x = 0;
+ _shakeOffsets[(kMaxShakeOffsets - 1) / 2].y = 0;
+ _shakeOffsets[(kMaxShakeOffsets - 1) * 3 / 4].x = 0;
+ _shakeOffsets[(kMaxShakeOffsets - 1) * 3 / 4].y = 0;
+ _shakeOffsets[kMaxShakeOffsets - 1].x = 0;
+ _shakeOffsets[kMaxShakeOffsets - 1].y = 0;
+
+ newShakePoint(0, (kMaxShakeOffsets - 1) / 4, 8);
+ newShakePoint((kMaxShakeOffsets - 1) / 4, (kMaxShakeOffsets - 1) / 2, 6);
+ newShakePoint((kMaxShakeOffsets - 1) / 2, (kMaxShakeOffsets - 1) * 3 / 4, 4);
+ newShakePoint((kMaxShakeOffsets - 1) * 3 / 4, kMaxShakeOffsets - 1, 3);
+
+ Common::Point lastOffset(0, 0);
+
+ // Store the current screen for later use
+ Graphics::Surface oldScreen;
+ Graphics::Surface *curScreen = g_system->lockScreen();
+ oldScreen.copyFrom(*curScreen);
+ g_system->unlockScreen();
+
+ // Convert to millis
+ duration = duration * 1000 / scale;
+
+ uint32 startTime = g_system->getMillis();
+
+ while (g_system->getMillis() < startTime + duration) {
+ Common::Point thisOffset = _shakeOffsets[(g_system->getMillis() - startTime) * (kMaxShakeOffsets - 1) / duration];
+ if (thisOffset != lastOffset) {
+ // Fill the screen with black
+ Graphics::Surface *screen = g_system->lockScreen();
+ screen->fillRect(Common::Rect(0, 0, 640, 480), g_system->getScreenFormat().RGBToColor(0, 0, 0));
+ g_system->unlockScreen();
+
+ // Calculate the src/dst offsets and the width/height
+ int32 srcOffsetX, dstOffsetX, width;
+
+ if (thisOffset.x > 0) {
+ srcOffsetX = 0;
+ dstOffsetX = thisOffset.x;
+ width = 640 - dstOffsetX;
+ } else {
+ srcOffsetX = -thisOffset.x;
+ dstOffsetX = 0;
+ width = 640 - srcOffsetX;
+ }
+
+ int32 srcOffsetY, dstOffsetY, height;
+
+ if (thisOffset.y > 0) {
+ srcOffsetY = 0;
+ dstOffsetY = thisOffset.y;
+ height = 480 - dstOffsetY;
+ } else {
+ srcOffsetY = -thisOffset.y;
+ dstOffsetY = 0;
+ height = 480 - srcOffsetY;
+ }
+
+ // Now copy to the screen
+ g_system->copyRectToScreen((byte *)oldScreen.getBasePtr(srcOffsetX, srcOffsetY), oldScreen.pitch,
+ dstOffsetX, dstOffsetY, width, height);
+ g_system->updateScreen();
+
+ lastOffset = thisOffset;
+ }
+
+ g_system->delayMillis(10);
+ }
+
+ if (lastOffset.x != 0 || lastOffset.y != 0) {
+ g_system->copyRectToScreen((byte *)oldScreen.pixels, oldScreen.pitch, 0, 0, 640, 480);
+ g_system->updateScreen();
+ }
+
+ oldScreen.free();
+}
+
+void GraphicsManager::enableErase() {
+ _erase = true;
+}
+
+void GraphicsManager::disableErase() {
+ _erase = false;
+}
+
+void GraphicsManager::enableUpdates() {
+ _updatesEnabled = true;
+ _screenFader->setFaderValue(100);
+}
+
+void GraphicsManager::disableUpdates() {
+ _updatesEnabled = false;
+ _screenFader->setFaderValue(0);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/graphics.h b/engines/pegasus/graphics.h
new file mode 100644
index 0000000000..fcdf1c9e78
--- /dev/null
+++ b/engines/pegasus/graphics.h
@@ -0,0 +1,95 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_GRAPHICS_H
+#define PEGASUS_GRAPHICS_H
+
+#include "common/rect.h"
+#include "common/str.h"
+#include "common/system.h"
+#include "graphics/surface.h"
+
+#include "pegasus/constants.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/util.h"
+
+namespace Pegasus {
+
+class Cursor;
+class DisplayElement;
+class PegasusEngine;
+class ScreenFader;
+
+class GraphicsManager {
+friend class Cursor;
+public:
+ GraphicsManager(PegasusEngine *vm);
+ ~GraphicsManager();
+
+ void addDisplayElement(DisplayElement *element);
+ void removeDisplayElement(DisplayElement *element);
+ void invalRect(const Common::Rect &rect);
+ DisplayOrder getBackOfActiveLayer() const { return _backLayer; }
+ DisplayOrder getFrontOfActiveLayer() const { return _frontLayer; }
+ void updateDisplay();
+ Graphics::Surface *getCurSurface() { return _curSurface; }
+ void setCurSurface(Graphics::Surface *surface) { _curSurface = surface; }
+ Graphics::Surface *getWorkArea() { return &_workArea; }
+ void clearScreen();
+ DisplayElement *findDisplayElement(const DisplayElementID id);
+ void shakeTheWorld(TimeValue time, TimeScale scale);
+ void enableErase();
+ void disableErase();
+ void enableUpdates();
+ void disableUpdates();
+
+ // These default to black
+ void doFadeOutSync(const TimeValue = kOneSecondPerThirtyTicks, const TimeScale = kThirtyTicksPerSecond, bool isBlack = true);
+ void doFadeInSync(const TimeValue = kOneSecondPerThirtyTicks, const TimeScale = kThirtyTicksPerSecond, bool isBlack = true);
+
+protected:
+ void markCursorAsDirty();
+
+private:
+ PegasusEngine *_vm;
+
+ bool _modifiedScreen, _erase;
+ Common::Rect _dirtyRect;
+ DisplayOrder _backLayer, _frontLayer;
+ DisplayElement *_firstDisplayElement, *_lastDisplayElement;
+ Graphics::Surface _workArea, *_curSurface;
+
+ // Shake Shake Shake!
+ static const int kMaxShakeOffsets = 17;
+ Common::Point _shakeOffsets[kMaxShakeOffsets];
+ void newShakePoint(int32 index1, int32 index2, int32 maxRadius);
+
+ bool _updatesEnabled;
+ ScreenFader *_screenFader;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/hotspot.cpp b/engines/pegasus/hotspot.cpp
new file mode 100644
index 0000000000..d8b07a94f4
--- /dev/null
+++ b/engines/pegasus/hotspot.cpp
@@ -0,0 +1,325 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/stream.h"
+
+#include "pegasus/hotspot.h"
+
+namespace Pegasus {
+
+Region::Region(Common::ReadStream *stream) {
+ uint16 length = stream->readUint16BE();
+
+ assert(length >= 10);
+
+ _bounds.top = stream->readUint16BE();
+ _bounds.left = stream->readUint16BE();
+ _bounds.bottom = stream->readUint16BE();
+ _bounds.right = stream->readUint16BE();
+
+ _bounds.debugPrint(0, "Bounds:");
+
+ if (length == 10)
+ return;
+
+ length -= 10;
+
+ while (length > 0) {
+ Vector v;
+ v.y = stream->readUint16BE();
+ length -= 2;
+
+ if (v.y == 0x7fff)
+ break;
+
+ debug(0, "y: %d", v.y);
+
+ // Normalize y to _bounds
+ v.y -= _bounds.top;
+
+ while (length > 0) {
+ Run run;
+ run.start = stream->readUint16BE();
+ length -= 2;
+
+ if (run.start == 0x7fff)
+ break;
+
+ run.end = stream->readUint16BE();
+ length -= 2;
+
+ debug(0, "\t[%d, %d)", run.start, run.end);
+
+ // Normalize to _bounds
+ run.start -= _bounds.left;
+ run.end -= _bounds.left;
+
+ v.push_back(run);
+ }
+
+ _vectors.push_back(v);
+ }
+}
+
+Region::Region(const Common::Rect &rect) {
+ _bounds = rect;
+}
+
+bool Region::pointInRegion(const Common::Point &point) const {
+ if (!_bounds.contains(point))
+ return false;
+
+ bool pixelActive = false;
+
+ // Normalize the points to _bounds
+ uint16 x = point.x - _bounds.left;
+ uint16 y = point.y - _bounds.top;
+
+ for (Common::List<Vector>::const_iterator v = _vectors.begin(); v != _vectors.end(); v++) {
+ if (v->y > y)
+ return pixelActive;
+
+ for (Vector::const_iterator run = v->begin(); run != v->end(); run++) {
+ if (x >= run->start && x < run->end) {
+ pixelActive = !pixelActive;
+ break;
+ }
+ }
+ }
+
+ // the case if the region is just a rect
+ return true;
+}
+
+void Region::moveTo(CoordType h, CoordType v) {
+ _bounds.moveTo(h, v);
+}
+
+void Region::moveTo(const Common::Point &point) {
+ _bounds.moveTo(point);
+}
+
+void Region::translate(CoordType h, CoordType v) {
+ _bounds.translate(h, v);
+}
+
+void Region::translate(const Common::Point &point) {
+ _bounds.translate(point.x, point.y);
+}
+
+void Region::getCenter(CoordType &h, CoordType &v) const {
+ h = (_bounds.left + _bounds.right) / 2;
+ v = (_bounds.top + _bounds.bottom) / 2;
+}
+
+void Region::getCenter(Common::Point &point) const {
+ getCenter(point.x, point.y);
+}
+
+Hotspot::Hotspot(const HotSpotID id) : IDObject(id) {
+ _spotFlags = kNoHotSpotFlags;
+ _spotActive = false;
+}
+
+Hotspot::~Hotspot() {
+}
+
+void Hotspot::setArea(const Common::Rect &area) {
+ _spotArea = Region(area);
+}
+
+void Hotspot::setArea(const CoordType left, const CoordType top, const CoordType right, const CoordType bottom) {
+ _spotArea = Region(Common::Rect(left, top, right, bottom));
+}
+
+void Hotspot::getBoundingBox(Common::Rect &r) const {
+ r = _spotArea.getBoundingBox();
+}
+
+void Hotspot::getCenter(Common::Point &pt) const {
+ _spotArea.getCenter(pt);
+}
+
+void Hotspot::getCenter(CoordType &h, CoordType &v) const {
+ _spotArea.getCenter(h, v);
+}
+
+void Hotspot::setActive() {
+ _spotActive = true;
+}
+
+void Hotspot::setInactive() {
+ _spotActive = false;
+}
+
+void Hotspot::setHotspotFlags(const HotSpotFlags flags) {
+ _spotFlags = flags;
+}
+
+void Hotspot::setMaskedHotspotFlags(const HotSpotFlags flags, const HotSpotFlags mask) {
+ _spotFlags = (_spotFlags & ~mask) | flags;
+}
+
+bool Hotspot::isSpotActive() const {
+ return _spotActive;
+}
+
+void Hotspot::moveSpotTo(const CoordType h, const CoordType v) {
+ _spotArea.moveTo(h, v);
+}
+
+void Hotspot::moveSpotTo(const Common::Point pt) {
+ _spotArea.moveTo(pt);
+}
+
+void Hotspot::moveSpot(const CoordType h, const CoordType v) {
+ _spotArea.translate(h, v);
+}
+
+void Hotspot::moveSpot(const Common::Point pt) {
+ _spotArea.translate(pt.x, pt.y);
+}
+
+bool Hotspot::pointInSpot(const Common::Point where) const {
+ return _spotActive && _spotArea.pointInRegion(where);
+}
+
+HotSpotFlags Hotspot::getHotspotFlags() const {
+ return _spotFlags;
+}
+
+HotspotList::HotspotList() {
+}
+
+HotspotList::~HotspotList() {
+ // TODO: Should this call deleteHotspots()?
+}
+
+void HotspotList::deleteHotspots() {
+ for (HotspotIterator it = begin(); it != end(); it++)
+ delete *it;
+
+ clear();
+}
+
+Hotspot *HotspotList::findHotspot(const Common::Point where) {
+ for (HotspotIterator it = begin(); it != end(); it++)
+ if ((*it)->pointInSpot(where))
+ return *it;
+
+ return 0;
+}
+
+HotSpotID HotspotList::findHotspotID(const Common::Point where) {
+ Hotspot *hotspot = findHotspot(where);
+ return hotspot ? hotspot->getObjectID() : kNoHotSpotID;
+}
+
+Hotspot *HotspotList::findHotspotByID(const HotSpotID id) {
+ for (HotspotIterator it = begin(); it != end(); it++)
+ if ((*it)->getObjectID() == id)
+ return *it;
+
+ return 0;
+}
+
+Hotspot *HotspotList::findHotspotByMask(const HotSpotFlags flags) {
+ for (HotspotIterator it = begin(); it != end(); it++)
+ if (((*it)->getHotspotFlags() & flags) == flags)
+ return *it;
+
+ return 0;
+}
+
+void HotspotList::activateMaskedHotspots(const HotSpotFlags flags) {
+ for (HotspotIterator it = begin(); it != end(); it++)
+ if (flags == kNoHotSpotFlags || ((*it)->getHotspotFlags() & flags) != 0)
+ (*it)->setActive();
+}
+
+void HotspotList::deactivateAllHotspots() {
+ for (HotspotIterator it = begin(); it != end(); it++)
+ (*it)->setInactive();
+}
+
+void HotspotList::deactivateMaskedHotspots(const HotSpotFlags flags) {
+ for (HotspotIterator it = begin(); it != end(); it++)
+ if (((*it)->getHotspotFlags() & flags) != 0)
+ (*it)->setInactive();
+}
+
+void HotspotList::activateOneHotspot(const HotSpotID id) {
+ for (HotspotIterator it = begin(); it != end(); it++) {
+ if ((*it)->getObjectID() == id) {
+ (*it)->setActive();
+ return;
+ }
+ }
+}
+
+void HotspotList::deactivateOneHotspot(const HotSpotID id) {
+ for (HotspotIterator it = begin(); it != end(); it++) {
+ if ((*it)->getObjectID() == id) {
+ (*it)->setInactive();
+ return;
+ }
+ }
+}
+
+void HotspotList::removeOneHotspot(const HotSpotID id) {
+ for (HotspotIterator it = begin(); it != end(); it++) {
+ if ((*it)->getObjectID() == id) {
+ erase(it);
+ return;
+ }
+ }
+}
+
+void HotspotList::removeMaskedHotspots(const HotSpotFlags flags) {
+ if (flags != kNoHotSpotFlags) {
+ for (HotspotIterator it = begin(); it != end(); ) {
+ if (((*it)->getHotspotFlags() & flags) != 0)
+ it = erase(it);
+ else
+ it++;
+ }
+ } else {
+ clear();
+ }
+}
+
+void HotspotList::setHotspotRect(const HotSpotID id, const Common::Rect &r) {
+ Hotspot *hotspot = findHotspotByID(id);
+ if (hotspot)
+ hotspot->setArea(r);
+}
+
+void HotspotList::getHotspotRect(const HotSpotID id, Common::Rect &r) {
+ Hotspot *hotspot = findHotspotByID(id);
+ if (hotspot)
+ hotspot->getBoundingBox(r);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/hotspot.h b/engines/pegasus/hotspot.h
new file mode 100644
index 0000000000..64d3fb19f9
--- /dev/null
+++ b/engines/pegasus/hotspot.h
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_HOTSPOT_H
+#define PEGASUS_HOTSPOT_H
+
+#include "common/list.h"
+#include "common/rect.h"
+
+#include "pegasus/constants.h"
+#include "pegasus/types.h"
+#include "pegasus/util.h"
+
+/*
+
+ Hot spots combine a pixel area, an ID value and an active flag.
+
+ A point is considered in a hot spot if the point is in the hot spot's pixel area and
+ the active flag is set.
+
+ In addition, hot spots have a 32 bit word of bit flags for filtering use.
+
+*/
+
+namespace Common {
+ class ReadStream;
+}
+
+namespace Pegasus {
+
+// Our implementation of QuickDraw regions
+class Region {
+public:
+ Region() {}
+ Region(Common::ReadStream *stream);
+ Region(const Common::Rect &rect);
+
+ Common::Rect getBoundingBox() const { return _bounds; }
+
+ bool pointInRegion(const Common::Point &point) const;
+
+ void moveTo(CoordType h, CoordType v);
+ void moveTo(const Common::Point &point);
+ void translate(CoordType h, CoordType v);
+ void translate(const Common::Point &point);
+ void getCenter(CoordType &h, CoordType &v) const;
+ void getCenter(Common::Point &point) const;
+
+private:
+ Common::Rect _bounds;
+
+ struct Run {
+ uint16 start, end;
+ };
+
+ class Vector : public Common::List<Run> {
+ public:
+ uint16 y;
+ };
+
+ Common::List<Vector> _vectors;
+};
+
+class Hotspot : public IDObject {
+public:
+ Hotspot(const HotSpotID);
+ virtual ~Hotspot();
+
+ void setArea(const Region &region) { _spotArea = region; }
+ void setArea(const Common::Rect &);
+ void setArea(const CoordType, const CoordType, const CoordType, const CoordType);
+ void getBoundingBox(Common::Rect &) const;
+ void getArea(Region &) const;
+ void getCenter(Common::Point&) const;
+ void getCenter(CoordType&, CoordType&) const;
+
+ void moveSpotTo(const CoordType, const CoordType);
+ void moveSpotTo(const Common::Point);
+ void moveSpot(const CoordType, const CoordType);
+ void moveSpot(const Common::Point);
+
+ bool pointInSpot(const Common::Point) const;
+
+ void setActive();
+ void setInactive();
+ bool isSpotActive() const;
+
+ HotSpotFlags getHotspotFlags() const;
+ void setHotspotFlags(const HotSpotFlags);
+ void setMaskedHotspotFlags(const HotSpotFlags flags, const HotSpotFlags mask);
+
+protected:
+ Region _spotArea;
+ HotSpotFlags _spotFlags;
+ bool _spotActive;
+};
+
+class HotspotList : public Common::List<Hotspot *> {
+public:
+ HotspotList();
+ virtual ~HotspotList();
+
+ void deleteHotspots();
+
+ Hotspot *findHotspot(const Common::Point);
+ HotSpotID findHotspotID(const Common::Point);
+ Hotspot *findHotspotByID(const HotSpotID);
+ Hotspot *findHotspotByMask(const HotSpotFlags);
+
+ void activateMaskedHotspots(const HotSpotFlags = kNoHotSpotFlags);
+ void deactivateAllHotspots();
+ void deactivateMaskedHotspots(const HotSpotFlags);
+
+ void activateOneHotspot(const HotSpotID);
+ void deactivateOneHotspot(const HotSpotID);
+
+ void removeOneHotspot(const HotSpotID);
+ void removeMaskedHotspots(const HotSpotFlags = kNoHotSpotFlags);
+
+ void setHotspotRect(const HotSpotID, const Common::Rect&);
+ void getHotspotRect(const HotSpotID, Common::Rect&);
+};
+
+typedef HotspotList::iterator HotspotIterator;
+
+#define g_allHotspots (((PegasusEngine *)g_engine)->getAllHotspots())
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/input.cpp b/engines/pegasus/input.cpp
new file mode 100644
index 0000000000..b74e4a4c45
--- /dev/null
+++ b/engines/pegasus/input.cpp
@@ -0,0 +1,373 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/events.h"
+#include "common/system.h"
+
+#include "pegasus/cursor.h"
+#include "pegasus/input.h"
+#include "pegasus/pegasus.h"
+
+namespace Common {
+DECLARE_SINGLETON(Pegasus::InputDeviceManager);
+}
+
+namespace Pegasus {
+
+InputDeviceManager::InputDeviceManager() {
+ // Set all keys to "not down"
+ _keyMap[Common::KEYCODE_UP] = false;
+ _keyMap[Common::KEYCODE_KP8] = false;
+ _keyMap[Common::KEYCODE_LEFT] = false;
+ _keyMap[Common::KEYCODE_KP4] = false;
+ _keyMap[Common::KEYCODE_DOWN] = false;
+ _keyMap[Common::KEYCODE_KP5] = false;
+ _keyMap[Common::KEYCODE_RIGHT] = false;
+ _keyMap[Common::KEYCODE_KP6] = false;
+ _keyMap[Common::KEYCODE_RETURN] = false;
+ _keyMap[Common::KEYCODE_SPACE] = false;
+ _keyMap[Common::KEYCODE_t] = false;
+ _keyMap[Common::KEYCODE_KP_EQUALS] = false;
+ _keyMap[Common::KEYCODE_i] = false;
+ _keyMap[Common::KEYCODE_KP_DIVIDE] = false;
+ _keyMap[Common::KEYCODE_q] = false;
+ _keyMap[Common::KEYCODE_ESCAPE] = false;
+ _keyMap[Common::KEYCODE_p] = false;
+ _keyMap[Common::KEYCODE_TILDE] = false;
+ _keyMap[Common::KEYCODE_BACKQUOTE] = false;
+ _keyMap[Common::KEYCODE_NUMLOCK] = false;
+ _keyMap[Common::KEYCODE_BACKSPACE] = false;
+ _keyMap[Common::KEYCODE_KP_MULTIPLY] = false;
+ _keyMap[Common::KEYCODE_LALT] = false;
+ _keyMap[Common::KEYCODE_RALT] = false;
+ _keyMap[Common::KEYCODE_e] = false;
+ _keyMap[Common::KEYCODE_KP_ENTER] = false;
+
+ g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 2, false);
+ _lastRawBits = kAllUpBits;
+ _consoleRequested = false;
+}
+
+InputDeviceManager::~InputDeviceManager() {
+ g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this);
+}
+
+void InputDeviceManager::getInput(Input &input, const InputBits filter) {
+ // Poll for events, but ignore them!
+ // We'll pick them up in notifyEvent()
+ // We do that so that any pollEvent() call can update the variables
+ // (ie. if one uses enter to access the restore menu, we never receive
+ // the key up event, which leads to bad things)
+ // This is to closely emulate what the GetKeys() function did on Mac OS
+ Common::Event event;
+ while (g_system->getEventManager()->pollEvent(event))
+ ;
+
+ // Now create the bitfield
+ InputBits currentBits = 0;
+
+ if (_keyMap[Common::KEYCODE_UP] || _keyMap[Common::KEYCODE_KP8])
+ currentBits |= (kRawButtonDown << kUpButtonShift);
+
+ if (_keyMap[Common::KEYCODE_DOWN] || _keyMap[Common::KEYCODE_KP5])
+ currentBits |= (kRawButtonDown << kDownButtonShift);
+
+ if (_keyMap[Common::KEYCODE_LEFT] || _keyMap[Common::KEYCODE_KP4])
+ currentBits |= (kRawButtonDown << kLeftButtonShift);
+
+ if (_keyMap[Common::KEYCODE_RIGHT] || _keyMap[Common::KEYCODE_KP6])
+ currentBits |= (kRawButtonDown << kRightButtonShift);
+
+ if (_keyMap[Common::KEYCODE_SPACE] || _keyMap[Common::KEYCODE_RETURN] || _keyMap[Common::KEYCODE_KP_ENTER])
+ currentBits |= (kRawButtonDown << kTwoButtonShift);
+
+ if (_keyMap[Common::KEYCODE_t] || _keyMap[Common::KEYCODE_KP_EQUALS])
+ currentBits |= (kRawButtonDown << kThreeButtonShift);
+
+ if (_keyMap[Common::KEYCODE_i] || _keyMap[Common::KEYCODE_KP_DIVIDE])
+ currentBits |= (kRawButtonDown << kFourButtonShift);
+
+ if (_keyMap[Common::KEYCODE_q])
+ currentBits |= (kRawButtonDown << kMod1ButtonShift);
+
+ if (_keyMap[Common::KEYCODE_ESCAPE] || _keyMap[Common::KEYCODE_p])
+ currentBits |= (kRawButtonDown << kMod3ButtonShift);
+
+ if (_keyMap[Common::KEYCODE_TILDE] || _keyMap[Common::KEYCODE_BACKQUOTE] || _keyMap[Common::KEYCODE_NUMLOCK])
+ currentBits |= (kRawButtonDown << kLeftFireButtonShift);
+
+ if (_keyMap[Common::KEYCODE_BACKSPACE] || _keyMap[Common::KEYCODE_KP_MULTIPLY])
+ currentBits |= (kRawButtonDown << kRightFireButtonShift);
+
+ // Update mouse button state
+ // Note that we don't use EVENT_LBUTTONUP/EVENT_LBUTTONDOWN because
+ // they do not show if the button is being held down. We're treating
+ // both mouse buttons as the same for ease of use.
+ if (g_system->getEventManager()->getButtonState() != 0)
+ currentBits |= (kRawButtonDown << kTwoButtonShift);
+
+ // Update the mouse position too
+ input.setInputLocation(g_system->getEventManager()->getMousePos());
+
+ // Set the outgoing bits
+ InputBits filteredBits = currentBits & filter;
+ input.setInputBits((filteredBits & kAllButtonDownBits) | (filteredBits & _lastRawBits & kAllAutoBits));
+
+ // Update the last bits
+ _lastRawBits = currentBits;
+
+ // Set the console to be requested or not
+ input.setConsoleRequested(_consoleRequested);
+
+ // WORKAROUND: The original had this in currentBits, but then
+ // pressing alt would count as an event (and mess up someone
+ // trying to do alt+enter or something). Since it's only used
+ // as an easter egg, I'm just going to handle it as a separate
+ // bool value.
+ // WORKAROUND x2: I'm also accepting 'e' here since an
+ // alt+click is often intercepted by the OS. 'e' is used as the
+ // easter egg key in Buried in Time and Legacy of Time.
+ input.setAltDown(_keyMap[Common::KEYCODE_LALT] || _keyMap[Common::KEYCODE_RALT] || _keyMap[Common::KEYCODE_e]);
+}
+
+// Wait until the input device stops returning input allowed by filter...
+void InputDeviceManager::waitInput(const InputBits filter) {
+ if (filter != 0) {
+ for (;;) {
+ Input input;
+ getInput(input, filter);
+ if (!input.anyInput())
+ break;
+ }
+ }
+}
+
+bool InputDeviceManager::notifyEvent(const Common::Event &event) {
+ // We're mapping from ScummVM events to pegasus events, which
+ // are based on pippin events.
+ _consoleRequested = false;
+
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_d:
+ if (event.kbd.flags & Common::KBD_CTRL) // Console!
+ _consoleRequested = true;
+ break;
+ case Common::KEYCODE_s:
+ // We support meta where available and control elsewhere
+ if (event.kbd.flags & (Common::KBD_CTRL|Common::KBD_META))
+ ((PegasusEngine *)g_engine)->requestSave();
+ break;
+ case Common::KEYCODE_o: // o for open (original)
+ case Common::KEYCODE_l: // l for load (ScummVM terminology)
+ // We support meta where available and control elsewhere
+ if (event.kbd.flags & (Common::KBD_CTRL|Common::KBD_META))
+ ((PegasusEngine *)g_engine)->requestLoad();
+ break;
+ default:
+ // Otherwise, set the key to down if we have it
+ if (_keyMap.contains(event.kbd.keycode))
+ _keyMap[event.kbd.keycode] = true;
+ break;
+ }
+ break;
+ case Common::EVENT_KEYUP:
+ // Set the key to up if we have it
+ if (_keyMap.contains(event.kbd.keycode))
+ _keyMap[event.kbd.keycode] = false;
+ break;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+int operator==(const Input &arg1, const Input &arg2) {
+ return arg1._inputState == arg2._inputState;
+}
+
+int operator!=(const Input &arg1, const Input &arg2) {
+ return !operator==(arg1, arg2);
+}
+
+InputHandler *InputHandler::_inputHandler = 0;
+bool InputHandler::_invalHotspots = false;
+InputBits InputHandler::_lastFilter = kFilterNoInput;
+
+InputHandler *InputHandler::setInputHandler(InputHandler *currentHandler) {
+ InputHandler *result = 0;
+
+ if (_inputHandler != currentHandler && (!_inputHandler || _inputHandler->releaseInputFocus())) {
+ result = _inputHandler;
+ _inputHandler = currentHandler;
+ if (_inputHandler)
+ _inputHandler->grabInputFocus();
+ }
+
+ return result;
+}
+
+void InputHandler::pollForInput() {
+ if (_inputHandler) {
+ Input input;
+ Hotspot *cursorSpot = 0;
+
+ InputHandler::getInput(input, cursorSpot);
+ if (_inputHandler->isClickInput(input, cursorSpot))
+ _inputHandler->clickInHotspot(input, cursorSpot);
+ else
+ _inputHandler->handleInput(input, cursorSpot);
+ }
+}
+
+void InputHandler::getInput(Input &input, Hotspot *&cursorSpot) {
+ Cursor *cursor = ((PegasusEngine *)g_engine)->_cursor;
+
+ if (_inputHandler)
+ _lastFilter = _inputHandler->getInputFilter();
+ else
+ _lastFilter = kFilterAllInput;
+
+ InputDevice.getInput(input, _lastFilter);
+
+ if (_inputHandler && _inputHandler->wantsCursor() && (_lastFilter & _inputHandler->getClickFilter()) != 0) {
+ if (cursor->isVisible()) {
+ g_allHotspots.deactivateAllHotspots();
+ _inputHandler->activateHotspots();
+
+ Common::Point cursorLocation;
+ cursor->getCursorLocation(cursorLocation);
+ cursorSpot = g_allHotspots.findHotspot(cursorLocation);
+
+ if (_inputHandler)
+ _inputHandler->updateCursor(cursorLocation, cursorSpot);
+ } else {
+ cursor->hideUntilMoved();
+ }
+ } else {
+ cursor->hide();
+ }
+}
+
+void InputHandler::readInputDevice(Input &input) {
+ InputDevice.getInput(input, kFilterAllInput);
+}
+
+InputHandler::InputHandler(InputHandler *nextHandler) {
+ _nextHandler = nextHandler;
+ allowInput(true);
+}
+
+InputHandler::~InputHandler() {
+ if (_inputHandler == this)
+ setInputHandler(_nextHandler);
+}
+
+void InputHandler::handleInput(const Input &input, const Hotspot *cursorSpot) {
+ if (_nextHandler)
+ _nextHandler->handleInput(input, cursorSpot);
+}
+
+void InputHandler::clickInHotspot(const Input &input, const Hotspot *cursorSpot) {
+ if (_nextHandler)
+ _nextHandler->clickInHotspot(input, cursorSpot);
+}
+
+bool InputHandler::isClickInput(const Input &input, const Hotspot *cursorSpot) {
+ if (_nextHandler)
+ return _nextHandler->isClickInput(input, cursorSpot);
+
+ return false;
+}
+
+void InputHandler::activateHotspots() {
+ if (_nextHandler)
+ _nextHandler->activateHotspots();
+}
+
+InputBits InputHandler::getInputFilter() {
+ if (_allowInput) {
+ if (_nextHandler)
+ return _nextHandler->getInputFilter();
+ else
+ return kFilterAllInput;
+ }
+
+ return kFilterNoInput;
+}
+
+InputBits InputHandler::getClickFilter() {
+ if (_allowInput && _nextHandler)
+ return _nextHandler->getClickFilter();
+
+ return kFilterNoInput;
+}
+
+void InputHandler::updateCursor(const Common::Point cursorLocation, const Hotspot *cursorSpot) {
+ if (_nextHandler)
+ _nextHandler->updateCursor(cursorLocation, cursorSpot);
+}
+
+bool InputHandler::wantsCursor() {
+ if (_allowInput) {
+ if (_nextHandler)
+ return _nextHandler->wantsCursor();
+ else
+ return true;
+ }
+
+ return false;
+}
+
+Tracker *Tracker::_currentTracker = 0;
+
+void Tracker::handleInput(const Input &input, const Hotspot *) {
+ if (stopTrackingInput(input))
+ stopTracking(input);
+ else if (isTracking())
+ continueTracking(input);
+}
+
+void Tracker::startTracking(const Input &) {
+ if (!isTracking()) {
+ _savedHandler = InputHandler::setInputHandler(this);
+ _currentTracker = this;
+ }
+}
+
+void Tracker::stopTracking(const Input &) {
+ if (isTracking()) {
+ _currentTracker = NULL;
+ InputHandler::setInputHandler(_savedHandler);
+ }
+}
+
+bool Tracker::isClickInput(const Input &input, const Hotspot *hotspot) {
+ return !isTracking() && InputHandler::isClickInput(input, hotspot);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/input.h b/engines/pegasus/input.h
new file mode 100644
index 0000000000..3e938fa42a
--- /dev/null
+++ b/engines/pegasus/input.h
@@ -0,0 +1,500 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_INPUT_H
+#define PEGASUS_INPUT_H
+
+#include "common/events.h"
+#include "common/hashmap.h"
+#include "common/rect.h"
+#include "common/singleton.h"
+
+#include "pegasus/constants.h"
+#include "pegasus/types.h"
+
+namespace Pegasus {
+
+class Hotspot;
+class Input;
+
+class InputDeviceManager : public Common::Singleton<InputDeviceManager>, public Common::EventObserver {
+public:
+ InputDeviceManager();
+ ~InputDeviceManager();
+
+ bool notifyEvent(const Common::Event &event);
+
+ void getInput(Input &, const InputBits);
+
+ void waitInput(const InputBits);
+
+protected:
+ friend class Common::Singleton<SingletonBaseType>;
+
+ // Keep track of which keys are down (= true) or not
+ Common::HashMap<uint, bool> _keyMap;
+ InputBits _lastRawBits;
+ bool _consoleRequested;
+};
+
+enum {
+ kButtonDownBit = 0,
+ kAutoButtonBit = 1,
+ kBitsPerButton = 2,
+
+ kButtonDownMask = 1 << kButtonDownBit,
+ kAutoButtonMask = 1 << kAutoButtonBit,
+
+ kButtonStateBits = kButtonDownMask | kAutoButtonMask,
+
+ kRawButtonUp = 0,
+ kRawButtonDown = kButtonDownMask | kAutoButtonMask,
+
+ kButtonUp = 0,
+ kButtonDown = kButtonDownMask,
+ kButtonAutoUp = kAutoButtonMask,
+ kButtonAutoDown = kButtonDownMask | kAutoButtonMask
+};
+
+enum {
+ kUpButtonNum = 0,
+ kLeftButtonNum = 1,
+ kDownButtonNum = 2,
+ kRightButtonNum = 3,
+ kLeftFireButtonNum = 4,
+ kRightFireButtonNum = 5,
+ kOneButtonNum = 6,
+ kTwoButtonNum = 7,
+ kThreeButtonNum = 8,
+ kFourButtonNum = 9,
+ kMod1ButtonNum = 10,
+ kMod2ButtonNum = 11,
+ kMod3ButtonNum = 12
+};
+
+enum {
+ kUpButtonShift = kUpButtonNum * kBitsPerButton,
+ kLeftButtonShift = kLeftButtonNum * kBitsPerButton,
+ kDownButtonShift = kDownButtonNum * kBitsPerButton,
+ kRightButtonShift = kRightButtonNum * kBitsPerButton,
+ kLeftFireButtonShift = kLeftFireButtonNum * kBitsPerButton,
+ kRightFireButtonShift = kRightFireButtonNum * kBitsPerButton,
+ kOneButtonShift = kOneButtonNum * kBitsPerButton,
+ kTwoButtonShift = kTwoButtonNum * kBitsPerButton,
+ kThreeButtonShift = kThreeButtonNum * kBitsPerButton,
+ kFourButtonShift = kFourButtonNum * kBitsPerButton,
+ kMod1ButtonShift = kMod1ButtonNum * kBitsPerButton,
+ kMod2ButtonShift = kMod2ButtonNum * kBitsPerButton,
+ kMod3ButtonShift = kMod3ButtonNum * kBitsPerButton
+};
+
+enum {
+ kAllUpBits = (kButtonUp << kUpButtonShift) |
+ (kButtonUp << kLeftButtonShift) |
+ (kButtonUp << kDownButtonShift) |
+ (kButtonUp << kRightButtonShift) |
+ (kButtonUp << kLeftFireButtonShift) |
+ (kButtonUp << kRightFireButtonShift) |
+ (kButtonUp << kOneButtonShift) |
+ (kButtonUp << kTwoButtonShift) |
+ (kButtonUp << kThreeButtonShift) |
+ (kButtonUp << kFourButtonShift) |
+ (kButtonUp << kMod1ButtonShift) |
+ (kButtonUp << kMod2ButtonShift) |
+ (kButtonUp << kMod3ButtonShift),
+ kDirectionBits = (kButtonDownMask << kUpButtonShift) |
+ (kButtonDownMask << kLeftButtonShift) |
+ (kButtonDownMask << kDownButtonShift) |
+ (kButtonDownMask << kRightButtonShift),
+ kButtonBits = (kButtonDownMask << kLeftFireButtonShift) |
+ (kButtonDownMask << kRightFireButtonShift) |
+ (kButtonDownMask << kOneButtonShift) |
+ (kButtonDownMask << kTwoButtonShift) |
+ (kButtonDownMask << kThreeButtonShift) |
+ (kButtonDownMask << kFourButtonShift) |
+ (kButtonDownMask << kMod1ButtonShift) |
+ (kButtonDownMask << kMod2ButtonShift) |
+ (kButtonDownMask << kMod3ButtonShift),
+ kAllButtonDownBits = kDirectionBits | kButtonBits,
+ kAllAutoBits = (kAutoButtonMask << kUpButtonShift) |
+ (kAutoButtonMask << kLeftButtonShift) |
+ (kAutoButtonMask << kDownButtonShift) |
+ (kAutoButtonMask << kRightButtonShift) |
+ (kAutoButtonMask << kLeftFireButtonShift) |
+ (kAutoButtonMask << kRightFireButtonShift) |
+ (kAutoButtonMask << kOneButtonShift) |
+ (kAutoButtonMask << kTwoButtonShift) |
+ (kAutoButtonMask << kThreeButtonShift) |
+ (kAutoButtonMask << kFourButtonShift) |
+ (kAutoButtonMask << kMod1ButtonShift) |
+ (kAutoButtonMask << kMod2ButtonShift) |
+ (kAutoButtonMask << kMod3ButtonShift),
+
+ kFilterUpButton = kButtonDownMask << kUpButtonShift,
+ kFilterUpAuto = kAutoButtonMask << kUpButtonShift,
+ kFilterUpButtonAny = kFilterUpButton | kFilterUpAuto,
+ kFilterLeftButton = kButtonDownMask << kLeftButtonShift,
+ kFilterLeftAuto = kAutoButtonMask << kLeftButtonShift,
+ kFilterLeftButtonAny = kFilterLeftButton | kFilterLeftAuto,
+ kFilterDownButton = kButtonDownMask << kDownButtonShift,
+ kFilterDownAuto = kAutoButtonMask << kDownButtonShift,
+ kFilterDownButtonAny = kFilterDownButton | kFilterDownAuto,
+ kFilterRightButton = kButtonDownMask << kRightButtonShift,
+ kFilterRightAuto = kAutoButtonMask << kRightButtonShift,
+ kFilterRightButtonAny = kFilterRightButton | kFilterRightAuto,
+ kFilterLeftFireButton = kButtonDownMask << kLeftFireButtonShift,
+ kFilterLeftFireAuto = kAutoButtonMask << kLeftFireButtonShift,
+ kFilterLeftFireButtonAny = kFilterLeftFireButton | kFilterLeftFireAuto,
+ kFilterRightFireButton = kButtonDownMask << kRightFireButtonShift,
+ kFilterRightFireAuto = kAutoButtonMask << kRightFireButtonShift,
+ kFilterRightFireButtonAny = kFilterRightFireButton | kFilterRightFireAuto,
+ kFilterOneButton = kButtonDownMask << kOneButtonShift,
+ kFilterOneAuto = kAutoButtonMask << kOneButtonShift,
+ kFilterOneButtonAny = kFilterOneButton | kFilterOneAuto,
+ kFilterTwoButton = kButtonDownMask << kTwoButtonShift,
+ kFilterTwoAuto = kAutoButtonMask << kTwoButtonShift,
+ kFilterTwoButtonAny = kFilterTwoButton | kFilterTwoAuto,
+ kFilterThreeButton = kButtonDownMask << kThreeButtonShift,
+ kFilterThreeAuto = kAutoButtonMask << kThreeButtonShift,
+ kFilterThreeButtonAny = kFilterThreeButton | kFilterThreeAuto,
+ kFilterFourButton = kButtonDownMask << kFourButtonShift,
+ kFilterFourAuto = kAutoButtonMask << kFourButtonShift,
+ kFilterFourButtonAny = kFilterFourButton | kFilterFourAuto,
+ kFilterMod1Button = kButtonDownMask << kMod1ButtonShift,
+ kFilterMod1Auto = kAutoButtonMask << kMod1ButtonShift,
+ kFilterMod1ButtonAny = kFilterMod1Button | kFilterMod1Auto,
+ kFilterMod2Button = kButtonDownMask << kMod2ButtonShift,
+ kFilterMod2Auto = kAutoButtonMask << kMod2ButtonShift,
+ kFilterMod2ButtonAny = kFilterMod2Button | kFilterMod2Auto,
+ kFilterMod3Button = kButtonDownMask << kMod3ButtonShift,
+ kFilterMod3Auto = kAutoButtonMask << kMod3ButtonShift,
+ kFilterMod3ButtonAny = kFilterMod3Button | kFilterMod3Auto,
+
+ kFilterNoInput = 0,
+ kFilterAllInput = kFilterUpButton |
+ kFilterUpAuto |
+ kFilterLeftButton |
+ kFilterLeftAuto |
+ kFilterDownButton |
+ kFilterDownAuto |
+ kFilterRightButton |
+ kFilterRightAuto |
+ kFilterLeftFireButton |
+ kFilterLeftFireAuto |
+ kFilterRightFireButton |
+ kFilterRightFireAuto |
+ kFilterOneButton |
+ kFilterOneAuto |
+ kFilterTwoButton |
+ kFilterTwoAuto |
+ kFilterThreeButton |
+ kFilterThreeAuto |
+ kFilterFourButton |
+ kFilterFourAuto |
+ kFilterMod1Button |
+ kFilterMod1Auto |
+ kFilterMod2Button |
+ kFilterMod2Auto |
+ kFilterMod3Button |
+ kFilterMod3Auto,
+
+ kFilterAllDirections = kFilterUpButton |
+ kFilterUpAuto |
+ kFilterLeftButton |
+ kFilterLeftAuto |
+ kFilterDownButton |
+ kFilterDownAuto |
+ kFilterRightButton |
+ kFilterRightAuto,
+
+ kFilterButtons = kFilterOneButton |
+ kFilterOneAuto |
+ kFilterTwoButton |
+ kFilterTwoAuto |
+ kFilterThreeButton |
+ kFilterThreeAuto |
+ kFilterFourButton |
+ kFilterFourAuto,
+
+ kFilterFireButtons = kFilterLeftFireButton |
+ kFilterLeftFireAuto |
+ kFilterRightFireButton |
+ kFilterRightFireAuto,
+
+ kFilterAllButtons = kFilterLeftFireButton |
+ kFilterLeftFireAuto |
+ kFilterRightFireButton |
+ kFilterRightFireAuto |
+ kFilterOneButton |
+ kFilterOneAuto |
+ kFilterTwoButton |
+ kFilterTwoAuto |
+ kFilterThreeButton |
+ kFilterThreeAuto |
+ kFilterFourButton |
+ kFilterFourAuto |
+ kFilterMod1Button |
+ kFilterMod1Auto |
+ kFilterMod2Button |
+ kFilterMod2Auto |
+ kFilterMod3Button |
+ kFilterMod3Auto,
+
+ kFilterAllInputNoAuto = kFilterUpButton |
+ kFilterLeftButton |
+ kFilterDownButton |
+ kFilterRightButton |
+ kFilterLeftFireButton |
+ kFilterRightFireButton |
+ kFilterOneButton |
+ kFilterTwoButton |
+ kFilterThreeButton |
+ kFilterFourButton |
+ kFilterMod1Button |
+ kFilterMod2Button |
+ kFilterMod3Button
+};
+
+static const InputBits kHintInterruption = kFilterAllInputNoAuto;
+static const InputBits kWarningInterruption = kFilterNoInput;
+static const InputBits kOpticalInterruption = kFilterAllInputNoAuto;
+
+/*
+
+ Buttons are defined as:
+ up, left, down, right direction buttons.
+ fireLeft, fireRight: fire buttons.
+ mod1, mod2, mod3: modifier buttons, similar to shift, control, etc.
+ a, b, c, d: general purpose buttons.
+
+ button state is held as bits in a long word, two bits per button.
+
+ Filter bits:
+ for each button, two bits are assigned for filtering. If bit 0 is set, the
+ corresponding button is available for "button down" input. If bit 1 is set,
+ the corresponding button is available for "auto down" input. Note that bit
+ 1 is meaningful only if bit 0 is set.
+
+*/
+
+class Input {
+friend int operator==(const Input &, const Input &);
+friend int operator!=(const Input &, const Input &);
+friend class InputDeviceManager;
+
+public:
+ Input() { clearInput(); }
+
+ bool upButtonDown() const { return (_inputState & (kButtonStateBits << kUpButtonShift)) == (kButtonDown << kUpButtonShift); }
+ bool upButtonAutoDown() const { return (_inputState & (kButtonStateBits << kUpButtonShift)) == (kButtonAutoDown << kUpButtonShift); }
+ bool upButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kUpButtonShift)) != 0; }
+
+ bool leftButtonDown() const { return (_inputState & (kButtonStateBits << kLeftButtonShift)) == (kButtonDown << kLeftButtonShift); }
+ bool leftButtonAutoDown() const { return (_inputState & (kButtonStateBits << kLeftButtonShift)) == (kButtonAutoDown << kLeftButtonShift); }
+ bool leftButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kLeftButtonShift)) != 0; }
+
+ bool downButtonDown() const { return (_inputState & (kButtonStateBits << kDownButtonShift)) == (kButtonDown << kDownButtonShift); }
+ bool downButtonAutoDown() const { return (_inputState & (kButtonStateBits << kDownButtonShift)) == (kButtonAutoDown << kDownButtonShift); }
+ bool downButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kDownButtonShift)) != 0; }
+
+ bool rightButtonDown() const { return (_inputState & (kButtonStateBits << kRightButtonShift)) == (kButtonDown << kRightButtonShift); }
+ bool rightButtonAutoDown() const { return (_inputState & (kButtonStateBits << kRightButtonShift)) == (kButtonAutoDown << kRightButtonShift); }
+ bool rightButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kRightButtonShift)) != 0; }
+
+ bool leftFireButtonDown() const { return (_inputState & (kButtonStateBits << kLeftFireButtonShift)) == (kButtonDown << kLeftFireButtonShift); }
+ bool leftFireButtonAutoDown() const { return (_inputState & (kButtonStateBits << kLeftFireButtonShift)) == (kButtonAutoDown << kLeftFireButtonShift); }
+ bool leftFireButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kLeftFireButtonShift)) != 0; }
+
+ bool rightFireButtonDown() const { return (_inputState & (kButtonStateBits << kRightFireButtonShift)) == (kButtonDown << kRightFireButtonShift); }
+ bool rightFireButtonAutoDown() const { return (_inputState & (kButtonStateBits << kRightFireButtonShift)) == (kButtonAutoDown << kRightFireButtonShift); }
+ bool rightFireButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kRightFireButtonShift)) != 0; }
+
+ bool oneButtonDown() const { return (_inputState & (kButtonStateBits << kOneButtonShift)) == (kButtonDown << kOneButtonShift); }
+ bool oneButtonAutoDown() const { return (_inputState & (kButtonStateBits << kOneButtonShift)) == (kButtonAutoDown << kOneButtonShift); }
+ bool oneButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kOneButtonShift)) != 0; }
+
+ bool twoButtonDown() const { return (_inputState & (kButtonStateBits << kTwoButtonShift)) == (kButtonDown << kTwoButtonShift); }
+ bool twoButtonAutoDown() const { return (_inputState & (kButtonStateBits << kTwoButtonShift)) == (kButtonAutoDown << kTwoButtonShift); }
+ bool twoButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kTwoButtonShift)) != 0; }
+
+ bool threeButtonDown() const { return (_inputState & (kButtonStateBits << kThreeButtonShift)) == (kButtonDown << kThreeButtonShift); }
+ bool threeButtonAutoDown() const { return (_inputState & (kButtonStateBits << kThreeButtonShift)) == (kButtonAutoDown << kThreeButtonShift); }
+ bool threeButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kThreeButtonShift)) != 0; }
+
+ bool fourButtonDown() const { return (_inputState & (kButtonStateBits << kFourButtonShift)) == (kButtonDown << kFourButtonShift); }
+ bool fourButtonAutoDown() const { return (_inputState & (kButtonStateBits << kFourButtonShift)) == (kButtonAutoDown << kFourButtonShift); }
+ bool fourButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kFourButtonShift)) != 0; }
+
+ bool mod1ButtonDown() const { return (_inputState & (kButtonStateBits << kMod1ButtonShift)) == (kButtonDown << kMod1ButtonShift); }
+ bool mod1ButtonAutoDown() const { return (_inputState & (kButtonStateBits << kMod1ButtonShift)) == (kButtonAutoDown << kMod1ButtonShift); }
+ bool mod1ButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kMod1ButtonShift)) != 0; }
+
+ bool mod2ButtonDown() const { return (_inputState & (kButtonStateBits << kMod2ButtonShift)) == (kButtonDown << kMod2ButtonShift); }
+ bool mod2ButtonAutoDown() const { return (_inputState & (kButtonStateBits << kMod2ButtonShift)) == (kButtonAutoDown << kMod2ButtonShift); }
+ bool mod2ButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kMod2ButtonShift)) != 0; }
+
+ bool mod3ButtonDown() const { return (_inputState & (kButtonStateBits << kMod3ButtonShift)) == (kButtonDown << kMod3ButtonShift); }
+ bool mod3ButtonAutoDown() const { return (_inputState & (kButtonStateBits << kMod3ButtonShift)) == (kButtonAutoDown << kMod3ButtonShift); }
+ bool mod3ButtonAnyDown() const { return (_inputState & (kButtonAutoDown << kMod3ButtonShift)) != 0; }
+
+ bool allAutoInput() const { return (_inputState & kAllAutoBits) != 0; }
+ bool anyDirectionInput() const { return (_inputState & kDirectionBits) != 0; }
+ bool anyButtonInput() const { return (_inputState & kButtonBits) != 0; }
+ bool anyInput() const { return _inputState != 0; }
+
+ void getInputLocation(Common::Point &where) const { where = _inputLocation; }
+
+ bool anyInputBitSet(const InputBits bits) const { return (_inputState & bits) != 0; }
+
+ bool isAltDown() const { return _altDown; }
+ bool isConsoleRequested() const { return _consoleRequested; }
+
+ void clearInput() {
+ _inputState = kAllUpBits;
+ _inputLocation.x = 0;
+ _inputLocation.y = 0;
+ _consoleRequested = false;
+ _altDown = false;
+ }
+
+protected:
+ void setInputBits(const InputBits state) { _inputState = state; }
+ void setInputLocation(const Common::Point &where) { _inputLocation = where; }
+ void setConsoleRequested(bool consoleRequested) { _consoleRequested = consoleRequested; }
+ void setAltDown(bool altDown) { _altDown = altDown; }
+
+ InputBits _inputState;
+ Common::Point _inputLocation;
+ bool _consoleRequested;
+ bool _altDown;
+};
+
+class InputHandler {
+public:
+ static InputHandler *setInputHandler(InputHandler*);
+ static InputHandler *getCurrentHandler() { return _inputHandler; }
+ static void pollForInput();
+ static void getInput(Input&, Hotspot*&);
+ static void readInputDevice(Input&);
+ static void invalHotspots() { _invalHotspots = true; }
+ static InputBits getCurrentFilter() { return _lastFilter; }
+
+ InputHandler(InputHandler*);
+ virtual ~InputHandler();
+
+ virtual void setNextHandler(InputHandler *nextHandler) { _nextHandler = nextHandler; }
+ virtual InputHandler *getNextHandler() { return _nextHandler; }
+
+ virtual void handleInput(const Input &, const Hotspot *);
+ virtual void clickInHotspot(const Input &, const Hotspot *);
+
+ virtual void activateHotspots();
+ virtual void updateCursor(const Common::Point, const Hotspot *);
+ virtual bool isClickInput(const Input &, const Hotspot *);
+ virtual bool wantsCursor();
+
+ virtual bool releaseInputFocus() { return true; }
+ virtual void grabInputFocus() {}
+
+ // This returns bits set for what kinds of input to accept.
+ virtual InputBits getInputFilter();
+
+ // This returns bits defining what input constitutes a "click."
+ virtual InputBits getClickFilter();
+
+ virtual void allowInput(const bool allow) { _allowInput = allow; }
+
+protected:
+ static InputHandler *_inputHandler;
+ static bool _invalHotspots;
+ static InputBits _lastFilter;
+
+ InputHandler *_nextHandler;
+ bool _allowInput;
+};
+
+
+/*
+
+ Tracker implements "dragging". A Tracker can receive a startTracking message,
+ which causes it to be the current tracker, as well as setting it up as the current
+ input handler. In addition, only one tracker can be tracking at a time, and no
+ other handler can be set up as the current handler until the track finishes. By
+ default, there is no next input handler for a Tracker, but this behavior can be
+ overridden if desired.
+
+*/
+
+class Tracker : public InputHandler {
+public:
+ Tracker() : InputHandler(0) {}
+ virtual ~Tracker() {}
+
+ virtual void handleInput(const Input &, const Hotspot *);
+ virtual bool stopTrackingInput(const Input &) { return false; }
+
+ virtual void startTracking(const Input &);
+ virtual void stopTracking(const Input &);
+ virtual void continueTracking(const Input &) {}
+
+ bool isTracking() { return this == _currentTracker; }
+ bool isClickInput(const Input &, const Hotspot *);
+
+ bool releaseInputFocus() { return !isTracking(); }
+
+protected:
+ static Tracker *_currentTracker;
+
+ InputHandler *_savedHandler;
+};
+
+class JMPPPInput {
+public:
+ static bool isMenuButtonPressInput(const Input &input) { return input.twoButtonDown(); }
+
+ static InputBits getClickInputFilter() { return kFilterTwoButton; }
+ static bool isClickInput(const Input &input) { return input.twoButtonDown(); }
+ static bool isDraggingInput(const Input &input) { return input.twoButtonAnyDown(); }
+ static bool isPressingInput(const Input &input) { return input.twoButtonAnyDown(); }
+
+ static bool isRaiseInventoryInput(const Input &input) { return input.leftFireButtonDown(); }
+ static bool isRaiseBiochipsInput(const Input &input) { return input.rightFireButtonDown(); }
+ static InputBits getItemPanelsInputFilter() { return kFilterLeftFireButton | kFilterRightFireButton; }
+
+ static bool isToggleAIMiddleInput(const Input &input) { return input.threeButtonDown(); }
+
+ static bool isToggleInfoInput(const Input &input) { return input.fourButtonDown(); }
+
+ // Hmmmmm....
+ static bool isEasterEggModifierInput(const Input &input) { return input.isAltDown(); }
+
+ static bool isTogglePauseInput(const Input &input) { return input.mod3ButtonDown(); }
+};
+
+} // End of namespace Pegasus
+
+#define InputDevice (::Pegasus::InputDeviceManager::instance())
+
+#endif
diff --git a/engines/pegasus/interaction.h b/engines/pegasus/interaction.h
new file mode 100644
index 0000000000..293ee6be83
--- /dev/null
+++ b/engines/pegasus/interaction.h
@@ -0,0 +1,110 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_INTERACTION_H
+#define PEGASUS_INTERACTION_H
+
+#include "pegasus/input.h"
+#include "pegasus/util.h"
+
+namespace Pegasus {
+
+static const InteractionID kNoInteractionID = -1;
+
+class Neighborhood;
+
+class GameInteraction : public IDObject, public InputHandler {
+public:
+ GameInteraction(const InteractionID id, Neighborhood *nextHandler) : IDObject(id), InputHandler((InputHandler *)nextHandler) {
+ _isInteracting = false;
+ _savedHandler = 0;
+ _owner = nextHandler;
+ }
+
+ // If the interaction is open (_isInteracting == true), it's too late to do anything
+ // about it here.
+ virtual ~GameInteraction() {}
+
+ // startInteraction and stopInteraction are called by the outside world to
+ // start and stop the interaction sequence.
+ // isInteracting returns a bool indicating whether or not the interaction
+ // is going.
+ void startInteraction() {
+ if (!isInteracting()) {
+ openInteraction();
+ initInteraction();
+ _isInteracting = true;
+ _savedHandler = InputHandler::setInputHandler(this);
+ }
+ }
+ void stopInteraction() {
+ if (isInteracting()) {
+ closeInteraction();
+ _isInteracting = false;
+ if (InputHandler::_inputHandler == this)
+ InputHandler::setInputHandler(_savedHandler);
+ }
+ }
+ void startOverInteraction() {
+ if (isInteracting())
+ resetInteraction();
+ }
+ bool isInteracting() const { return _isInteracting; }
+ Neighborhood *getOwner() const { return _owner; }
+
+ virtual Common::String getBriefingMovie() { return ""; }
+ virtual Common::String getEnvScanMovie() { return ""; }
+ virtual long getNumHints() { return 0; }
+ virtual Common::String getHintMovie(uint) { return ""; }
+ virtual bool canSolve() { return false; }
+
+ virtual void setSoundFXLevel(const uint16) {}
+ virtual void setAmbienceLevel(const uint16) {}
+
+ virtual void doSolve() {}
+
+protected:
+ // Subclasses override openInteraction and closeInteraction to perform
+ // specific initialization and cleanup. Override resetInteraction to
+ // "start the interaction over." resetInteraction is called only when
+ // the interaction is already open.
+ // These functions are only called in pairs, never two opens or closes
+ // in a row.
+ virtual void openInteraction() {}
+ virtual void initInteraction() {}
+ virtual void closeInteraction() {}
+ virtual void resetInteraction() {}
+
+ InputHandler *_savedHandler;
+ Neighborhood *_owner;
+
+private:
+ // Private so that only StartInteraction and StopInteraction can touch it.
+ bool _isInteracting;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/interface.cpp b/engines/pegasus/interface.cpp
new file mode 100644
index 0000000000..d9d3865192
--- /dev/null
+++ b/engines/pegasus/interface.cpp
@@ -0,0 +1,667 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/compass.h"
+#include "pegasus/energymonitor.h"
+#include "pegasus/interface.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/biochips/biochipitem.h"
+#include "pegasus/items/inventory/inventoryitem.h"
+
+namespace Pegasus {
+
+Interface *g_interface = 0;
+
+Interface::Interface() : InputHandler(0), _interfaceNotification(kInterfaceNotificationID, (NotificationManager *)((PegasusEngine *)g_engine)),
+ _currentItemSpot(kCurrentItemSpotID), _currentBiochipSpot(kCurrentBiochipSpotID),
+ _background1(kInterface1ID), _background2(kInterface2ID), _background3(kInterface3ID),
+ _background4(kInterface4ID), _datePicture(kDateID), _inventoryPush(kInventoryPushID),
+ _inventoryLid(kInventoryLidID, kNoDisplayElement),
+ _inventoryPanel(kNoDisplayElement, (InputHandler *)((PegasusEngine *)g_engine), ((PegasusEngine *)g_engine)->getItemsInventory()),
+ _biochipPush(kBiochipPushID), _biochipLid(kBiochipLidID, kNoDisplayElement),
+ _biochipPanel(kNoDisplayElement, (InputHandler *)((PegasusEngine *)g_engine), ((PegasusEngine *)g_engine)->getBiochipsInventory()) {
+ g_energyMonitor = 0;
+ _previousHandler = 0;
+ _inventoryRaised = false;
+ _biochipRaised = false;
+ _playingEndMessage = false;
+ g_interface = this;
+}
+
+Interface::~Interface() {
+ throwAwayInterface();
+ g_interface = 0;
+}
+
+void Interface::throwAwayInterface() {
+ g_allHotspots.removeOneHotspot(kCurrentItemSpotID);
+ g_allHotspots.removeOneHotspot(kCurrentBiochipSpotID);
+
+ throwAwayBackground();
+ throwAwayDateMonitor();
+ throwAwayEnergyMonitor();
+ throwAwayAIArea();
+ throwAwayCompass();
+ throwAwayNotifications();
+ throwAwayInventoryPanel();
+ throwAwayBiochipPanel();
+}
+
+void Interface::validateBackground() {
+ if (!_background1.isSurfaceValid()) {
+ _background1.initFromPICTFile("Images/Interface/3DInterface Left");
+ _background2.initFromPICTFile("Images/Interface/3DInterface Top");
+ _background3.initFromPICTFile("Images/Interface/3DInterface Right");
+ _background4.initFromPICTFile("Images/Interface/3DInterface Bottom");
+
+ _background1.setDisplayOrder(kBackground1Order);
+ _background1.startDisplaying();
+ _background1.moveElementTo(kBackground1Left, kBackground1Top);
+
+ _background2.setDisplayOrder(kBackground2Order);
+ _background2.startDisplaying();
+ _background2.moveElementTo(kBackground2Left, kBackground2Top);
+
+ _background3.setDisplayOrder(kBackground2Order);
+ _background3.startDisplaying();
+ _background3.moveElementTo(kBackground3Left, kBackground3Top);
+
+ _background4.setDisplayOrder(kBackground4Order);
+ _background4.startDisplaying();
+ _background4.moveElementTo(kBackground4Left, kBackground4Top);
+
+ _background1.show();
+ _background2.show();
+ _background3.show();
+ _background4.show();
+ }
+}
+
+void Interface::throwAwayBackground() {
+ _background1.stopDisplaying();
+ _background1.deallocateSurface();
+ _background2.stopDisplaying();
+ _background2.deallocateSurface();
+ _background3.stopDisplaying();
+ _background3.deallocateSurface();
+ _background4.stopDisplaying();
+ _background4.deallocateSurface();
+}
+
+void Interface::validateDateMonitor() {
+ if (!_datePicture.isSurfaceValid()) {
+ _datePicture.setDisplayOrder(kDateOrder);
+ _datePicture.startDisplaying();
+ _datePicture.moveElementTo(kDateLeft, kDateTop);
+ _datePicture.show();
+ }
+}
+
+void Interface::throwAwayDateMonitor() {
+ _datePicture.stopDisplaying();
+ _datePicture.deallocateSurface();
+}
+
+void Interface::setDate(const uint16 dateResID) {
+ validateDateMonitor();
+ _datePicture.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, dateResID);
+ _datePicture.triggerRedraw();
+}
+
+void Interface::validateCompass() {
+ if (!g_compass) {
+ new Compass();
+ g_compass->initCompass();
+ g_compass->setDisplayOrder(kCompassOrder);
+ g_compass->startDisplaying();
+ g_compass->moveElementTo(kCompassLeft, kCompassTop);
+ g_compass->show();
+ }
+}
+
+void Interface::throwAwayCompass() {
+ delete g_compass;
+}
+
+void Interface::validateNotifications() {
+ _interfaceNotification.notifyMe(this, kInterfaceNotificationFlags, kInterfaceNotificationFlags);
+ _inventoryLidCallBack.setNotification(&_interfaceNotification);
+ _inventoryPushCallBack.setNotification(&_interfaceNotification);
+ _biochipLidCallBack.setNotification(&_interfaceNotification);
+ _biochipPushCallBack.setNotification(&_interfaceNotification);
+}
+
+void Interface::throwAwayNotifications() {
+ _interfaceNotification.cancelNotification(this);
+}
+
+void Interface::validateAIArea() {
+ if (!g_AIArea) {
+ new AIArea((InputHandler *)((PegasusEngine *)g_engine));
+ if (g_AIArea)
+ g_AIArea->initAIArea();
+ }
+}
+
+void Interface::throwAwayAIArea() {
+ delete g_AIArea;
+}
+
+void Interface::validateInventoryPanel() {
+ if (!_inventoryPanel.isSurfaceValid()) {
+ _inventoryPanel.initInventoryImage(&_inventoryPush);
+ _inventoryPanel.moveElementTo(kInventoryPushLeft, kInventoryPushTop);
+ _inventoryPush.setSlideDirection(kSlideUpMask);
+ _inventoryPush.setInAndOutElements(&_inventoryPanel, 0);
+ _inventoryPush.setDisplayOrder(kInventoryPushOrder);
+ _inventoryPush.startDisplaying();
+
+ _inventoryLid.useFileName("Images/Lids/Inventory Lid Sequence");
+ _inventoryLid.useTransparent(true);
+ _inventoryLid.openFrameSequence();
+ _inventoryLid.moveElementTo(kInventoryLidLeft, kInventoryLidTop);
+ _inventoryLid.setDisplayOrder(kInventoryLidOrder);
+ _inventoryLid.startDisplaying();
+
+ _inventoryPushCallBack.initCallBack(&_inventoryPush, kCallBackAtExtremes);
+ _inventoryLidCallBack.initCallBack(&_inventoryLid, kCallBackAtExtremes);
+
+ _inventoryUp = false;
+ _inventoryRaised = false;
+
+ Item *item = getCurrentInventoryItem();
+ if (item)
+ item->select();
+ }
+}
+
+void Interface::throwAwayInventoryPanel() {
+ _inventoryPanel.stopDisplaying();
+ _inventoryPanel.throwAwayInventoryImage();
+ _inventoryPush.stopDisplaying();
+ _inventoryLid.stopDisplaying();
+ _inventoryLid.closeFrameSequence();
+ _inventoryPushCallBack.releaseCallBack();
+ _inventoryLidCallBack.releaseCallBack();
+
+ Item *item = getCurrentInventoryItem();
+ if (item)
+ item->deselect();
+
+ _inventoryUp = false;
+ _inventoryRaised = false;
+}
+
+void Interface::validateBiochipPanel() {
+ if (!_biochipPanel.isSurfaceValid()) {
+ _biochipPanel.initInventoryImage(&_biochipPush);
+ _biochipPanel.moveElementTo(kBiochipPushLeft, kBiochipPushTop);
+ _biochipPush.setSlideDirection(kSlideUpMask);
+ _biochipPush.setInAndOutElements(&_biochipPanel, 0);
+ _biochipPush.setDisplayOrder(kBiochipPushOrder);
+ _biochipPush.startDisplaying();
+
+ _biochipLid.useFileName("Images/Lids/Biochip Lid Sequence");
+ _biochipLid.useTransparent(true);
+ _biochipLid.openFrameSequence();
+ _biochipLid.moveElementTo(kBiochipLidLeft, kBiochipLidTop);
+ _biochipLid.setDisplayOrder(kBiochipLidOrder);
+ _biochipLid.startDisplaying();
+
+ _biochipPushCallBack.initCallBack(&_biochipPush, kCallBackAtExtremes);
+ _biochipLidCallBack.initCallBack(&_biochipLid, kCallBackAtExtremes);
+
+ _biochipUp = false;
+ _biochipRaised = false;
+
+ Item *item = getCurrentBiochip();
+ if (item)
+ item->select();
+ }
+}
+
+void Interface::throwAwayBiochipPanel() {
+ _biochipPanel.stopDisplaying();
+ _biochipPanel.throwAwayInventoryImage();
+ _biochipPush.stopDisplaying();
+ _biochipLid.stopDisplaying();
+ _biochipLid.closeFrameSequence();
+ _biochipPushCallBack.releaseCallBack();
+ _biochipLidCallBack.releaseCallBack();
+
+ Item *item = getCurrentBiochip();
+ if (item)
+ item->deselect();
+
+ _biochipUp = false;
+ _biochipRaised = false;
+}
+
+void Interface::validateEnergyMonitor() {
+ if (!g_energyMonitor)
+ new EnergyMonitor();
+}
+
+void Interface::throwAwayEnergyMonitor() {
+ delete g_energyMonitor;
+}
+
+void Interface::createInterface() {
+ validateBackground();
+ validateDateMonitor();
+ validateCompass();
+ validateNotifications();
+ validateAIArea();
+ validateBiochipPanel();
+ validateInventoryPanel();
+ validateEnergyMonitor();
+
+ if (!g_allHotspots.findHotspotByID(kCurrentItemSpotID)) {
+ _currentItemSpot.setArea(Common::Rect(76, 334, 172, 430));
+ _currentItemSpot.setHotspotFlags(kShellSpotFlag);
+ _currentItemSpot.setActive();
+ g_allHotspots.push_back(&_currentItemSpot);
+ }
+
+ if (!g_allHotspots.findHotspotByID(kCurrentBiochipSpotID)) {
+ _currentBiochipSpot.setArea(Common::Rect(364, 334, 460, 430));
+ _currentBiochipSpot.setHotspotFlags(kShellSpotFlag);
+ _currentBiochipSpot.setActive();
+ g_allHotspots.push_back(&_currentBiochipSpot);
+ }
+}
+
+InventoryResult Interface::addInventoryItem(InventoryItem *item) {
+ return _inventoryPanel.addInventoryItem(item);
+}
+
+InventoryResult Interface::removeInventoryItem(InventoryItem *item) {
+ return _inventoryPanel.removeInventoryItem(item);
+}
+
+void Interface::removeAllItemsFromInventory() {
+ _inventoryPanel.removeAllItems();
+}
+
+InventoryItem *Interface::getCurrentInventoryItem() {
+ return (InventoryItem *)_inventoryPanel.getCurrentItem();
+}
+
+void Interface::setCurrentInventoryItem(InventoryItem *item) {
+ setCurrentInventoryItemID(item->getObjectID());
+}
+
+void Interface::setCurrentInventoryItemID(ItemID id) {
+ _inventoryPanel.setCurrentItemID(id);
+}
+
+InventoryResult Interface::addBiochip(BiochipItem *item) {
+ return _biochipPanel.addInventoryItem(item);
+}
+
+void Interface::removeAllItemsFromBiochips() {
+ _biochipPanel.removeAllItems();
+}
+
+BiochipItem *Interface::getCurrentBiochip() {
+ return (BiochipItem *)_biochipPanel.getCurrentItem();
+}
+
+void Interface::setCurrentBiochip(BiochipItem *item) {
+ setCurrentBiochipID(item->getObjectID());
+}
+
+void Interface::setCurrentBiochipID(ItemID id) {
+ _biochipPanel.setCurrentItemID(id);
+}
+
+void Interface::receiveNotification(Notification *notification, const NotificationFlags flags) {
+ if (notification == &_interfaceNotification) {
+ switch (flags) {
+ case kInventoryLidOpenFlag:
+ inventoryLidOpen(true);
+ break;
+ case kInventoryLidClosedFlag:
+ inventoryLidClosed();
+ break;
+ case kInventoryDrawerUpFlag:
+ inventoryDrawerUp();
+ break;
+ case kInventoryDrawerDownFlag:
+ inventoryDrawerDown(true);
+ break;
+ case kBiochipLidOpenFlag:
+ biochipLidOpen(true);
+ break;
+ case kBiochipLidClosedFlag:
+ biochipLidClosed();
+ break;
+ case kBiochipDrawerUpFlag:
+ biochipDrawerUp();
+ break;
+ case kBiochipDrawerDownFlag:
+ biochipDrawerDown(true);
+ break;
+ }
+ }
+}
+
+void Interface::raiseInventoryDrawer(const bool doCallBacks) {
+ if (!_biochipUp)
+ _previousHandler = InputHandler::getCurrentHandler();
+
+ InputHandler::setInputHandler(&_inventoryPanel);
+ _inventoryUp = true;
+ _inventoryPanel.activateInventoryPicture();
+
+ if (doCallBacks) {
+ _inventoryLidCallBack.setCallBackFlag(kInventoryLidOpenFlag);
+ _inventoryLidCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ }
+
+ _inventoryLid.show();
+ _inventoryPush.show();
+ _inventoryLid.start();
+}
+
+void Interface::playEndMessage() {
+ raiseInventoryDrawerForMessage();
+ _playingEndMessage = true;
+ _inventoryPanel.playEndMessage(&_inventoryPush);
+ lowerInventoryDrawerForMessage();
+ _playingEndMessage = false;
+}
+
+void Interface::raiseInventoryDrawerForMessage() {
+ _inventoryPanel.disableLooping();
+ raiseInventoryDrawerSync();
+}
+
+void Interface::lowerInventoryDrawerForMessage() {
+ lowerInventoryDrawerSync();
+}
+
+void Interface::inventoryLidOpen(const bool doCallBacks) {
+ _inventoryLid.stop();
+
+ if (doCallBacks) {
+ _inventoryPushCallBack.setCallBackFlag(kInventoryDrawerUpFlag);
+ _inventoryPushCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ }
+
+ FaderMoveSpec moveSpec;
+ moveSpec.makeTwoKnotFaderSpec(60, 0, 0, 15, 1000);
+ _inventoryPush.startFader(moveSpec);
+}
+
+void Interface::inventoryDrawerUp() {
+ _inventoryPush.stopFader();
+ _inventoryPanel.panelUp();
+ _inventoryRaised = true;
+}
+
+bool Interface::isInventoryUp() {
+ return _inventoryRaised;
+}
+
+bool Interface::isInventoryDown() {
+ return !_inventoryUp;
+}
+
+void Interface::lowerInventoryDrawer(const bool doCallBacks) {
+ if (_inventoryRaised) {
+ _inventoryRaised = false;
+
+ if (!_playingEndMessage)
+ _inventoryPanel.deactivateInventoryPicture();
+
+ if (doCallBacks) {
+ _inventoryPushCallBack.setCallBackFlag(kInventoryDrawerDownFlag);
+ _inventoryPushCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ }
+
+ FaderMoveSpec moveSpec;
+ moveSpec.makeTwoKnotFaderSpec(60, 0, 1000, 15, 0);
+ _inventoryPush.startFader(moveSpec);
+ }
+}
+
+void Interface::inventoryDrawerDown(const bool doCallBacks) {
+ _inventoryPush.stopFader();
+
+ if (doCallBacks) {
+ _inventoryLidCallBack.setCallBackFlag(kInventoryLidClosedFlag);
+ _inventoryLidCallBack.scheduleCallBack(kTriggerAtStart, 0, 0);
+ }
+
+ _inventoryLid.setRate(-1);
+}
+
+void Interface::inventoryLidClosed() {
+ _inventoryLid.stop();
+
+ if (!_biochipUp)
+ InputHandler::setInputHandler(_previousHandler);
+
+ _inventoryLid.hide();
+ _inventoryPush.hide();
+ _inventoryUp = false;
+}
+
+void Interface::raiseBiochipDrawer(const bool doCallBacks) {
+ if (!_inventoryUp)
+ _previousHandler = InputHandler::getCurrentHandler();
+
+ InputHandler::setInputHandler(&_biochipPanel);
+ _biochipUp = true;
+ _biochipPanel.activateInventoryPicture();
+
+ if (doCallBacks) {
+ _biochipLidCallBack.setCallBackFlag(kBiochipLidOpenFlag);
+ _biochipLidCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ }
+
+ _biochipLid.show();
+ _biochipPush.show();
+ _biochipLid.start();
+}
+
+void Interface::biochipLidOpen(const bool doCallBacks) {
+ _biochipLid.stop();
+
+ if (doCallBacks) {
+ _biochipPushCallBack.setCallBackFlag(kBiochipDrawerUpFlag);
+ _biochipPushCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ }
+
+ FaderMoveSpec moveSpec;
+ moveSpec.makeTwoKnotFaderSpec(60, 0, 0, 9, 1000);
+ _biochipPush.startFader(moveSpec);
+}
+
+void Interface::biochipDrawerUp() {
+ _biochipPush.stopFader();
+ _biochipPanel.panelUp();
+ _biochipRaised = true;
+}
+
+void Interface::lowerBiochipDrawer(const bool doCallBacks) {
+ if (_biochipRaised) {
+ _biochipRaised = false;
+ _biochipPanel.deactivateInventoryPicture();
+
+ if (doCallBacks) {
+ _biochipPushCallBack.setCallBackFlag(kBiochipDrawerDownFlag);
+ _biochipPushCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ }
+
+ FaderMoveSpec moveSpec;
+ moveSpec.makeTwoKnotFaderSpec(60, 0, 1000, 9, 0);
+ _biochipPush.startFader(moveSpec);
+ }
+}
+
+void Interface::biochipDrawerDown(const bool doCallBacks) {
+ _biochipPush.stopFader();
+
+ if (doCallBacks) {
+ _biochipLidCallBack.setCallBackFlag(kBiochipLidClosedFlag);
+ _biochipLidCallBack.scheduleCallBack(kTriggerAtStart, 0, 0);
+ }
+
+ _biochipLid.setRate(-1);
+}
+
+void Interface::biochipLidClosed() {
+ _biochipLid.stop();
+
+ if (!_inventoryUp)
+ InputHandler::setInputHandler(_previousHandler);
+
+ _biochipLid.hide();
+ _biochipPush.hide();
+ _biochipUp = false;
+}
+
+void Interface::calibrateCompass() {
+ uint32 currentValue = g_compass->getFaderValue();
+ FaderMoveSpec compassMove;
+ compassMove.makeTwoKnotFaderSpec(15, 0, currentValue, 30, currentValue + 360);
+
+ g_compass->startFader(compassMove);
+
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ while (g_compass->isFading()) {
+ vm->refreshDisplay();
+ g_system->delayMillis(10);
+ }
+
+ vm->refreshDisplay();
+ g_compass->setFaderValue(currentValue);
+}
+
+void Interface::calibrateEnergyBar() {
+ g_energyMonitor->calibrateEnergyBar();
+}
+
+void Interface::raiseInventoryDrawerSync() {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ raiseInventoryDrawer(false);
+
+ while (_inventoryLid.isRunning()) {
+ vm->checkCallBacks();
+ vm->refreshDisplay();
+ g_system->delayMillis(10);
+ }
+
+ vm->refreshDisplay();
+ inventoryLidOpen(false);
+
+ while (_inventoryPush.isFading()) {
+ vm->checkCallBacks();
+ vm->refreshDisplay();
+ g_system->delayMillis(10);
+ }
+
+ vm->refreshDisplay();
+ inventoryDrawerUp();
+}
+
+void Interface::lowerInventoryDrawerSync() {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ lowerInventoryDrawer(false);
+
+ while (_inventoryPush.isFading()) {
+ vm->checkCallBacks();
+ vm->refreshDisplay();
+ g_system->delayMillis(10);
+ }
+
+ vm->refreshDisplay();
+ inventoryDrawerDown(false);
+
+ while (_inventoryLid.isRunning()) {
+ vm->checkCallBacks();
+ vm->refreshDisplay();
+ g_system->delayMillis(10);
+ }
+
+ vm->refreshDisplay();
+ inventoryLidClosed();
+}
+
+void Interface::raiseBiochipDrawerSync() {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ raiseBiochipDrawer(false);
+
+ while (_biochipLid.isRunning()) {
+ vm->checkCallBacks();
+ vm->refreshDisplay();
+ g_system->delayMillis(10);
+ }
+
+ vm->refreshDisplay();
+ biochipLidOpen(false);
+
+ while (_biochipPush.isFading()) {
+ vm->checkCallBacks();
+ vm->refreshDisplay();
+ g_system->delayMillis(10);
+ }
+
+ vm->refreshDisplay();
+ biochipDrawerUp();
+}
+
+void Interface::lowerBiochipDrawerSync() {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ lowerBiochipDrawer(false);
+
+ while (_biochipPush.isFading()) {
+ vm->checkCallBacks();
+ vm->refreshDisplay();
+ g_system->delayMillis(10);
+ }
+
+ vm->refreshDisplay();
+ biochipDrawerDown(false);
+
+ while (_biochipLid.isRunning()) {
+ vm->checkCallBacks();
+ vm->refreshDisplay();
+ g_system->delayMillis(10);
+ }
+
+ vm->refreshDisplay();
+ biochipLidClosed();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/interface.h b/engines/pegasus/interface.h
new file mode 100644
index 0000000000..a65d9a595a
--- /dev/null
+++ b/engines/pegasus/interface.h
@@ -0,0 +1,148 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_INTERFACE_H
+#define PEGASUS_INTERFACE_H
+
+#include "pegasus/hotspot.h"
+#include "pegasus/input.h"
+#include "pegasus/notification.h"
+#include "pegasus/surface.h"
+#include "pegasus/transition.h"
+#include "pegasus/items/inventorypicture.h"
+
+namespace Pegasus {
+
+class BiochipItem;
+class InventoryItem;
+
+class Interface : public InputHandler, public NotificationReceiver {
+public:
+ Interface();
+ virtual ~Interface();
+
+ void createInterface();
+
+ // Recalibration functions...
+ void calibrateCompass();
+ void calibrateEnergyBar();
+ void raiseInventoryDrawerSync();
+ void lowerInventoryDrawerSync();
+ void raiseBiochipDrawerSync();
+ void lowerBiochipDrawerSync();
+
+ void raiseInventoryDrawer(const bool doCallBacks = true);
+ void raiseBiochipDrawer(const bool doCallBacks = true);
+ void lowerInventoryDrawer(const bool doCallBacks = true);
+ void lowerBiochipDrawer(const bool doCallBacks = true);
+
+ void raiseInventoryDrawerForMessage();
+ void lowerInventoryDrawerForMessage();
+ bool isInventoryUp();
+ bool isInventoryDown();
+
+ InventoryResult addInventoryItem(InventoryItem *);
+ InventoryResult removeInventoryItem(InventoryItem *);
+ void removeAllItemsFromInventory();
+ InventoryItem *getCurrentInventoryItem();
+ void setCurrentInventoryItem(InventoryItem *);
+ void setCurrentInventoryItemID(ItemID);
+ InventoryResult addBiochip(BiochipItem *);
+ void removeAllItemsFromBiochips();
+ BiochipItem *getCurrentBiochip();
+ void setCurrentBiochip(BiochipItem *);
+ void setCurrentBiochipID(ItemID);
+
+ void setDate(const uint16);
+
+ void playEndMessage();
+
+ void throwAwayInterface();
+
+protected:
+ void validateBackground();
+ void validateDateMonitor();
+ void validateCompass();
+ void validateNotifications();
+ void validateAIArea();
+ void validateInventoryPanel();
+ void validateBiochipPanel();
+ void validateEnergyMonitor();
+
+ void throwAwayBackground();
+ void throwAwayDateMonitor();
+ void throwAwayCompass();
+ void throwAwayNotifications();
+ void throwAwayAIArea();
+ void throwAwayInventoryPanel();
+ void throwAwayBiochipPanel();
+ void throwAwayEnergyMonitor();
+
+ void receiveNotification(Notification *, const NotificationFlags);
+ void inventoryLidOpen(const bool doCallBacks);
+ void inventoryLidClosed();
+ void inventoryDrawerUp();
+ void inventoryDrawerDown(const bool doCallBacks);
+ void biochipLidOpen(const bool doCallBacks);
+ void biochipLidClosed();
+ void biochipDrawerUp();
+ void biochipDrawerDown(const bool doCallBacks);
+
+ Picture _background1;
+ Picture _background2;
+ Picture _background3;
+ Picture _background4;
+
+ Picture _datePicture;
+
+ InputHandler *_previousHandler;
+
+ Push _inventoryPush;
+ SpriteSequence _inventoryLid;
+ NotificationCallBack _inventoryPushCallBack;
+ NotificationCallBack _inventoryLidCallBack;
+ InventoryItemsPicture _inventoryPanel;
+ bool _inventoryUp, _inventoryRaised;
+
+ Push _biochipPush;
+ SpriteSequence _biochipLid;
+ NotificationCallBack _biochipPushCallBack;
+ NotificationCallBack _biochipLidCallBack;
+ BiochipPicture _biochipPanel;
+ bool _biochipUp, _biochipRaised;
+
+ Hotspot _currentItemSpot;
+ Hotspot _currentBiochipSpot;
+
+ Notification _interfaceNotification;
+
+ bool _playingEndMessage;
+};
+
+extern Interface *g_interface;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/autodragger.cpp b/engines/pegasus/items/autodragger.cpp
new file mode 100644
index 0000000000..40bad14a89
--- /dev/null
+++ b/engines/pegasus/items/autodragger.cpp
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/elements.h"
+#include "pegasus/items/autodragger.h"
+
+namespace Pegasus {
+
+AutoDragger::AutoDragger() {
+ _draggingElement = NULL;
+ _lastTime = 0;
+ initCallBack(this, kCallBackAtExtremes);
+}
+
+void AutoDragger::autoDrag(DisplayElement *dragElement, const Common::Point &startPoint, const Common::Point &stopPoint,
+ TimeValue dragTime, TimeScale dragScale) {
+ _draggingElement = dragElement;
+
+ if (_draggingElement) {
+ _startLocation = startPoint;
+ _stopLocation = stopPoint;
+ _lastTime = 0;
+ _done = false;
+ _draggingElement->moveElementTo(_startLocation.x, _startLocation.y);
+ setScale(dragScale);
+ setSegment(0, dragTime);
+ setTime(0);
+ scheduleCallBack(kTriggerAtStop, 0, 0);
+ startIdling();
+ start();
+ } else {
+ stopDragging();
+ }
+}
+
+void AutoDragger::stopDragging() {
+ cancelCallBack();
+ stopIdling();
+ _draggingElement = 0;
+ _startLocation = Common::Point();
+ _stopLocation = Common::Point();
+ _lastTime = 0;
+ _done = true;
+}
+
+bool AutoDragger::isDragging() {
+ return isIdling();
+}
+
+void AutoDragger::useIdleTime() {
+ TimeValue thisTime = getTime();
+
+ if (thisTime != _lastTime) {
+ int32 offsetX = (_stopLocation.x - _startLocation.x) * (int32)thisTime / (int32)getDuration();
+ int32 offsetY = (_stopLocation.y - _startLocation.y) * (int32)thisTime / (int32)getDuration();
+ _draggingElement->moveElementTo(_startLocation.x + offsetX, _startLocation.y + offsetY);
+ _lastTime = thisTime;
+ }
+
+ if (_done)
+ stopDragging();
+}
+
+void AutoDragger::callBack() {
+ if (isIdling())
+ _done = true;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/autodragger.h b/engines/pegasus/items/autodragger.h
new file mode 100644
index 0000000000..6783fdf9a3
--- /dev/null
+++ b/engines/pegasus/items/autodragger.h
@@ -0,0 +1,57 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_ITEMS_AUTODRAGGER_H
+#define PEGASUS_ITEMS_AUTODRAGGER_H
+
+#include "pegasus/timers.h"
+
+namespace Pegasus {
+
+class DisplayElement;
+
+class AutoDragger : private Idler, private TimeBase, private TimeBaseCallBack {
+public:
+ AutoDragger();
+ virtual ~AutoDragger() {}
+
+ void autoDrag(DisplayElement *, const Common::Point &, const Common::Point &, TimeValue, TimeScale);
+ bool isDragging();
+ void stopDragging();
+
+protected:
+ void useIdleTime();
+ void callBack();
+
+ DisplayElement *_draggingElement;
+ Common::Point _startLocation, _stopLocation;
+ TimeValue _lastTime;
+ bool _done;
+};
+
+} // End of namespace Pegasus
+
+#endif
+
diff --git a/engines/pegasus/items/biochips/aichip.cpp b/engines/pegasus/items/biochips/aichip.cpp
new file mode 100644
index 0000000000..cbcfc363e8
--- /dev/null
+++ b/engines/pegasus/items/biochips/aichip.cpp
@@ -0,0 +1,279 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/energymonitor.h"
+#include "pegasus/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/biochips/aichip.h"
+#include "pegasus/neighborhood/neighborhood.h"
+
+namespace Pegasus {
+
+// indexed by [number of hints][number of solves (0, 1, or 2)][which button to highlight]
+static const ItemState s_highlightState[4][3][7] = {
+ {
+ {kAI000, -1, -1, -1, -1, kAI005, kAI006},
+ {kAI010, -1, -1, -1, -1, kAI015, kAI016},
+ {kAI020, -1, -1, -1, kAI024, -1, -1}
+ },
+ {
+ {kAI100, kAI101, -1, -1, -1, kAI105, kAI106},
+ {kAI110, kAI111, -1, -1, -1, kAI115, kAI116},
+ {kAI120, kAI121, -1, -1, kAI124, kAI125, kAI126}
+ },
+ {
+ {kAI200, kAI201, kAI202, -1, -1, kAI205, kAI206},
+ {kAI210, kAI211, kAI212, -1, -1, kAI215, kAI216},
+ {kAI220, kAI221, kAI222, -1, kAI224, kAI225, kAI226}
+ },
+ {
+ {kAI300, kAI301, kAI302, kAI303, -1, kAI305, kAI306},
+ {kAI310, kAI311, kAI312, kAI313, -1, kAI315, kAI316},
+ {kAI320, kAI321, kAI322, kAI323, kAI324, kAI325, kAI326}
+ }
+};
+
+AIChip *g_AIChip = 0;
+
+AIChip::AIChip(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
+ BiochipItem(id, neighborhood, room, direction), _briefingSpot(kAIBriefingSpotID), _scanSpot(kAIScanSpotID),
+ _hint1Spot(kAIHint1SpotID), _hint2Spot(kAIHint2SpotID), _hint3Spot(kAIHint3SpotID), _solveSpot(kAISolveSpotID) {
+ _briefingSpot.setArea(Common::Rect(kAIMiddleAreaLeft + 10, kAIMiddleAreaTop + 27, kAIMiddleAreaLeft + 10 + 81, kAIMiddleAreaTop + 27 + 31));
+ _briefingSpot.setHotspotFlags(kAIBiochipSpotFlag);
+ g_allHotspots.push_back(&_briefingSpot);
+
+ _scanSpot.setArea(Common::Rect(kAIMiddleAreaLeft + 100, kAIMiddleAreaTop + 27, kAIMiddleAreaLeft + 100 + 81, kAIMiddleAreaTop + 27 + 31));
+ _scanSpot.setHotspotFlags(kAIBiochipSpotFlag);
+ g_allHotspots.push_back(&_scanSpot);
+
+ _hint1Spot.setArea(Common::Rect(kAIMiddleAreaLeft + 70, kAIMiddleAreaTop + 67, kAIMiddleAreaLeft + 70 + 21, kAIMiddleAreaTop + 67 + 21));
+ _hint1Spot.setHotspotFlags(kAIBiochipSpotFlag);
+ g_allHotspots.push_back(&_hint1Spot);
+
+ _hint2Spot.setArea(Common::Rect(kAIMiddleAreaLeft + 91, kAIMiddleAreaTop + 67, kAIMiddleAreaLeft + 91 + 20, kAIMiddleAreaTop + 67 + 21));
+ _hint2Spot.setHotspotFlags(kAIBiochipSpotFlag);
+ g_allHotspots.push_back(&_hint2Spot);
+
+ _hint3Spot.setArea(Common::Rect(kAIMiddleAreaLeft + 111, kAIMiddleAreaTop + 67, kAIMiddleAreaLeft + 111 + 20, kAIMiddleAreaTop + 67 + 21));
+ _hint3Spot.setHotspotFlags(kAIBiochipSpotFlag);
+ g_allHotspots.push_back(&_hint3Spot);
+
+ _solveSpot.setArea(Common::Rect(kAIMiddleAreaLeft + 131, kAIMiddleAreaTop + 67, kAIMiddleAreaLeft + 131 + 50, kAIMiddleAreaTop + 67 + 21));
+ _solveSpot.setHotspotFlags(kAIBiochipSpotFlag);
+ g_allHotspots.push_back(&_solveSpot);
+
+ _playingMovie = false;
+ setItemState(kAI000);
+
+ g_AIChip = this;
+}
+
+AIChip::~AIChip() {
+ g_AIChip = NULL;
+
+ g_allHotspots.removeOneHotspot(kAIBriefingSpotID);
+ g_allHotspots.removeOneHotspot(kAIScanSpotID);
+ g_allHotspots.removeOneHotspot(kAIHint1SpotID);
+ g_allHotspots.removeOneHotspot(kAIHint2SpotID);
+ g_allHotspots.removeOneHotspot(kAIHint3SpotID);
+ g_allHotspots.removeOneHotspot(kAISolveSpotID);
+}
+
+void AIChip::select() {
+ BiochipItem::select();
+ setUpAIChip();
+}
+
+void AIChip::takeSharedArea() {
+ setUpAIChip();
+}
+
+void AIChip::setUpAIChip() {
+ if (!_playingMovie) {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ uint numSolves;
+ if (GameState.getWalkthroughMode()) {
+ if (vm->canSolve())
+ numSolves = 2;
+ else
+ numSolves = 1;
+ } else {
+ numSolves = 0;
+ }
+
+ setItemState(s_highlightState[vm->getNumHints()][numSolves][0]);
+ }
+}
+
+// Only does something when there are hints or solves available.
+void AIChip::setUpAIChipRude() {
+ if (!_playingMovie) {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ uint numSolves;
+ if (GameState.getWalkthroughMode()) {
+ if (vm->canSolve())
+ numSolves = 2;
+ else
+ numSolves = 1;
+ } else {
+ numSolves = 0;
+ }
+
+ uint numHints = vm->getNumHints();
+ if (numSolves == 2 || numHints != 0)
+ setItemState(s_highlightState[numHints][numSolves][0]);
+ }
+}
+
+void AIChip::activateAIHotspots() {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+ _briefingSpot.setActive();
+ _scanSpot.setActive();
+
+ switch (vm->getNumHints()) {
+ case 3:
+ _hint3Spot.setActive();
+ // fall through
+ case 2:
+ _hint2Spot.setActive();
+ // fall through
+ case 1:
+ _hint1Spot.setActive();
+ break;
+ }
+
+ if (GameState.getWalkthroughMode() && vm->canSolve())
+ _solveSpot.setActive();
+}
+
+void AIChip::showBriefingClicked() {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ _playingMovie = true;
+
+ uint numSolves;
+ if (GameState.getWalkthroughMode()) {
+ if (vm->canSolve())
+ numSolves = 2;
+ else
+ numSolves = 1;
+ } else {
+ numSolves = 0;
+ }
+
+ ItemState newState = s_highlightState[vm->getNumHints()][numSolves][kAIBriefingSpotID - kAIHint1SpotID + 1];
+ if (newState != -1)
+ setItemState(newState);
+}
+
+void AIChip::showEnvScanClicked() {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ _playingMovie = true;
+
+ uint numSolves;
+ if (GameState.getWalkthroughMode()) {
+ if (vm->canSolve())
+ numSolves = 2;
+ else
+ numSolves = 1;
+ } else {
+ numSolves = 0;
+ }
+
+ ItemState newState = s_highlightState[vm->getNumHints()][numSolves][kAIScanSpotID - kAIHint1SpotID + 1];
+
+ if (newState != -1)
+ setItemState(newState);
+}
+
+void AIChip::clearClicked() {
+ _playingMovie = false;
+ setUpAIChip();
+}
+
+void AIChip::clickInAIHotspot(HotSpotID id) {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ Common::String movieName;
+
+ switch (id) {
+ case kAIBriefingSpotID:
+ movieName = vm->getBriefingMovie();
+ break;
+ case kAIScanSpotID:
+ movieName = vm->getEnvScanMovie();
+ break;
+ case kAIHint1SpotID:
+ movieName = vm->getHintMovie(1);
+ break;
+ case kAIHint2SpotID:
+ movieName = vm->getHintMovie(2);
+ break;
+ case kAIHint3SpotID:
+ movieName = vm->getHintMovie(3);
+ break;
+ case kAISolveSpotID:
+ g_neighborhood->doSolve();
+ break;
+ }
+
+ ItemState state = getItemState();
+
+ if (!movieName.empty()) {
+ _playingMovie = true;
+
+ uint numSolves;
+ if (GameState.getWalkthroughMode()) {
+ if (vm->canSolve())
+ numSolves = 2;
+ else
+ numSolves = 1;
+ } else {
+ numSolves = 0;
+ }
+
+ ItemState newState = s_highlightState[vm->getNumHints()][numSolves][id - kAIHint1SpotID + 1];
+
+ if (newState != -1)
+ setItemState(newState);
+
+ if (g_AIArea) {
+ vm->prepareForAIHint(movieName);
+ g_AIArea->playAIMovie(kRightAreaSignature, movieName, false, kHintInterruption);
+ vm->cleanUpAfterAIHint(movieName);
+ }
+
+ if (newState != -1)
+ setItemState(state);
+
+ _playingMovie = false;
+ }
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/biochips/aichip.h b/engines/pegasus/items/biochips/aichip.h
new file mode 100644
index 0000000000..7a33953612
--- /dev/null
+++ b/engines/pegasus/items/biochips/aichip.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_ITEMS_BIOCHIPS_AICHIP_H
+#define PEGASUS_ITEMS_BIOCHIPS_AICHIP_H
+
+#include "pegasus/hotspot.h"
+#include "pegasus/items/biochips/biochipitem.h"
+
+namespace Pegasus {
+
+class AIChip : public BiochipItem {
+public:
+ AIChip(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+ virtual ~AIChip();
+
+ void select();
+
+ void setUpAIChip();
+
+ // Called to set up the AI chip when the AI chip is the current chip but does not
+ // own the center area.
+ void setUpAIChipRude();
+ void activateAIHotspots();
+ void clickInAIHotspot(HotSpotID);
+
+ void takeSharedArea();
+
+ void showBriefingClicked();
+ void showEnvScanClicked();
+ void clearClicked();
+
+protected:
+ Hotspot _briefingSpot;
+ Hotspot _scanSpot;
+ Hotspot _hint1Spot;
+ Hotspot _hint2Spot;
+ Hotspot _hint3Spot;
+ Hotspot _solveSpot;
+ bool _playingMovie;
+};
+
+extern AIChip *g_AIChip;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/biochips/biochipitem.cpp b/engines/pegasus/items/biochips/biochipitem.cpp
new file mode 100644
index 0000000000..5686948937
--- /dev/null
+++ b/engines/pegasus/items/biochips/biochipitem.cpp
@@ -0,0 +1,95 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/stream.h"
+
+#include "pegasus/pegasus.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/biochips/biochipitem.h"
+
+namespace Pegasus {
+
+BiochipItem::BiochipItem(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
+ Item(id, neighborhood, room, direction) {
+
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ Common::SeekableReadStream *biochipInfo = vm->_resFork->getResource(MKTAG('B', 'i', 'o', 'I'), kItemBaseResID + id);
+ if (biochipInfo) {
+ _biochipInfoPanelTime = biochipInfo->readUint32BE();
+ delete biochipInfo;
+ } else {
+ _biochipInfoPanelTime = 0;
+ }
+
+ Common::SeekableReadStream *rightInfo = vm->_resFork->getResource(MKTAG('R', 'g', 'h', 't'), kItemBaseResID + id);
+ if (!rightInfo)
+ error("Could not find right info for biochip %d", id);
+
+ _rightAreaInfo = readItemState(rightInfo);
+ delete rightInfo;
+
+ setItemState(kNormalItem);
+}
+
+BiochipItem::~BiochipItem() {
+ delete[] _rightAreaInfo.entries;
+}
+
+ItemType BiochipItem::getItemType() {
+ return kBiochipItemType;
+}
+
+TimeValue BiochipItem::getRightAreaTime() const {
+ if (!_rightAreaInfo.entries)
+ return 0xffffffff;
+
+ TimeValue time;
+ ItemState state;
+
+ findItemStateEntryByState(_rightAreaInfo, _itemState, time);
+ if (time == 0xffffffff)
+ getItemStateEntry(_rightAreaInfo, 0, state, time);
+
+ return time;
+}
+
+// Must affect images in right area.
+void BiochipItem::select() {
+ Item::select();
+
+ if (g_AIArea)
+ g_AIArea->setAIAreaToTime(kBiochipSignature, kRightAreaSignature, getRightAreaTime());
+}
+
+void BiochipItem::deselect() {
+ Item::deselect();
+
+ if (g_AIArea)
+ g_AIArea->setAIAreaToTime(kBiochipSignature, kRightAreaSignature, 0xffffffff);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/biochips/biochipitem.h b/engines/pegasus/items/biochips/biochipitem.h
new file mode 100644
index 0000000000..2039e80c6f
--- /dev/null
+++ b/engines/pegasus/items/biochips/biochipitem.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_ITEMS_BIOCHIPS_BIOCHIPITEM_H
+#define PEGASUS_ITEMS_BIOCHIPS_BIOCHIPITEM_H
+
+#include "pegasus/items/item.h"
+
+namespace Pegasus {
+
+class BiochipItem : public Item {
+public:
+ BiochipItem(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+ virtual ~BiochipItem();
+
+ virtual ItemType getItemType();
+
+ TimeValue getPanelTime() const { return _biochipInfoPanelTime; }
+ TimeValue getRightAreaTime() const;
+
+ // Must affect images in right area.
+ virtual void select();
+ virtual void deselect();
+
+protected:
+ TimeValue _biochipInfoPanelTime;
+ ItemStateInfo _rightAreaInfo;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/biochips/mapchip.cpp b/engines/pegasus/items/biochips/mapchip.cpp
new file mode 100644
index 0000000000..69050d5193
--- /dev/null
+++ b/engines/pegasus/items/biochips/mapchip.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/gamestate.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/biochips/mapchip.h"
+#include "pegasus/neighborhood/neighborhood.h"
+
+namespace Pegasus {
+
+MapChip *g_map = 0;
+
+MapChip::MapChip(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
+ BiochipItem(id, neighborhood, room, direction) {
+ g_map = this;
+ setItemState(kMapUnavailable);
+}
+
+MapChip::~MapChip() {
+ g_map = 0;
+}
+
+void MapChip::writeToStream(Common::WriteStream *stream) {
+ return _image.writeToStream(stream);
+}
+
+void MapChip::readFromStream(Common::ReadStream *stream) {
+ return _image.readFromStream(stream);
+}
+
+void MapChip::select() {
+ BiochipItem::select();
+ moveToMapLocation(GameState.getCurrentNeighborhood(), GameState.getCurrentRoom(), GameState.getCurrentDirection());
+ _image.show();
+}
+
+void MapChip::takeSharedArea() {
+ _image.show();
+}
+
+void MapChip::giveUpSharedArea() {
+ _image.hide();
+}
+
+void MapChip::deselect() {
+ BiochipItem::deselect();
+ _image.unloadImage();
+}
+
+void MapChip::moveToMapLocation(const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant dir) {
+ AirQuality airQuality;
+
+ if (g_neighborhood)
+ airQuality = g_neighborhood->getAirQuality(room);
+ else
+ airQuality = kAirQualityGood;
+
+ switch (neighborhood) {
+ case kMarsID:
+ if (airQuality == kAirQualityVacuum) {
+ if (room >= kMars35 && room <= kMars39) {
+ setItemState(kMapEngaged);
+ if (isSelected() && g_AIArea && g_AIArea->getMiddleAreaOwner() == kBiochipSignature)
+ _image.loadGearRoomIfNecessary();
+ } else {
+ setItemState(kMapEngaged);
+ if (isSelected() && g_AIArea && g_AIArea->getMiddleAreaOwner() == kBiochipSignature)
+ _image.loadMazeIfNecessary();
+ }
+
+ _image.moveToMapLocation(neighborhood, room, dir);
+ } else {
+ _image.unloadImage();
+ setItemState(kMapUnavailable);
+ }
+ break;
+ default:
+ _image.unloadImage();
+ setItemState(kMapUnavailable);
+ break;
+ }
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/biochips/mapchip.h b/engines/pegasus/items/biochips/mapchip.h
new file mode 100644
index 0000000000..6690090aa4
--- /dev/null
+++ b/engines/pegasus/items/biochips/mapchip.h
@@ -0,0 +1,64 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_ITEMS_BIOCHIPS_MAPCHIP_H
+#define PEGASUS_ITEMS_BIOCHIPS_MAPCHIP_H
+
+#include "pegasus/items/biochips/biochipitem.h"
+#include "pegasus/items/biochips/mapimage.h"
+
+namespace Common {
+ class ReadStream;
+ class WriteStream;
+}
+
+namespace Pegasus {
+
+class MapChip : public BiochipItem {
+public:
+ MapChip(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+ virtual ~MapChip();
+
+ void select();
+ void deselect();
+ void takeSharedArea();
+ void giveUpSharedArea();
+
+ void moveToMapLocation(const NeighborhoodID, const RoomID, const DirectionConstant);
+
+ void writeToStream(Common::WriteStream *);
+ void readFromStream(Common::ReadStream *);
+
+ bool beenToMaze() { return _image.anyFlagSet(); }
+
+protected:
+ MapImage _image;
+};
+
+extern MapChip *g_map;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/biochips/mapimage.cpp b/engines/pegasus/items/biochips/mapimage.cpp
new file mode 100644
index 0000000000..9f4170d063
--- /dev/null
+++ b/engines/pegasus/items/biochips/mapimage.cpp
@@ -0,0 +1,443 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/items/biochips/mapimage.h"
+
+namespace Pegasus {
+
+#define FLAG_TO_INDEX(flag) ((flag) >> 2)
+#define INDEX_TO_FLAG(index) ((index) << 2)
+
+#define ROOM_TO_INDEX(room) \
+ (((room) >= kMars35 && (room) <= kMars39) ? ((room) - kMars35) : \
+ (((room) == kMars60) ? (kMars39 - kMars35 + 1) : \
+ ((room) - kMarsMaze004 + kMars39 - kMars35 + 2)))
+
+#define INDEX_TO_ROOM(index) \
+ (((index) <= ROOM_TO_INDEX(kMars39)) ? \
+ (((index) - ROOM_TO_INDEX(kMars35)) + kMars35) : \
+ ((index) <= ROOM_TO_INDEX(kMars60,)) ? kMars60 : \
+ ((((index) - ROOM_TO_INDEX(kMarsMaze004))) + kMarsMaze004))
+
+#define ROOM_TO_FLAG(room, dir) (INDEX_TO_FLAG(ROOM_TO_INDEX(room)) | (dir))
+
+#define FLAG_TO_ROOM(flag) (INDEX_TO_ROOM(FLAG_TO_INDEX(flag)))
+
+#define FLAG_TO_DIRECTION(flag) ((flag) & 3)
+
+static const int kGearRoomFlagLow = ROOM_TO_FLAG(kMars35, kNorth);
+static const int kGearRoomFlagHigh = ROOM_TO_FLAG(kMars39, kWest);
+
+static const int kMazeFlagLow = ROOM_TO_FLAG(kMars60, kNorth);
+static const int kMazeFlagHigh = ROOM_TO_FLAG(kMarsMaze200, kWest);
+
+static const CoordType kGearRoomScreenOffsetX = 49;
+static const CoordType kGearRoomScreenOffsetY = 47;
+
+static const CoordType kGearRoomGridOriginX = 1;
+static const CoordType kGearRoomGridOriginY = 4;
+
+static const CoordType kMazeScreenOffsetX = 16;
+static const CoordType kMazeScreenOffsetY = 20;
+
+static const CoordType kMazeGridOriginX = 6;
+static const CoordType kMazeGridOriginY = 1;
+
+static const CoordType kGridWidth = 4;
+static const CoordType kGridHeight = 4;
+
+static const uint16 kMapOfMazePICTID = 906;
+static const uint16 kMapOfGearRoomPICTID = 907;
+
+static const int s_mapCoords[MapImage::kNumMappingRooms][2] = {
+ /* kMars35 */ { 0, 0 },
+ /* kMars36 */ { 1, 0 },
+ /* kMars37 */ { 2, 0 },
+ /* kMars38 */ { 3, 0 },
+ /* kMars39 */ { 4, 0 },
+ /* kMars60 */ { 19, 9 },
+ /* kMarsMaze004 */ { 18, 9 },
+ /* kMarsMaze005 */ { 18, 10 },
+ /* kMarsMaze006 */ { 17, 10 },
+ /* kMarsMaze007 */ { 16, 10 },
+ /* kMarsMaze008 */ { 15, 10 },
+ /* kMarsMaze009 */ { 14, 10 },
+ /* kMarsMaze010 */ { 14, 9 },
+ /* kMarsMaze011 */ { 14, 8 },
+ /* kMarsMaze012 */ { 14, 7 },
+ /* kMarsMaze015 */ { 16, 7 },
+ /* kMarsMaze016 */ { 14, 11 },
+ /* kMarsMaze017 */ { 14, 12 },
+ /* kMarsMaze018 */ { 15, 12 },
+ /* kMarsMaze019 */ { 16, 12 },
+ /* kMarsMaze020 */ { 16, 13 },
+ /* kMarsMaze021 */ { 16, 14 },
+ /* kMarsMaze022 */ { 16, 15 },
+ /* kMarsMaze023 */ { 17, 15 },
+ /* kMarsMaze024 */ { 18, 15 },
+ /* kMarsMaze025 */ { 18, 14 },
+ /* kMarsMaze026 */ { 18, 13 },
+ /* kMarsMaze027 */ { 18, 12 },
+ /* kMarsMaze028 */ { 18, 11 },
+ /* kMarsMaze031 */ { 19, 14 },
+ /* kMarsMaze032 */ { 20, 14 },
+ /* kMarsMaze033 */ { 20, 13 },
+ /* kMarsMaze034 */ { 20, 12 },
+ /* kMarsMaze035 */ { 20, 11 },
+ /* kMarsMaze036 */ { 21, 11 },
+ /* kMarsMaze037 */ { 15, 15 },
+ /* kMarsMaze038 */ { 14, 15 },
+ /* kMarsMaze039 */ { 13, 15 },
+ /* kMarsMaze042 */ { 10, 15 },
+ /* kMarsMaze043 */ { 9, 15 },
+ /* kMarsMaze044 */ { 8, 15 },
+ /* kMarsMaze045 */ { 7, 15 },
+ /* kMarsMaze046 */ { 6, 15 },
+ /* kMarsMaze047 */ { 5, 15 },
+ /* kMarsMaze049 */ { 13, 14 },
+ /* kMarsMaze050 */ { 12, 14 },
+ /* kMarsMaze051 */ { 11, 14 },
+ /* kMarsMaze052 */ { 10, 14 },
+ /* kMarsMaze053 */ { 10, 13 },
+ /* kMarsMaze054 */ { 9, 13 },
+ /* kMarsMaze055 */ { 8, 13 },
+ /* kMarsMaze056 */ { 8, 12 },
+ /* kMarsMaze057 */ { 7, 12 },
+ /* kMarsMaze058 */ { 12, 13 },
+ /* kMarsMaze059 */ { 12, 12 },
+ /* kMarsMaze060 */ { 12, 11 },
+ /* kMarsMaze061 */ { 12, 10 },
+ /* kMarsMaze063 */ { 12, 9 },
+ /* kMarsMaze064 */ { 12, 8 },
+ /* kMarsMaze065 */ { 12, 7 },
+ /* kMarsMaze066 */ { 13, 7 },
+ /* kMarsMaze067 */ { 15, 7 },
+ /* kMarsMaze068 */ { 17, 7 },
+ /* kMarsMaze069 */ { 18, 7 },
+ /* kMarsMaze070 */ { 19, 7 },
+ /* kMarsMaze071 */ { 20, 7 },
+ /* kMarsMaze072 */ { 20, 6 },
+ /* kMarsMaze074 */ { 20, 5 },
+ /* kMarsMaze076 */ { 20, 4 },
+ /* kMarsMaze078 */ { 20, 3 },
+ /* kMarsMaze079 */ { 20, 2 },
+ /* kMarsMaze081 */ { 20, 2 },
+ /* kMarsMaze083 */ { 20, 0 },
+ /* kMarsMaze084 */ { 19, 0 },
+ /* kMarsMaze085 */ { 18, 0 },
+ /* kMarsMaze086 */ { 17, 0 },
+ /* kMarsMaze087 */ { 16, 0 },
+ /* kMarsMaze088 */ { 15, 0 },
+ /* kMarsMaze089 */ { 14, 0 },
+ /* kMarsMaze090 */ { 13, 0 },
+ /* kMarsMaze091 */ { 12, 0 },
+ /* kMarsMaze092 */ { 11, 0 },
+ /* kMarsMaze093 */ { 10, 0 },
+ /* kMarsMaze098 */ { 10, 1 },
+ /* kMarsMaze099 */ { 8, 2 },
+ /* kMarsMaze100 */ { 9, 2 },
+ /* kMarsMaze101 */ { 10, 2 },
+ /* kMarsMaze104 */ { 13, 2 },
+ /* kMarsMaze105 */ { 13, 3 },
+ /* kMarsMaze106 */ { 13, 4 },
+ /* kMarsMaze107 */ { 13, 5 },
+ /* kMarsMaze108 */ { 14, 5 },
+ /* kMarsMaze111 */ { 15, 5 },
+ /* kMarsMaze113 */ { 16, 5 },
+ /* kMarsMaze114 */ { 17, 5 },
+ /* kMarsMaze115 */ { 18, 5 },
+ /* kMarsMaze116 */ { 18, 4 },
+ /* kMarsMaze117 */ { 18, 3 },
+ /* kMarsMaze118 */ { 19, 3 },
+ /* kMarsMaze119 */ { 18, 2 },
+ /* kMarsMaze120 */ { 17, 2 },
+ /* kMarsMaze121 */ { 16, 2 },
+ /* kMarsMaze122 */ { 15, 2 },
+ /* kMarsMaze123 */ { 15, 1 },
+ /* kMarsMaze124 */ { 12, 4 },
+ /* kMarsMaze125 */ { 11, 4 },
+ /* kMarsMaze126 */ { 10, 4 },
+ /* kMarsMaze127 */ { 10, 5 },
+ /* kMarsMaze128 */ { 10, 6 },
+ /* kMarsMaze129 */ { 9, 6 },
+ /* kMarsMaze130 */ { 8, 6 },
+ /* kMarsMaze131 */ { 7, 6 },
+ /* kMarsMaze132 */ { 7, 7 },
+ /* kMarsMaze133 */ { 7, 8 },
+ /* kMarsMaze136 */ { 7, 11 },
+ /* kMarsMaze137 */ { 6, 11 },
+ /* kMarsMaze138 */ { 5, 11 },
+ /* kMarsMaze139 */ { 5, 12 },
+ /* kMarsMaze140 */ { 4, 12 },
+ /* kMarsMaze141 */ { 5, 13 },
+ /* kMarsMaze142 */ { 5, 14 },
+ /* kMarsMaze143 */ { 4, 14 },
+ /* kMarsMaze144 */ { 3, 14 },
+ /* kMarsMaze145 */ { 3, 13 },
+ /* kMarsMaze146 */ { 2, 13 },
+ /* kMarsMaze147 */ { 1, 13 },
+ /* kMarsMaze148 */ { 1, 14 },
+ /* kMarsMaze149 */ { 1, 15 },
+ /* kMarsMaze152 */ { 1, 12 },
+ /* kMarsMaze153 */ { 1, 11 },
+ /* kMarsMaze154 */ { 1, 10 },
+ /* kMarsMaze155 */ { 1, 9 },
+ /* kMarsMaze156 */ { 1, 8 },
+ /* kMarsMaze157 */ { 2, 10 },
+ /* kMarsMaze159 */ { 2, 8 },
+ /* kMarsMaze160 */ { 2, 7 },
+ /* kMarsMaze161 */ { 2, 6 },
+ /* kMarsMaze162 */ { 3, 10 },
+ /* kMarsMaze163 */ { 3, 9 },
+ /* kMarsMaze164 */ { 3, 8 },
+ /* kMarsMaze165 */ { 4, 8 },
+ /* kMarsMaze166 */ { 5, 8 },
+ /* kMarsMaze167 */ { 6, 8 },
+ /* kMarsMaze168 */ { 3, 6 },
+ /* kMarsMaze169 */ { 4, 6 },
+ /* kMarsMaze170 */ { 5, 6 },
+ /* kMarsMaze171 */ { 5, 5 },
+ /* kMarsMaze172 */ { 5, 4 },
+ /* kMarsMaze173 */ { 4, 4 },
+ /* kMarsMaze174 */ { 3, 4 },
+ /* kMarsMaze175 */ { 3, 5 },
+ /* kMarsMaze177 */ { 8, 4 },
+ /* kMarsMaze178 */ { 8, 3 },
+ /* kMarsMaze179 */ { 7, 4 },
+ /* kMarsMaze180 */ { 6, 4 },
+ /* kMarsMaze181 */ { 6, 3 },
+ /* kMarsMaze182 */ { 6, 2 },
+ /* kMarsMaze183 */ { 6, 1 },
+ /* kMarsMaze184 */ { 6, 0 },
+ /* kMarsMaze187 */ { 3, 0 },
+ /* kMarsMaze188 */ { 2, 0 },
+ /* kMarsMaze189 */ { 1, 0 },
+ /* kMarsMaze190 */ { 1, 1 },
+ /* kMarsMaze191 */ { 1, 2 },
+ /* kMarsMaze192 */ { 5, 2 },
+ /* kMarsMaze193 */ { 4, 2 },
+ /* kMarsMaze194 */ { 3, 2 },
+ /* kMarsMaze195 */ { 3, 1 },
+ /* kMarsMaze198 */ { 1, 3 },
+ /* kMarsMaze199 */ { 1, 4 },
+ /* kMarsMaze200 */ { 0, 4 }
+};
+
+MapImage::MapImage() : DisplayElement(kNoDisplayElement) {
+ _whichArea = kMapNoArea;
+ setBounds(kAIMiddleAreaLeft, kAIMiddleAreaTop, kAIMiddleAreaLeft + kAIMiddleAreaWidth, kAIMiddleAreaTop + kAIMiddleAreaHeight);
+ setDisplayOrder(kAIMiddleAreaOrder + 10);
+ startDisplaying();
+
+ _darkGreen = g_system->getScreenFormat().RGBToColor(64, 150, 10);
+ _lightGreen = g_system->getScreenFormat().RGBToColor(102, 239, 0);
+}
+
+void MapImage::writeToStream(Common::WriteStream *stream) {
+ _mappedRooms.writeToStream(stream);
+}
+
+void MapImage::readFromStream(Common::ReadStream *stream) {
+ _mappedRooms.readFromStream(stream);
+}
+
+void MapImage::loadGearRoomIfNecessary() {
+ if (_whichArea != kMapGearRoom) {
+ _mapImage.getImageFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kMapOfGearRoomPICTID);
+
+ Common::Rect bounds;
+ _mapImage.getSurfaceBounds(bounds);
+ _mapMask.allocateSurface(bounds);
+ _whichArea = kMapGearRoom;
+
+ GraphicsManager *gfx = ((PegasusEngine *)g_engine)->_gfx;
+ gfx->setCurSurface(_mapMask.getSurface());
+
+ gfx->getCurSurface()->fillRect(bounds, g_system->getScreenFormat().RGBToColor(0xff, 0xff, 0xff));
+
+ for (int i = kGearRoomFlagLow; i <= kGearRoomFlagHigh; i++)
+ if (_mappedRooms.getFlag(i))
+ addFlagToMask(i);
+
+ gfx->setCurSurface(gfx->getWorkArea());
+ show();
+ }
+}
+
+void MapImage::loadMazeIfNecessary() {
+ if (_whichArea != kMapMaze) {
+ _mapImage.getImageFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kMapOfMazePICTID);
+
+ Common::Rect bounds;
+ _mapImage.getSurfaceBounds(bounds);
+ _mapMask.allocateSurface(bounds);
+ _whichArea = kMapMaze;
+
+ GraphicsManager *gfx = ((PegasusEngine *)g_engine)->_gfx;
+ gfx->setCurSurface(_mapMask.getSurface());
+
+ gfx->getCurSurface()->fillRect(bounds, g_system->getScreenFormat().RGBToColor(0xff, 0xff, 0xff));
+
+ for (int i = kMazeFlagLow; i <= kMazeFlagHigh; i++)
+ if (_mappedRooms.getFlag(i))
+ addFlagToMask(i);
+
+ gfx->setCurSurface(gfx->getWorkArea());
+ show();
+ }
+}
+
+void MapImage::unloadImage() {
+ _mapImage.deallocateSurface();
+ _mapMask.deallocateSurface();
+ hide();
+ _whichArea = kMapNoArea;
+}
+
+void MapImage::moveToMapLocation(const NeighborhoodID, const RoomID room, const DirectionConstant dir) {
+ GraphicsManager *gfx = ((PegasusEngine *)g_engine)->_gfx;
+
+ int flag = ROOM_TO_FLAG(room, dir);
+
+ if (!_mappedRooms.getFlag(flag)) {
+ _mappedRooms.setFlag(flag, true);
+
+ if (_mapMask.isSurfaceValid()) {
+ gfx->setCurSurface(_mapMask.getSurface());
+ addFlagToMask(flag);
+ gfx->setCurSurface(gfx->getWorkArea());
+ }
+ }
+
+ if (isDisplaying())
+ triggerRedraw();
+}
+
+void MapImage::addFlagToMask(const int flag) {
+ Common::Rect r1;
+ getRevealedRects(flag, r1);
+ ((PegasusEngine *)g_engine)->_gfx->getCurSurface()->fillRect(r1, g_system->getScreenFormat().RGBToColor(0, 0, 0));
+}
+
+// This function can even be sensitive to open doors.
+// clone2727 notices that it's not, though
+void MapImage::getRevealedRects(const uint32 flag, Common::Rect &r1) {
+ CoordType gridX, gridY;
+
+ switch (_whichArea) {
+ case kMapMaze:
+ gridX = kMazeGridOriginX;
+ gridY = kMazeGridOriginY;
+ break;
+ case kMapGearRoom:
+ gridX = kGearRoomGridOriginX;
+ gridY = kGearRoomGridOriginY;
+ break;
+ default:
+ return;
+ }
+
+ int index = FLAG_TO_INDEX(flag);
+ gridX += s_mapCoords[index][0] * kGridWidth;
+ gridY += s_mapCoords[index][1] * kGridHeight;
+
+ r1 = Common::Rect(gridX - 1, gridY - 1, gridX + kGridWidth + 1, gridY + kGridHeight + 1);
+}
+
+void MapImage::drawPlayer() {
+ Graphics::Surface *screen = ((PegasusEngine *)g_engine)->_gfx->getCurSurface();
+
+ CoordType gridX, gridY;
+
+ switch (_whichArea) {
+ case kMapMaze:
+ gridX = _bounds.left + kMazeScreenOffsetX + kMazeGridOriginX;
+ gridY = _bounds.top + kMazeScreenOffsetY + kMazeGridOriginY;
+ break;
+ case kMapGearRoom:
+ gridX = _bounds.left + kGearRoomScreenOffsetX + kGearRoomGridOriginX;
+ gridY = _bounds.top + kGearRoomScreenOffsetY + kGearRoomGridOriginY;
+ break;
+ default:
+ return;
+ }
+
+ int index = ROOM_TO_INDEX(GameState.getCurrentRoom());
+ gridX += s_mapCoords[index][0] * kGridWidth;
+ gridY += s_mapCoords[index][1] * kGridHeight;
+
+ // This was intended to make little arrows
+ switch (GameState.getCurrentDirection()) {
+ case kNorth:
+ screen->drawLine(gridX + 1, gridY, gridX + 2, gridY, _darkGreen);
+ screen->drawLine(gridX, gridY + 1, gridX + 3, gridY + 1, _darkGreen);
+ screen->drawLine(gridX + 1, gridY + 1, gridX + 2, gridY + 1, _lightGreen);
+ screen->drawLine(gridX, gridY + 2, gridX + 3, gridY + 2, _lightGreen);
+ break;
+ case kSouth:
+ screen->drawLine(gridX + 1, gridY + 3, gridX + 2, gridY + 3, _darkGreen);
+ screen->drawLine(gridX, gridY + 2, gridX + 3, gridY + 2, _darkGreen);
+ screen->drawLine(gridX + 1, gridY + 2, gridX + 2, gridY + 2, _lightGreen);
+ screen->drawLine(gridX, gridY + 1, gridX + 3, gridY + 1, _lightGreen);
+ break;
+ case kEast:
+ screen->drawLine(gridX + 3, gridY + 1, gridX + 3, gridY + 2, _darkGreen);
+ screen->drawLine(gridX + 2, gridY, gridX + 2, gridY + 3, _darkGreen);
+ screen->drawLine(gridX + 2, gridY + 1, gridX + 2, gridY + 2, _lightGreen);
+ screen->drawLine(gridX + 1, gridY, gridX + 1, gridY + 3, _lightGreen);
+ break;
+ case kWest:
+ screen->drawLine(gridX, gridY + 1, gridX, gridY + 2, _darkGreen);
+ screen->drawLine(gridX + 1, gridY, gridX + 1, gridY + 3, _darkGreen);
+ screen->drawLine(gridX + 1, gridY + 1, gridX + 1, gridY + 2, _lightGreen);
+ screen->drawLine(gridX + 2, gridY, gridX + 2, gridY + 3, _lightGreen);
+ break;
+ }
+}
+
+void MapImage::draw(const Common::Rect &) {
+ Common::Rect r1;
+ _mapImage.getSurfaceBounds(r1);
+
+ Common::Rect r2 = r1;
+ switch (_whichArea) {
+ case kMapMaze:
+ r2.moveTo(_bounds.left + kMazeScreenOffsetX, _bounds.top + kMazeScreenOffsetY);
+ break;
+ case kMapGearRoom:
+ r2.moveTo(_bounds.left + kGearRoomScreenOffsetX, _bounds.top + kGearRoomScreenOffsetY);
+ break;
+ default:
+ return;
+ }
+
+ _mapImage.copyToCurrentPortMasked(r1, r2, &_mapMask);
+
+ drawPlayer();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/biochips/mapimage.h b/engines/pegasus/items/biochips/mapimage.h
new file mode 100644
index 0000000000..49ad9945ee
--- /dev/null
+++ b/engines/pegasus/items/biochips/mapimage.h
@@ -0,0 +1,84 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_ITEMS_BIOCHIPS_MAPIMAGE_H
+#define PEGASUS_ITEMS_BIOCHIPS_MAPIMAGE_H
+
+#include "pegasus/elements.h"
+#include "pegasus/surface.h"
+#include "pegasus/util.h"
+#include "pegasus/neighborhood/mars/constants.h"
+
+namespace Common {
+ class ReadStream;
+ class WriteStream;
+}
+
+namespace Pegasus {
+
+class MapImage : public DisplayElement {
+public:
+ MapImage();
+ virtual ~MapImage() {}
+
+ void writeToStream(Common::WriteStream *);
+ void readFromStream(Common::ReadStream *);
+
+ void loadGearRoomIfNecessary();
+ void loadMazeIfNecessary();
+ void unloadImage();
+ void moveToMapLocation(const NeighborhoodID, const RoomID, const DirectionConstant);
+
+ void draw(const Common::Rect &);
+
+ bool anyFlagSet() { return _mappedRooms.anyFlagSet(); }
+
+ static const uint32 kNumMappingRooms = (kMars39 - kMars35 + 1) + (kMars60 - kMars60 + 1) +
+ (kMarsMaze200 - kMarsMaze004 + 1);
+ static const uint32 kNumMappingFlags = kNumMappingRooms * 4;
+
+protected:
+ enum MapArea {
+ kMapNoArea,
+ kMapMaze,
+ kMapGearRoom
+ };
+
+ void addFlagToMask(const int flag);
+ void getRevealedRects(const uint32, Common::Rect &);
+ void drawPlayer();
+
+ MapArea _whichArea;
+
+ FlagsArray<byte, kNumMappingFlags> _mappedRooms;
+
+ uint32 _darkGreen, _lightGreen;
+
+ Surface _mapImage, _mapMask;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/biochips/opticalchip.cpp b/engines/pegasus/items/biochips/opticalchip.cpp
new file mode 100644
index 0000000000..7b8858edae
--- /dev/null
+++ b/engines/pegasus/items/biochips/opticalchip.cpp
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/pegasus.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/biochips/opticalchip.h"
+
+namespace Pegasus {
+
+OpticalChip *g_opticalChip = 0;
+
+OpticalChip::OpticalChip(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
+ BiochipItem(id, neighborhood, room, direction), _ariesHotspot(kAriesSpotID), _mercuryHotspot(kMercurySpotID),
+ _poseidonHotspot(kPoseidonSpotID) {
+ _ariesHotspot.setArea(Common::Rect(kAIMiddleAreaLeft + 60, kAIMiddleAreaTop + 27, kAIMiddleAreaLeft + 60 + 121, kAIMiddleAreaTop + 27 + 20));
+ _ariesHotspot.setHotspotFlags(kOpticalBiochipSpotFlag);
+ g_allHotspots.push_back(&_ariesHotspot);
+
+ _mercuryHotspot.setArea(Common::Rect(kAIMiddleAreaLeft + 60, kAIMiddleAreaTop + 47, kAIMiddleAreaLeft + 60 + 121, kAIMiddleAreaTop + 47 + 20));
+ _mercuryHotspot.setHotspotFlags(kOpticalBiochipSpotFlag);
+ g_allHotspots.push_back(&_mercuryHotspot);
+
+ _poseidonHotspot.setArea(Common::Rect(kAIMiddleAreaLeft + 60, kAIMiddleAreaTop + 67, kAIMiddleAreaLeft + 60 + 121, kAIMiddleAreaTop + 67 + 20));
+ _poseidonHotspot.setHotspotFlags(kOpticalBiochipSpotFlag);
+ g_allHotspots.push_back(&_poseidonHotspot);
+
+ setItemState(kOptical000);
+
+ g_opticalChip = this;
+}
+
+OpticalChip::~OpticalChip() {
+ g_allHotspots.removeOneHotspot(kAriesSpotID);
+ g_allHotspots.removeOneHotspot(kMercurySpotID);
+ g_allHotspots.removeOneHotspot(kPoseidonSpotID);
+}
+
+void OpticalChip::writeToStream(Common::WriteStream *stream) {
+ BiochipItem::writeToStream(stream);
+ _opticalFlags.writeToStream(stream);
+}
+
+void OpticalChip::readFromStream(Common::ReadStream *stream) {
+ BiochipItem::readFromStream(stream);
+ _opticalFlags.readFromStream(stream);
+}
+
+void OpticalChip::addAries() {
+ _opticalFlags.setFlag(kOpticalAriesExposed, true);
+ setUpOpticalChip();
+}
+
+void OpticalChip::addMercury() {
+ _opticalFlags.setFlag(kOpticalMercuryExposed, true);
+ setUpOpticalChip();
+}
+
+void OpticalChip::addPoseidon() {
+ _opticalFlags.setFlag(kOpticalPoseidonExposed, true);
+ setUpOpticalChip();
+}
+
+void OpticalChip::setUpOpticalChip() {
+ if (_opticalFlags.getFlag(kOpticalAriesExposed)) {
+ if (_opticalFlags.getFlag(kOpticalMercuryExposed)) {
+ if (_opticalFlags.getFlag(kOpticalPoseidonExposed))
+ setItemState(kOptical111);
+ else
+ setItemState(kOptical011);
+ } else {
+ if (_opticalFlags.getFlag(kOpticalPoseidonExposed))
+ setItemState(kOptical101);
+ else
+ setItemState(kOptical001);
+ }
+ } else {
+ if (_opticalFlags.getFlag(kOpticalMercuryExposed)) {
+ if (_opticalFlags.getFlag(kOpticalPoseidonExposed))
+ setItemState(kOptical110);
+ else
+ setItemState(kOptical010);
+ } else {
+ if (_opticalFlags.getFlag(kOpticalPoseidonExposed))
+ setItemState(kOptical100);
+ else
+ setItemState(kOptical000);
+ }
+ }
+}
+
+void OpticalChip::activateOpticalHotspots() {
+ if (_opticalFlags.getFlag(kOpticalAriesExposed))
+ _ariesHotspot.setActive();
+ if (_opticalFlags.getFlag(kOpticalMercuryExposed))
+ _mercuryHotspot.setActive();
+ if (_opticalFlags.getFlag(kOpticalPoseidonExposed))
+ _poseidonHotspot.setActive();
+}
+
+void OpticalChip::clickInOpticalHotspot(HotSpotID id) {
+ playOpMemMovie(id);
+}
+
+void OpticalChip::playOpMemMovie(HotSpotID id) {
+ Common::String movieName;
+ switch (id) {
+ case kAriesSpotID:
+ movieName = "Images/AI/Globals/OMAI";
+ break;
+ case kMercurySpotID:
+ movieName = "Images/AI/Globals/OMMI";
+ break;
+ case kPoseidonSpotID:
+ movieName = "Images/AI/Globals/OMPI";
+ break;
+ }
+
+ ItemState state = getItemState(), newState;
+ switch (state) {
+ case kOptical001:
+ newState = kOptical002;
+ break;
+ case kOptical010:
+ newState = kOptical020;
+ break;
+ case kOptical011:
+ if (id == kAriesSpotID)
+ newState = kOptical012;
+ else
+ newState = kOptical021;
+ break;
+ case kOptical100:
+ newState = kOptical200;
+ break;
+ case kOptical101:
+ if (id == kAriesSpotID)
+ newState = kOptical102;
+ else
+ newState = kOptical201;
+ break;
+ case kOptical110:
+ if (id == kMercurySpotID)
+ newState = kOptical120;
+ else
+ newState = kOptical210;
+ break;
+ case kOptical111:
+ if (id == kAriesSpotID)
+ newState = kOptical112;
+ else if (id == kMercurySpotID)
+ newState = kOptical121;
+ else
+ newState = kOptical211;
+ break;
+ case kOptical000: // Can never happen.
+ default:
+ error("Invalid optical chip state");
+ }
+
+ setItemState(newState);
+
+ if (g_AIArea)
+ g_AIArea->playAIMovie(kRightAreaSignature, movieName, false, kOpticalInterruption);
+
+ setItemState(state);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/biochips/opticalchip.h b/engines/pegasus/items/biochips/opticalchip.h
new file mode 100644
index 0000000000..2f66f73d3a
--- /dev/null
+++ b/engines/pegasus/items/biochips/opticalchip.h
@@ -0,0 +1,71 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_ITEMS_BIOCHIPS_OPTICALCHIP_H
+#define PEGASUS_ITEMS_BIOCHIPS_OPTICALCHIP_H
+
+#include "pegasus/hotspot.h"
+#include "pegasus/util.h"
+#include "pegasus/items/biochips/biochipitem.h"
+
+namespace Pegasus {
+
+class OpticalChip : public BiochipItem {
+public:
+ OpticalChip(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+ virtual ~OpticalChip();
+
+ virtual void writeToStream(Common::WriteStream *);
+ virtual void readFromStream(Common::ReadStream *);
+
+ void addAries();
+ void addMercury();
+ void addPoseidon();
+
+ void activateOpticalHotspots();
+ void clickInOpticalHotspot(HotSpotID);
+ void playOpMemMovie(HotSpotID);
+
+protected:
+ enum {
+ kOpticalAriesExposed,
+ kOpticalMercuryExposed,
+ kOpticalPoseidonExposed,
+ kNumOpticalChipFlags
+ };
+
+ void setUpOpticalChip();
+
+ FlagsArray<byte, kNumOpticalChipFlags> _opticalFlags;
+ Hotspot _ariesHotspot;
+ Hotspot _mercuryHotspot;
+ Hotspot _poseidonHotspot;
+};
+
+extern OpticalChip *g_opticalChip;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/biochips/pegasuschip.cpp b/engines/pegasus/items/biochips/pegasuschip.cpp
new file mode 100644
index 0000000000..fa551fce30
--- /dev/null
+++ b/engines/pegasus/items/biochips/pegasuschip.cpp
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/energymonitor.h"
+#include "pegasus/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/items/biochips/pegasuschip.h"
+#include "pegasus/neighborhood/tsa/fulltsa.h"
+#include "pegasus/neighborhood/tsa/tinytsa.h"
+
+namespace Pegasus {
+
+PegasusChip::PegasusChip(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
+ BiochipItem(id, neighborhood, room, direction), _recallSpot(kPegasusRecallSpotID) {
+ _recallSpot.setArea(Common::Rect(kAIMiddleAreaLeft + 116, kAIMiddleAreaTop + 63, kAIMiddleAreaLeft + 184, kAIMiddleAreaTop + 91));
+ _recallSpot.setHotspotFlags(kPegasusBiochipSpotFlag);
+ g_allHotspots.push_back(&_recallSpot);
+ setItemState(kPegasusTSA00);
+}
+
+PegasusChip::~PegasusChip() {
+ g_allHotspots.removeOneHotspot(kPegasusRecallSpotID);
+}
+
+void PegasusChip::select() {
+ BiochipItem::select();
+ setUpPegasusChip();
+}
+
+void PegasusChip::setUpPegasusChip() {
+ switch (GameState.getCurrentNeighborhood()) {
+ case kCaldoriaID:
+ setItemState(kPegasusCaldoria);
+ break;
+ case kFullTSAID:
+ case kFinalTSAID:
+ case kTinyTSAID:
+ setItemState(kPegasusTSA10);
+ break;
+ case kPrehistoricID:
+ if (((PegasusEngine *)g_engine)->playerHasItemID(kHistoricalLog))
+ setItemState(kPegasusPrehistoric00);
+ else
+ setItemState(kPegasusPrehistoric10);
+ break;
+ case kMarsID:
+ if (GameState.getMarsFinished())
+ setItemState(kPegasusMars00);
+ else
+ setItemState(kPegasusMars10);
+ break;
+ case kWSCID:
+ if (GameState.getWSCFinished())
+ setItemState(kPegasusWSC00);
+ else
+ setItemState(kPegasusWSC10);
+ break;
+ case kNoradAlphaID:
+ case kNoradDeltaID:
+ if (GameState.getNoradFinished())
+ setItemState(kPegasusNorad00);
+ else
+ setItemState(kPegasusNorad10);
+ break;
+ }
+}
+
+// Only does something if the chip should be announcing that the time zone is finished...
+void PegasusChip::setUpPegasusChipRude() {
+ switch (GameState.getCurrentNeighborhood()) {
+ case kPrehistoricID:
+ if (((PegasusEngine *)g_engine)->playerHasItemID(kHistoricalLog))
+ setItemState(kPegasusPrehistoric00);
+ break;
+ case kMarsID:
+ if (GameState.getMarsFinished())
+ setItemState(kPegasusMars00);
+ break;
+ case kWSCID:
+ if (GameState.getWSCFinished())
+ setItemState(kPegasusWSC00);
+ break;
+ case kNoradAlphaID:
+ case kNoradDeltaID:
+ if (GameState.getNoradFinished())
+ setItemState(kPegasusNorad00);
+ break;
+ }
+}
+
+void PegasusChip::activatePegasusHotspots() {
+ switch (GameState.getCurrentNeighborhood()) {
+ case kPrehistoricID:
+ // WORKAROUND: Don't allow the player to recall if they don't have
+ // the historical log. Otherwise, gameplay is broken when returning
+ // to the TSA.
+ if (!((PegasusEngine *)g_engine)->playerHasItemID(kHistoricalLog))
+ return;
+ // fall through
+ case kMarsID:
+ case kWSCID:
+ case kNoradAlphaID:
+ case kNoradDeltaID:
+ _recallSpot.setActive();
+ break;
+ }
+}
+
+void PegasusChip::clickInPegasusHotspot() {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ ItemState thisState = getItemState();
+ ItemState hiliteState;
+
+ switch (thisState) {
+ case kPegasusPrehistoric00:
+ hiliteState = kPegasusPrehistoric01;
+ break;
+ case kPegasusPrehistoric10:
+ hiliteState = kPegasusPrehistoric11;
+ break;
+ case kPegasusMars00:
+ hiliteState = kPegasusMars01;
+ break;
+ case kPegasusMars10:
+ hiliteState = kPegasusMars11;
+ break;
+ case kPegasusNorad00:
+ hiliteState = kPegasusNorad01;
+ break;
+ case kPegasusNorad10:
+ hiliteState = kPegasusNorad11;
+ break;
+ case kPegasusWSC00:
+ hiliteState = kPegasusWSC01;
+ break;
+ case kPegasusWSC10:
+ hiliteState = kPegasusWSC11;
+ break;
+ default:
+ error("Invalid pegasus chip state");
+ }
+
+ // WORKAROUND: The original called setItemState() here. However,
+ // since we're overriding select() to call setUpPegasusChip(),
+ // the highlighted frame is never displayed! So, we're manually
+ // setting the state and selecting the item. Also of note is that
+ // setItemState() for this class is effectively useless since it
+ // always gets overriden in the select() function. The only reason
+ // that this doesn't end in infinite recursion is because setItemState()
+ // has a check against the current state to make sure you don't call
+ // select() again. </rant>
+ _itemState = hiliteState;
+ BiochipItem::select();
+
+ uint32 time = g_system->getMillis();
+ while (g_system->getMillis() < time + 500) {
+ vm->refreshDisplay();
+ g_system->delayMillis(10);
+ }
+
+ setItemState(thisState);
+
+ if (!((Neighborhood *)g_neighborhood)->okayToJump())
+ return;
+
+ if (g_energyMonitor)
+ g_energyMonitor->stopEnergyDraining();
+
+ if (GameState.getTSAState() == kPlayerWentToPrehistoric || GameState.allTimeZonesFinished())
+ vm->jumpToNewEnvironment(kFullTSAID, kTSA37, kNorth);
+ else
+ vm->jumpToNewEnvironment(kTinyTSAID, kTinyTSA37, kNorth);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/biochips/pegasuschip.h b/engines/pegasus/items/biochips/pegasuschip.h
new file mode 100644
index 0000000000..7597424821
--- /dev/null
+++ b/engines/pegasus/items/biochips/pegasuschip.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_ITEMS_BIOCHIPS_PEGASUSCHIP_H
+#define PEGASUS_ITEMS_BIOCHIPS_PEGASUSCHIP_H
+
+#include "pegasus/hotspot.h"
+#include "pegasus/items/biochips/biochipitem.h"
+
+namespace Pegasus {
+
+class PegasusChip : public BiochipItem {
+public:
+ PegasusChip(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+ virtual ~PegasusChip();
+
+ void select();
+
+ void setUpPegasusChip();
+
+ // Called to set up the Pegasus chip when the Pegasus chip is the current chip but does not
+ // own the center area.
+ void setUpPegasusChipRude();
+ void activatePegasusHotspots();
+ void clickInPegasusHotspot();
+
+protected:
+ Hotspot _recallSpot;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/biochips/retscanchip.cpp b/engines/pegasus/items/biochips/retscanchip.cpp
new file mode 100644
index 0000000000..84b74a63d2
--- /dev/null
+++ b/engines/pegasus/items/biochips/retscanchip.cpp
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/ai/ai_area.h"
+#include "pegasus/items/biochips/retscanchip.h"
+
+namespace Pegasus {
+
+RetScanChip::RetScanChip(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
+ BiochipItem(id, neighborhood, room, direction) {
+}
+
+void RetScanChip::searchForLaser() {
+ ItemExtraEntry entry;
+ findItemExtra(kRetinalScanSearching, entry);
+
+ if (g_AIArea)
+ g_AIArea->playAIAreaSequence(kBiochipSignature, kMiddleAreaSignature, entry.extraStart, entry.extraStop);
+
+ findItemExtra(kRetinalScanActivated, entry);
+ if (g_AIArea)
+ g_AIArea->playAIAreaSequence(kBiochipSignature, kRightAreaSignature, entry.extraStart, entry.extraStop);
+
+ setItemState(kRetinalSimulating);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/biochips/retscanchip.h b/engines/pegasus/items/biochips/retscanchip.h
new file mode 100644
index 0000000000..153e6cd071
--- /dev/null
+++ b/engines/pegasus/items/biochips/retscanchip.h
@@ -0,0 +1,43 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_ITEMS_BIOCHIPS_RETSCANCHIP_H
+#define PEGASUS_ITEMS_BIOCHIPS_RETSCANCHIP_H
+
+#include "pegasus/items/biochips/biochipitem.h"
+
+namespace Pegasus {
+
+class RetScanChip : public BiochipItem {
+public:
+ RetScanChip(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+ virtual ~RetScanChip() {}
+
+ void searchForLaser();
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/biochips/shieldchip.cpp b/engines/pegasus/items/biochips/shieldchip.cpp
new file mode 100644
index 0000000000..58cbfcc4ec
--- /dev/null
+++ b/engines/pegasus/items/biochips/shieldchip.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/gamestate.h"
+#include "pegasus/items/biochips/shieldchip.h"
+#include "pegasus/neighborhood/neighborhood.h"
+
+namespace Pegasus {
+
+ShieldChip *g_shield = 0;
+
+ShieldChip::ShieldChip(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
+ BiochipItem(id, neighborhood, room, direction) {
+ g_shield = this;
+}
+
+void ShieldChip::select() {
+ BiochipItem::select();
+ GameState.setShieldOn(true);
+ if (g_neighborhood)
+ g_neighborhood->shieldOn();
+}
+
+void ShieldChip::deselect() {
+ BiochipItem::deselect();
+ GameState.setShieldOn(false);
+ if (g_neighborhood)
+ g_neighborhood->shieldOff();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/biochips/shieldchip.h b/engines/pegasus/items/biochips/shieldchip.h
new file mode 100644
index 0000000000..69c6369236
--- /dev/null
+++ b/engines/pegasus/items/biochips/shieldchip.h
@@ -0,0 +1,46 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_ITEMS_BIOCHIPS_SHIELDCHIP_H
+#define PEGASUS_ITEMS_BIOCHIPS_SHIELDCHIP_H
+
+#include "pegasus/items/biochips/biochipitem.h"
+
+namespace Pegasus {
+
+class ShieldChip : public BiochipItem {
+public:
+ ShieldChip(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+ virtual ~ShieldChip() {}
+
+ void select();
+ void deselect();
+};
+
+extern ShieldChip *g_shield;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/inventory.cpp b/engines/pegasus/items/inventory.cpp
new file mode 100644
index 0000000000..57923b105d
--- /dev/null
+++ b/engines/pegasus/items/inventory.cpp
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/constants.h"
+#include "pegasus/items/item.h"
+#include "pegasus/items/inventory.h"
+
+namespace Pegasus {
+
+Inventory::Inventory() {
+ _weightLimit = 100;
+ _ownerID = kNoActorID;
+ _referenceCount = 0;
+}
+
+Inventory::~Inventory() {
+}
+
+void Inventory::setWeightLimit(WeightType limit) {
+ _weightLimit = limit;
+ // *** What to do if the new weight limit is greater than the current weight?
+}
+
+WeightType Inventory::getWeight() {
+ WeightType result = 0;
+
+ for (ItemIterator it = _inventoryList.begin(); it != _inventoryList.end(); it++)
+ result += (*it)->getItemWeight();
+
+ return result;
+}
+
+// If the item already belongs, just return kInventoryOK.
+InventoryResult Inventory::addItem(Item *item) {
+ if (itemInInventory(item))
+ return kInventoryOK;
+
+ if (getWeight() + item->getItemWeight() > _weightLimit)
+ return kTooMuchWeight;
+
+ _inventoryList.push_back(item);
+ item->setItemOwner(_ownerID);
+
+ ++_referenceCount;
+ return kInventoryOK;
+}
+
+InventoryResult Inventory::removeItem(Item *item) {
+ for (ItemIterator it = _inventoryList.begin(); it != _inventoryList.end(); it++) {
+ if (*it == item) {
+ _inventoryList.erase(it);
+ item->setItemOwner(kNoActorID);
+
+ ++_referenceCount;
+ return kInventoryOK;
+ }
+ }
+
+ return kItemNotInInventory;
+}
+
+InventoryResult Inventory::removeItem(ItemID id) {
+ Item *item = findItemByID(id);
+
+ if (item) {
+ _inventoryList.remove(item);
+ item->setItemOwner(kNoActorID);
+
+ ++_referenceCount;
+ return kInventoryOK;
+ }
+
+ return kItemNotInInventory;
+}
+
+void Inventory::removeAllItems() {
+ _inventoryList.clear();
+ ++_referenceCount;
+}
+
+bool Inventory::itemInInventory(Item *item) {
+ for (ItemIterator it = _inventoryList.begin(); it != _inventoryList.end(); it++)
+ if (*it == item)
+ return true;
+
+ return false;
+}
+
+bool Inventory::itemInInventory(ItemID id) {
+ return findItemByID(id) != NULL;
+}
+
+Item *Inventory::getItemAt(int32 index) {
+ int32 i = 0;
+ for (ItemIterator it = _inventoryList.begin(); it != _inventoryList.end(); it++, i++)
+ if (i == index)
+ return *it;
+
+ return 0;
+}
+
+ItemID Inventory::getItemIDAt(int32 index) {
+ Item *item = getItemAt(index);
+
+ if (item)
+ return item->getObjectID();
+
+ return kNoItemID;
+}
+
+Item *Inventory::findItemByID(ItemID id) {
+ return _inventoryList.findItemByID(id);
+}
+
+// Return -1 if not found.
+
+int32 Inventory::findIndexOf(Item *item) {
+ uint32 i = 0;
+ for (ItemIterator it = _inventoryList.begin(); it != _inventoryList.end(); it++, i++)
+ if (*it == item)
+ return i;
+
+ return -1;
+}
+
+// Return -1 if not found.
+
+int32 Inventory::findIndexOf(ItemID id) {
+ uint32 i = 0;
+ for (ItemIterator it = _inventoryList.begin(); it != _inventoryList.end(); it++, i++)
+ if ((*it)->getObjectID() == id)
+ return i;
+
+ return -1;
+}
+
+WeightType Inventory::getWeightLimit() {
+ return _weightLimit;
+}
+
+int32 Inventory::getNumItems() {
+ return _inventoryList.size();
+}
+
+void Inventory::setOwnerID(const ActorID id) {
+ _ownerID = id;
+}
+
+ActorID Inventory::getOwnerID() const {
+ return _ownerID;
+}
+
+} // End of namespae Pegasus
diff --git a/engines/pegasus/items/inventory.h b/engines/pegasus/items/inventory.h
new file mode 100644
index 0000000000..796ec49556
--- /dev/null
+++ b/engines/pegasus/items/inventory.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_ITEMS_INVENTORY_H
+#define PEGASUS_ITEMS_INVENTORY_H
+
+#include "pegasus/types.h"
+#include "pegasus/items/itemlist.h"
+
+namespace Pegasus {
+
+class Item;
+
+// Inventories have a "current item". This item is the default item the player can
+// use. In a text adventure system, the current item would be "it", as in
+// "Hit the troll with it," where "it" would refer to some weapon which is the current
+// item. In a graphic adventure, the current item would be the item the user selects
+// to use with the mouse or other pointing device.
+
+class Inventory {
+public:
+ Inventory();
+ virtual ~Inventory();
+
+ WeightType getWeightLimit();
+ void setWeightLimit(WeightType limit);
+ WeightType getWeight();
+
+ virtual InventoryResult addItem(Item *item);
+ virtual InventoryResult removeItem(Item *item);
+ virtual InventoryResult removeItem(ItemID id);
+ virtual bool itemInInventory(Item *item);
+ virtual bool itemInInventory(ItemID id);
+ virtual Item *getItemAt(int32 index);
+ virtual ItemID getItemIDAt(int32 index);
+ virtual Item *findItemByID(ItemID id);
+ virtual int32 findIndexOf(Item *item);
+ virtual int32 findIndexOf(ItemID id);
+ int32 getNumItems();
+ virtual void removeAllItems();
+
+ void setOwnerID(const ActorID id);
+ ActorID getOwnerID() const;
+
+ uint32 getReferenceCount() { return _referenceCount; }
+
+protected:
+ WeightType _weightLimit;
+ ActorID _ownerID;
+ ItemList _inventoryList;
+
+private:
+ uint32 _referenceCount;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/inventory/airmask.cpp b/engines/pegasus/items/inventory/airmask.cpp
new file mode 100644
index 0000000000..c65dd36102
--- /dev/null
+++ b/engines/pegasus/items/inventory/airmask.cpp
@@ -0,0 +1,249 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/inventory/airmask.h"
+#include "pegasus/neighborhood/neighborhood.h"
+
+namespace Pegasus {
+
+AirMask *g_airMask = 0;
+
+// Based on full == 100, which is scale used by GetAirLeft().
+static const TimeValue kOxygenLowThreshold = 25;
+
+void AirMask::airMaskTimerExpired() {
+ if (g_neighborhood)
+ g_neighborhood->checkAirMask();
+}
+
+AirMask::AirMask(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
+ InventoryItem(id, neighborhood, room, direction), _toggleSpot(kAirMaskToggleSpotID) {
+ g_airMask = this;
+ _toggleSpot.setArea(Common::Rect(kAIMiddleAreaLeft + 10, kAIMiddleAreaTop + 17, kAIMiddleAreaLeft + 110, kAIMiddleAreaTop + 57));
+ _toggleSpot.setHotspotFlags(kAirMaskSpotFlag);
+ g_allHotspots.push_back(&_toggleSpot);
+ setItemState(kAirMaskEmptyOff);
+ _oxygenTimer.primeFuse(0);
+ _oxygenTimer.setFunctor(new Common::Functor0Mem<void, AirMask>(this, &AirMask::airMaskTimerExpired));
+}
+
+AirMask::~AirMask() {
+ g_allHotspots.removeOneHotspot(kAirMaskToggleSpotID);
+ g_airMask = 0;
+}
+
+void AirMask::writeToStream(Common::WriteStream *stream) {
+ InventoryItem::writeToStream(stream);
+ stream->writeUint32BE(_oxygenTimer.getTimeRemaining());
+}
+
+void AirMask::readFromStream(Common::ReadStream *stream) {
+ _oxygenTimer.stopFuse();
+ InventoryItem::readFromStream(stream);
+ _oxygenTimer.primeFuse(stream->readUint32BE());
+}
+
+void AirMask::putMaskOn() {
+ AirQuality airQuality;
+
+ if (g_neighborhood)
+ airQuality = g_neighborhood->getAirQuality(GameState.getCurrentRoom());
+ else
+ airQuality = kAirQualityGood;
+
+ uint airLevel = getAirLeft();
+ ItemState newState = getItemState();
+ ItemState oldState = newState;
+
+ if (airLevel == 0) {
+ newState = kAirMaskEmptyFilter;
+ } else if (airLevel <= kOxygenLowThreshold) {
+ if (airQuality == kAirQualityVacuum)
+ newState = kAirMaskLowOn;
+ else
+ newState = kAirMaskLowFilter;
+ } else {
+ if (airQuality == kAirQualityVacuum)
+ newState = kAirMaskFullOn;
+ else
+ newState = kAirMaskFullFilter;
+ }
+
+ if (newState != oldState)
+ setItemState(newState);
+}
+
+void AirMask::takeMaskOff() {
+ uint airLevel = getAirLeft();
+ ItemState newState = getItemState();
+ ItemState oldState = newState;
+
+ if (airLevel == 0)
+ newState = kAirMaskEmptyOff;
+ else if (airLevel <= kOxygenLowThreshold)
+ newState = kAirMaskLowOff;
+ else
+ newState = kAirMaskFullOff;
+
+ if (newState != oldState)
+ setItemState(newState);
+}
+
+void AirMask::toggleItemState() {
+ if (isAirMaskInUse())
+ takeMaskOff();
+ else
+ putMaskOn();
+}
+
+void AirMask::airQualityChanged() {
+ if (isAirMaskInUse())
+ putMaskOn();
+ else
+ takeMaskOff();
+}
+
+void AirMask::setItemState(const ItemState newState) {
+ if (newState != getItemState()) {
+ InventoryItem::setItemState(newState);
+
+ switch (newState) {
+ case kAirMaskFullOn:
+ case kAirMaskLowOn:
+ if (!_oxygenTimer.isFuseLit()) {
+ _oxygenTimer.lightFuse();
+ startIdling();
+ }
+ break;
+ default:
+ if (_oxygenTimer.isFuseLit()) {
+ _oxygenTimer.stopFuse();
+ stopIdling();
+ }
+ break;
+ }
+
+ if (g_neighborhood)
+ g_neighborhood->checkAirMask();
+
+ g_AIArea->checkMiddleArea();
+ }
+}
+
+void AirMask::useIdleTime() {
+ if (getAirLeft() == 0)
+ setItemState(kAirMaskEmptyOff);
+ else if (getAirLeft() <= kOxygenLowThreshold)
+ setItemState(kAirMaskLowOn);
+}
+
+void AirMask::refillAirMask() {
+ switch (getItemState()) {
+ case kAirMaskEmptyOff:
+ case kAirMaskLowOff:
+ setItemState(kAirMaskFullOff);
+ break;
+ case kAirMaskEmptyFilter:
+ case kAirMaskLowFilter:
+ setItemState(kAirMaskFullFilter);
+ break;
+ case kAirMaskLowOn:
+ setItemState(kAirMaskFullOn);
+ break;
+ }
+
+ if (_oxygenTimer.isFuseLit()) {
+ _oxygenTimer.stopFuse();
+ _oxygenTimer.primeFuse(kOxyMaskFullTime);
+ _oxygenTimer.lightFuse();
+ } else {
+ _oxygenTimer.primeFuse(kOxyMaskFullTime);
+ }
+}
+
+// Doesn't return 0 until the timer is actually at 0.
+uint AirMask::getAirLeft() {
+ return CLIP<int>(((_oxygenTimer.getTimeRemaining() * 100) + kOxyMaskFullTime - 1) / kOxyMaskFullTime, 0, 100);
+}
+
+bool AirMask::isAirMaskInUse() {
+ switch (getItemState()) {
+ case kAirMaskEmptyOff:
+ case kAirMaskLowOff:
+ case kAirMaskFullOff:
+ return false;
+ break;
+ default:
+ return true;
+ break;
+ }
+}
+
+bool AirMask::isAirMaskOn() {
+ switch (getItemState()) {
+ case kAirMaskLowOn:
+ case kAirMaskFullOn:
+ return true;
+ break;
+ default:
+ return false;
+ break;
+ }
+}
+
+bool AirMask::isAirFilterOn() {
+ switch (getItemState()) {
+ case kAirMaskEmptyFilter:
+ case kAirMaskLowFilter:
+ case kAirMaskFullFilter:
+ return true;
+ break;
+ default:
+ return false;
+ break;
+ }
+}
+
+void AirMask::addedToInventory() {
+ GameState.setMarsMaskOnFiller(false);
+}
+
+void AirMask::removedFromInventory() {
+ if (isAirMaskInUse())
+ toggleItemState();
+}
+
+void AirMask::activateAirMaskHotspots() {
+ _toggleSpot.setActive();
+}
+
+void AirMask::clickInAirMaskHotspot() {
+ toggleItemState();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/inventory/airmask.h b/engines/pegasus/items/inventory/airmask.h
new file mode 100644
index 0000000000..6a2d708a6c
--- /dev/null
+++ b/engines/pegasus/items/inventory/airmask.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_ITEMS_INVENTORY_AIRMASK_H
+#define PEGASUS_ITEMS_INVENTORY_AIRMASK_H
+
+#include "pegasus/hotspot.h"
+#include "pegasus/timers.h"
+#include "pegasus/items/inventory/inventoryitem.h"
+
+namespace Pegasus {
+
+class AirMask : public InventoryItem, private Idler {
+public:
+ AirMask(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+ virtual ~AirMask();
+
+ virtual void writeToStream(Common::WriteStream *);
+ virtual void readFromStream(Common::ReadStream *);
+
+ virtual void setItemState(const ItemState);
+ void putMaskOn();
+ void takeMaskOff();
+ void toggleItemState();
+ void airQualityChanged();
+
+ bool isAirMaskInUse();
+ bool isAirMaskOn();
+ bool isAirFilterOn();
+
+ void refillAirMask();
+
+ // Returns a percentage
+ uint getAirLeft();
+
+ void activateAirMaskHotspots();
+ void clickInAirMaskHotspot();
+
+protected:
+ void airMaskTimerExpired();
+
+ virtual void removedFromInventory();
+ virtual void addedToInventory();
+ void useIdleTime();
+
+ Hotspot _toggleSpot;
+ FuseFunction _oxygenTimer;
+};
+
+extern AirMask *g_airMask;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/inventory/gascanister.cpp b/engines/pegasus/items/inventory/gascanister.cpp
new file mode 100644
index 0000000000..bf63cc6542
--- /dev/null
+++ b/engines/pegasus/items/inventory/gascanister.cpp
@@ -0,0 +1,46 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/ai/ai_area.h"
+#include "pegasus/items/inventory/gascanister.h"
+
+namespace Pegasus {
+
+GasCanister::GasCanister(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
+ InventoryItem(id, neighborhood, room, direction) {
+}
+
+void GasCanister::select() {
+ InventoryItem::select();
+ takeSharedArea();
+}
+
+void GasCanister::takeSharedArea() {
+ ItemExtraEntry entry;
+ findItemExtra(kGasCanLoop, entry);
+ g_AIArea->loopAIAreaSequence(kInventorySignature, kMiddleAreaSignature, entry.extraStart, entry.extraStop);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/inventory/gascanister.h b/engines/pegasus/items/inventory/gascanister.h
new file mode 100644
index 0000000000..7d4d8193f5
--- /dev/null
+++ b/engines/pegasus/items/inventory/gascanister.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_ITEMS_INVENTORY_GASCANISTER_H
+#define PEGASUS_ITEMS_INVENTORY_GASCANISTER_H
+
+#include "pegasus/items/inventory/inventoryitem.h"
+
+namespace Pegasus {
+
+class GasCanister : public InventoryItem {
+public:
+ GasCanister(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+ virtual ~GasCanister() {}
+
+ void select();
+ void takeSharedArea();
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/inventory/inventoryitem.cpp b/engines/pegasus/items/inventory/inventoryitem.cpp
new file mode 100644
index 0000000000..4399708879
--- /dev/null
+++ b/engines/pegasus/items/inventory/inventoryitem.cpp
@@ -0,0 +1,110 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/stream.h"
+
+#include "pegasus/pegasus.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/inventory/inventoryitem.h"
+
+namespace Pegasus {
+
+InventoryItem::InventoryItem(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
+ Item(id, neighborhood, room, direction) {
+
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ Common::SeekableReadStream *leftInfo = vm->_resFork->getResource(MKTAG('L', 'e', 'f', 't'), kItemBaseResID + id);
+ if (leftInfo) {
+ _leftAreaInfo = readItemState(leftInfo);
+ delete leftInfo;
+ } else {
+ _leftAreaInfo.numEntries = 0;
+ _leftAreaInfo.entries = 0;
+ }
+
+ Common::SeekableReadStream *inventoryInfo = vm->_resFork->getResource(MKTAG('I', 'n', 'v', 'I'), kItemBaseResID + id);
+ if (inventoryInfo) {
+ _inventoryInfo.panelStart = inventoryInfo->readUint32BE();
+ _inventoryInfo.panelStop = inventoryInfo->readUint32BE();
+ delete inventoryInfo;
+ } else {
+ _inventoryInfo.panelStart = _inventoryInfo.panelStop = 0;
+ }
+
+ _itemAnimationTime = 0;
+}
+
+InventoryItem::~InventoryItem() {
+ delete[] _leftAreaInfo.entries;
+}
+
+ItemType InventoryItem::getItemType() {
+ return kInventoryItemType;
+}
+
+TimeValue InventoryItem::getLeftAreaTime() const {
+ if (!_leftAreaInfo.entries)
+ return 0xffffffff;
+
+ TimeValue time;
+ ItemState state;
+
+ findItemStateEntryByState(_leftAreaInfo, _itemState, time);
+ if (time == 0xffffffff)
+ getItemStateEntry(_leftAreaInfo, 0, state, time);
+
+ return time;
+}
+
+void InventoryItem::setAnimationTime(const TimeValue time) {
+ _itemAnimationTime = time;
+}
+
+TimeValue InventoryItem::getAnimationTime() const {
+ return _itemAnimationTime;
+}
+
+// Must affect images in left area.
+void InventoryItem::select() {
+ Item::select();
+
+ if (g_AIArea)
+ g_AIArea->setAIAreaToTime(kInventorySignature, kLeftAreaSignature, getLeftAreaTime());
+}
+
+void InventoryItem::deselect() {
+ Item::deselect();
+
+ if (g_AIArea)
+ g_AIArea->setAIAreaToTime(kInventorySignature, kLeftAreaSignature, 0xffffffff);
+}
+
+void InventoryItem::getPanelTimes(TimeValue &start, TimeValue &stop) const {
+ start = _inventoryInfo.panelStart;
+ stop = _inventoryInfo.panelStop;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/inventory/inventoryitem.h b/engines/pegasus/items/inventory/inventoryitem.h
new file mode 100644
index 0000000000..9d78113014
--- /dev/null
+++ b/engines/pegasus/items/inventory/inventoryitem.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_ITEMS_INVENTORY_INVENTORYITEM_H
+#define PEGASUS_ITEMS_INVENTORY_INVENTORYITEM_H
+
+#include "pegasus/items/item.h"
+
+namespace Pegasus {
+
+// JMPInventoryInfo contains the resource data used by InventoryItems.
+
+struct JMPInventoryInfo {
+ TimeValue panelStart;
+ TimeValue panelStop;
+};
+
+class InventoryItem : public Item {
+public:
+ InventoryItem(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+ virtual ~InventoryItem();
+
+ virtual ItemType getItemType();
+
+ void getPanelTimes(TimeValue &, TimeValue &) const;
+ TimeValue getLeftAreaTime() const;
+
+ void setAnimationTime(const TimeValue);
+ TimeValue getAnimationTime() const;
+
+ virtual void toggleItemState() {}
+
+ // Must affect images in left area.
+ virtual void select();
+ virtual void deselect();
+
+protected:
+ JMPInventoryInfo _inventoryInfo;
+ ItemStateInfo _leftAreaInfo;
+ TimeValue _itemAnimationTime;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/inventory/keycard.cpp b/engines/pegasus/items/inventory/keycard.cpp
new file mode 100644
index 0000000000..c818b6675b
--- /dev/null
+++ b/engines/pegasus/items/inventory/keycard.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/pegasus.h"
+#include "pegasus/items/inventory/keycard.h"
+
+namespace Pegasus {
+
+KeyCard::KeyCard(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) :
+ InventoryItem(id, neighborhood, room, direction) {
+ setItemState(kFlashlightOff);
+}
+
+void KeyCard::toggleItemState() {
+ if (getItemState() == kFlashlightOff)
+ setItemState(kFlashlightOn);
+ else
+ setItemState(kFlashlightOff);
+}
+
+void KeyCard::setItemState(const ItemState newState) {
+ if (newState != getItemState()) {
+ InventoryItem::setItemState(newState);
+ ((PegasusEngine *)g_engine)->checkFlashlight();
+ }
+}
+
+bool KeyCard::isFlashlightOn() {
+ return getItemState() == kFlashlightOn;
+}
+
+void KeyCard::removedFromInventory() {
+ if (isFlashlightOn())
+ setItemState(kFlashlightOff);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/inventory/keycard.h b/engines/pegasus/items/inventory/keycard.h
new file mode 100644
index 0000000000..846f40e6e5
--- /dev/null
+++ b/engines/pegasus/items/inventory/keycard.h
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_ITEMS_INVENTORY_KEYCARD_H
+#define PEGASUS_ITEMS_INVENTORY_KEYCARD_H
+
+#include "pegasus/items/inventory/inventoryitem.h"
+
+namespace Pegasus {
+
+class KeyCard : public InventoryItem {
+public:
+ KeyCard(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+ virtual ~KeyCard() {}
+
+ virtual void toggleItemState();
+ virtual void setItemState(const ItemState);
+ bool isFlashlightOn();
+
+protected:
+ virtual void removedFromInventory();
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/inventorypicture.cpp b/engines/pegasus/items/inventorypicture.cpp
new file mode 100644
index 0000000000..fc812faae2
--- /dev/null
+++ b/engines/pegasus/items/inventorypicture.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/pegasus.h"
+#include "pegasus/transition.h"
+#include "pegasus/items/inventorypicture.h"
+#include "pegasus/items/biochips/biochipitem.h"
+#include "pegasus/items/inventory/inventoryitem.h"
+
+namespace Pegasus {
+
+InventoryPicture::InventoryPicture(const DisplayElementID id, InputHandler *nextHandler, Inventory *inventory) :
+ InputHandler(nextHandler), Picture(id), _panelMovie(kNoDisplayElement){
+ _inventory = inventory;
+ _lastReferenceCount = 0xffffffff;
+
+ if (_inventory->getNumItems() > 0) {
+ _currentItemIndex = 0;
+ _currentItem = (Item *)_inventory->getItemAt(0);
+ } else {
+ _currentItemIndex = -1;
+ _currentItem = 0;
+ }
+
+ _active = false;
+ _shouldDrawHighlight = true;
+ _itemsPerRow = 1;
+ _numberOfRows = 1;
+ _itemWidth = 0;
+ _itemHeight = 0;
+ _itemX = 0;
+ _itemY = 0;
+}
+
+void InventoryPicture::initInventoryImage(Transition *transition) {
+ initFromPICTFile(_pictName, true);
+ _panelMovie.shareSurface(this);
+ _panelMovie.initFromMovieFile(_movieName);
+ _panelMovie.getBounds(_highlightBounds);
+ _panelMovie.setTriggeredElement(transition);
+ _highlightImage.initFromPICTFile(_highlightName, true);
+}
+
+void InventoryPicture::throwAwayInventoryImage() {
+ if (isSurfaceValid()) {
+ _panelMovie.releaseMovie();
+ _highlightImage.deallocateSurface();
+ deallocateSurface();
+ }
+}
+
+void InventoryPicture::getItemXY(uint32 index, CoordType &x, CoordType &y) {
+ x = (index % _itemsPerRow) * _itemWidth + _itemX;
+ y = (index / _itemsPerRow) * _itemHeight + _itemY;
+}
+
+void InventoryPicture::drawItemHighlight(const Common::Rect &r) {
+ if (_highlightImage.isSurfaceValid()) {
+ Common::Rect r2 = _highlightBounds;
+ Common::Rect bounds;
+ getBounds(bounds);
+
+ r2.translate(bounds.left, bounds.top);
+ r2 = r2.findIntersectingRect(r);
+ if (!r2.isEmpty()) {
+ Common::Rect r1 = r2;
+ r1.translate(-bounds.left - _highlightBounds.left, -bounds.top - _highlightBounds.top);
+ _highlightImage.drawImage(r1, r2);
+ }
+ }
+}
+
+void InventoryPicture::draw(const Common::Rect &r) {
+ Picture::draw(r);
+ if (_inventory->getNumItems() != 0 && _shouldDrawHighlight)
+ drawItemHighlight(r);
+}
+
+// Assumes index >= 0.
+void InventoryPicture::setCurrentItemIndex(int32 index) {
+ if (index >= _inventory->getNumItems())
+ index = _inventory->getNumItems() - 1;
+
+ Item *currentItem = 0;
+ if (index >= 0)
+ currentItem = (Item *)_inventory->getItemAt(index);
+
+ if (currentItem != _currentItem) {
+ if (_currentItem) {
+ if (_currentItem->isSelected())
+ _currentItem->deselect();
+
+ if (_active)
+ unhighlightCurrentItem();
+ }
+
+ _currentItemIndex = index;
+ _currentItem = currentItem;
+ if (_currentItem) {
+ _currentItem->select();
+
+ if (_active)
+ highlightCurrentItem();
+ }
+
+ if (_active)
+ triggerRedraw();
+ }
+}
+
+void InventoryPicture::setCurrentItemID(ItemID id) {
+ int32 index = _inventory->findIndexOf(id);
+ if (index >= 0)
+ setCurrentItemIndex(index);
+}
+
+InventoryResult InventoryPicture::addInventoryItem(Item *item) {
+ InventoryResult result = _inventory->addItem(item);
+
+ if (result == kInventoryOK)
+ setCurrentItemIndex(_inventory->findIndexOf(item));
+
+ return result;
+}
+
+InventoryResult InventoryPicture::removeInventoryItem(Item *item) {
+ InventoryResult result = _inventory->removeItem(item);
+
+ if (result == kInventoryOK)
+ setCurrentItemIndex(getCurrentItemIndex());
+
+ return result;
+}
+
+void InventoryPicture::removeAllItems() {
+ _inventory->removeAllItems();
+ setCurrentItemIndex(0);
+}
+
+bool InventoryPicture::itemInInventory(Item *item) {
+ return _inventory->itemInInventory(item);
+}
+
+bool InventoryPicture::itemInInventory(const ItemID id) {
+ return _inventory->itemInInventory(id);
+}
+
+void InventoryPicture::panelUp() {
+ allowInput(true);
+}
+
+// Must ensure that the picture matches the _inventory member variable.
+void InventoryPicture::activateInventoryPicture() {
+ if (_active)
+ return;
+
+ allowInput(false);
+
+ if (_lastReferenceCount != _inventory->getReferenceCount()) {
+ uint32 numItems = _inventory->getNumItems();
+
+ CoordType x, y;
+ getItemXY(0, x, y);
+ _panelMovie.moveMovieBoxTo(x, y);
+ _panelMovie.show();
+
+ for (uint32 i = 0; i < numItems; i++) {
+ Item *item = (Item *)_inventory->getItemAt(i);
+ if (item == _currentItem)
+ item->select();
+
+ getItemXY(i, x, y);
+ _panelMovie.moveMovieBoxTo(x, y);
+ _panelMovie.setTime(getItemPanelTime(item));
+ _panelMovie.redrawMovieWorld();
+ }
+
+ uint32 numSlots = _itemsPerRow * _numberOfRows;
+
+ for (uint32 i = numItems; i < numSlots; i++) {
+ getItemXY(i, x, y);
+ _panelMovie.moveMovieBoxTo(x, y);
+ _panelMovie.setTime(0);
+ _panelMovie.redrawMovieWorld();
+ }
+
+ _lastReferenceCount = _inventory->getReferenceCount();
+ }
+
+ show(); // *** Do we really need this?
+ if (_currentItem)
+ highlightCurrentItem();
+
+ _active = true;
+}
+
+void InventoryPicture::deactivateInventoryPicture() {
+ if (!_active)
+ return;
+
+ _active = false;
+ allowInput(false);
+ _panelMovie.hide();
+ hide();
+
+ if (_inventory->getNumItems() != 0)
+ if (!_currentItem->isActive())
+ _currentItem->activate();
+}
+
+void InventoryPicture::handleInput(const Input &input, const Hotspot *cursorSpot) {
+ if (_active) {
+ if (input.upButtonDown()) {
+ if (_currentItemIndex - _itemsPerRow >= 0)
+ setCurrentItemIndex(_currentItemIndex - _itemsPerRow);
+ } else if (input.downButtonDown()) {
+ if (_currentItemIndex + _itemsPerRow < _inventory->getNumItems())
+ setCurrentItemIndex(_currentItemIndex + _itemsPerRow);
+ } else if (input.leftButtonDown()) {
+ if ((_currentItemIndex % _itemsPerRow) != 0)
+ setCurrentItemIndex(_currentItemIndex - 1);
+ } else if (input.rightButtonDown()) {
+ if (((_currentItemIndex + 1) % _itemsPerRow) != 0 && _currentItemIndex + 1 < _inventory->getNumItems())
+ setCurrentItemIndex(_currentItemIndex + 1);
+ }
+ }
+
+ InputHandler::handleInput(input, cursorSpot);
+}
+
+void InventoryPicture::highlightCurrentItem() {
+ CoordType x, y;
+ getItemXY(_currentItemIndex, x, y);
+ _highlightBounds.moveTo(x, y);
+}
+
+InventoryItemsPicture::InventoryItemsPicture(const DisplayElementID id, InputHandler *nextHandler, Inventory *inventory) :
+ InventoryPicture(id, nextHandler, inventory) {
+ _pictName = "Images/Items/Inventory/Inventory Panel";
+ _movieName = "Images/Items/Inventory/Inventory Panel Movie";
+ _highlightName = "Images/Items/Inventory/Inventory Hilite";
+
+ _itemsPerRow = 3;
+ _numberOfRows = 3;
+ _itemWidth = 88;
+ _itemHeight = 64;
+ _itemX = 8;
+ _itemY = 26;
+ _isLooping = true;
+}
+
+void InventoryItemsPicture::loopCurrentItem() {
+ if (_isLooping) {
+ CoordType x, y;
+ getItemXY(_currentItemIndex, x, y);
+ _panelMovie.moveMovieBoxTo(x, y);
+ _highlightBounds.moveTo(x, y);
+
+ TimeValue start, stop;
+ ((InventoryItem *)_currentItem)->getPanelTimes(start, stop);
+ _panelMovie.stop();
+ _panelMovie.setFlags(0);
+ _panelMovie.setSegment(start, stop);
+ _panelMovie.setFlags(kLoopTimeBase);
+ _panelMovie.setTime(((InventoryItem *)_currentItem)->getAnimationTime());
+ _panelMovie.start();
+ }
+}
+
+void InventoryItemsPicture::highlightCurrentItem() {
+ InventoryPicture::highlightCurrentItem();
+ loopCurrentItem();
+}
+
+void InventoryItemsPicture::unhighlightCurrentItem() {
+ InventoryPicture::unhighlightCurrentItem();
+ _panelMovie.stop();
+ _panelMovie.setFlags(0);
+ ((InventoryItem *)_currentItem)->setAnimationTime(_panelMovie.getTime());
+}
+
+TimeValue InventoryItemsPicture::getItemPanelTime(Item *item) {
+ TimeValue start, stop;
+ ((InventoryItem *)item)->getPanelTimes(start, stop);
+ ((InventoryItem *)item)->setAnimationTime(start);
+ return start;
+}
+
+void InventoryItemsPicture::deactivateInventoryPicture() {
+ if (_active) {
+ InventoryPicture::deactivateInventoryPicture();
+ _panelMovie.stop();
+ _panelMovie.setFlags(0);
+ _panelMovie.setSegment(0, _panelMovie.getDuration());
+ _isLooping = true;
+ }
+}
+
+void InventoryItemsPicture::playEndMessage(DisplayElement *pushElement) {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ Movie endMessage(0);
+
+ _shouldDrawHighlight = false;
+ endMessage.shareSurface(this);
+ endMessage.initFromMovieFile("Images/Caldoria/A56 Congrats");
+ endMessage.moveMovieBoxTo(kFinalMessageLeft - kInventoryPushLeft, kFinalMessageTop - kInventoryPushTop);
+ endMessage.setTriggeredElement(pushElement);
+ endMessage.start();
+
+ while (endMessage.isRunning()) {
+ vm->checkCallBacks();
+ vm->refreshDisplay();
+ g_system->delayMillis(10);
+ }
+
+ endMessage.stop();
+}
+
+BiochipPicture::BiochipPicture(const DisplayElementID id, InputHandler *nextHandler, Inventory *inventory) :
+ InventoryPicture(id, nextHandler, inventory) {
+ _pictName = "Images/Items/Biochips/Biochip Panel";
+ _movieName = "Images/Items/Biochips/Biochip Panel Movie";
+ _highlightName = "Images/Items/Biochips/BioChip Hilite";
+
+ _itemsPerRow = 4;
+ _numberOfRows = 2;
+ _itemWidth = 46;
+ _itemHeight = 46;
+ _itemX = 4;
+ _itemY = 24;
+}
+
+void BiochipPicture::unhighlightCurrentItem() {
+ InventoryPicture::unhighlightCurrentItem();
+ CoordType x, y;
+ getItemXY(_currentItemIndex, x, y);
+ _panelMovie.show();
+ _panelMovie.moveMovieBoxTo(x, y);
+ _panelMovie.setTime(getItemPanelTime(_currentItem));
+ _panelMovie.redrawMovieWorld();
+}
+
+TimeValue BiochipPicture::getItemPanelTime(Item *item) {
+ return ((BiochipItem *)item)->getPanelTime();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/inventorypicture.h b/engines/pegasus/items/inventorypicture.h
new file mode 100644
index 0000000000..88a4a4ba75
--- /dev/null
+++ b/engines/pegasus/items/inventorypicture.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_ITEMS_INVENTORYPICTURE_H
+#define PEGASUS_ITEMS_INVENTORYPICTURE_H
+
+#include "pegasus/input.h"
+#include "pegasus/movie.h"
+#include "pegasus/surface.h"
+
+namespace Pegasus {
+
+class Inventory;
+class Item;
+class Input;
+class Transition;
+
+class InventoryPicture : public InputHandler, public Picture {
+public:
+ InventoryPicture(const DisplayElementID, InputHandler *, Inventory *);
+ virtual ~InventoryPicture() {}
+
+ void initInventoryImage(Transition *);
+ void throwAwayInventoryImage();
+
+ void panelUp();
+ void activateInventoryPicture();
+ void deactivateInventoryPicture();
+ void handleInput(const Input &, const Hotspot *);
+ bool wantsCursor() { return false; }
+
+ InventoryResult addInventoryItem(Item *);
+ InventoryResult removeInventoryItem(Item *);
+ void removeAllItems();
+ Item *getCurrentItem() { return _currentItem; }
+ void setCurrentItemIndex(int32);
+ void setCurrentItemID(ItemID);
+ int32 getCurrentItemIndex() { return _currentItemIndex; }
+ bool itemInInventory(Item *);
+ bool itemInInventory(const ItemID);
+
+protected:
+ void getItemXY(uint32, CoordType &, CoordType &);
+ void draw(const Common::Rect &);
+ void drawItemHighlight(const Common::Rect &);
+ virtual void highlightCurrentItem();
+ virtual void unhighlightCurrentItem() {}
+ virtual TimeValue getItemPanelTime(Item *) = 0;
+
+ Inventory *_inventory;
+ uint32 _lastReferenceCount;
+ Frame _highlightImage;
+ Movie _panelMovie;
+ int32 _currentItemIndex;
+ Item *_currentItem;
+ Common::Rect _highlightBounds;
+ bool _active, _shouldDrawHighlight;
+
+ Common::String _pictName;
+ Common::String _movieName;
+ Common::String _highlightName;
+ uint16 _itemsPerRow;
+ uint16 _numberOfRows;
+ uint16 _itemWidth;
+ uint16 _itemHeight;
+ uint16 _itemX;
+ uint16 _itemY;
+};
+
+class InventoryItemsPicture : public InventoryPicture {
+public:
+ InventoryItemsPicture(const DisplayElementID, InputHandler *, Inventory *);
+ virtual ~InventoryItemsPicture() {}
+
+ void deactivateInventoryPicture();
+
+ void disableLooping() { _isLooping = false; }
+
+ void playEndMessage(DisplayElement *);
+
+protected:
+ virtual void highlightCurrentItem();
+ virtual void unhighlightCurrentItem();
+ virtual TimeValue getItemPanelTime(Item *);
+ void loopCurrentItem();
+
+ InputHandler *_previousHandler;
+ bool _isLooping;
+};
+
+class BiochipPicture : public InventoryPicture {
+public:
+ BiochipPicture(const DisplayElementID, InputHandler *, Inventory *);
+ virtual ~BiochipPicture() {}
+
+protected:
+ virtual void unhighlightCurrentItem();
+ virtual TimeValue getItemPanelTime(Item *);
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/item.cpp b/engines/pegasus/items/item.cpp
new file mode 100644
index 0000000000..8089f2b93d
--- /dev/null
+++ b/engines/pegasus/items/item.cpp
@@ -0,0 +1,314 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/error.h"
+#include "common/stream.h"
+
+#include "pegasus/constants.h"
+#include "pegasus/elements.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/surface.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/item.h"
+#include "pegasus/items/itemlist.h"
+#include "pegasus/items/biochips/biochipitem.h"
+#include "pegasus/items/inventory/inventoryitem.h"
+
+namespace Pegasus {
+
+Item::Item(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) : IDObject(id) {
+ _itemNeighborhood = neighborhood;
+ _itemRoom = room;
+ _itemDirection = direction;
+ _itemWeight = 1;
+ _itemOwnerID = kNoActorID;
+ _itemState = 0;
+
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ Common::SeekableReadStream *info = vm->_resFork->getResource(kItemInfoResType, kItemBaseResID + id);
+ if (info) {
+ _itemInfo.infoLeftTime = info->readUint32BE();
+ _itemInfo.infoRightStart = info->readUint32BE();
+ _itemInfo.infoRightStop = info->readUint32BE();
+ _itemInfo.dragSpriteNormalID = info->readUint16BE();
+ _itemInfo.dragSpriteUsedID = info->readUint16BE();
+
+ if (vm->isDemo()) {
+ // Adjust info right times to account for the stuff that was chopped out of the
+ // info right movies.
+ // Assumes time scale of 600.
+
+ // Gap times in seconds
+ static const TimeValue kGap1 = 24;
+ static const TimeValue kGap2 = 34;
+ static const TimeValue kGap3 = 4;
+ static const TimeValue kGap4 = 4;
+
+ static const TimeValue kGapForGroup1 = kGap1;
+ static const TimeValue kGapForGroup2 = kGapForGroup1 + kGap2;
+ static const TimeValue kGapForGroup3 = kGapForGroup2 + kGap3;
+ static const TimeValue kGapForGroup4 = kGapForGroup3 + kGap4;
+
+ switch (id) {
+ case kHistoricalLog:
+ case kJourneymanKey:
+ case kKeyCard:
+ _itemInfo.infoRightStart -= 600 * kGapForGroup1;
+ _itemInfo.infoRightStop -= 600 * kGapForGroup1;
+ break;
+ case kAIBiochip:
+ _itemInfo.infoRightStart -= 600 * kGapForGroup2;
+ _itemInfo.infoRightStop -= 600 * kGapForGroup2;
+ break;
+ case kMapBiochip:
+ _itemInfo.infoRightStart -= 600 * kGapForGroup3;
+ _itemInfo.infoRightStop -= 600 * kGapForGroup3;
+ break;
+ case kPegasusBiochip:
+ _itemInfo.infoRightStart -= 600 * kGapForGroup4;
+ _itemInfo.infoRightStop -= 600 * kGapForGroup4;
+ break;
+ }
+ }
+
+ delete info;
+ } else {
+ memset(&_itemInfo, 0, sizeof(_itemInfo));
+ }
+
+ Common::SeekableReadStream *middleAreaInfo = vm->_resFork->getResource(kMiddleAreaInfoResType, kItemBaseResID + id);
+ if (middleAreaInfo) {
+ _sharedAreaInfo = readItemState(middleAreaInfo);
+ delete middleAreaInfo;
+ } else {
+ // Only kArgonPickup does not have this
+ memset(&_sharedAreaInfo, 0, sizeof(_sharedAreaInfo));
+ }
+
+ Common::SeekableReadStream *extraInfo = vm->_resFork->getResource(kItemExtraInfoResType, kItemBaseResID + id);
+ if (!extraInfo)
+ error("Extra info not found for item %d", id);
+
+ _itemExtras.numEntries = extraInfo->readUint16BE();
+ _itemExtras.entries = new ItemExtraEntry[_itemExtras.numEntries];
+ for (uint16 i = 0; i < _itemExtras.numEntries; i++) {
+ _itemExtras.entries[i].extraID = extraInfo->readUint32BE();
+ _itemExtras.entries[i].extraArea = extraInfo->readUint16BE();
+ _itemExtras.entries[i].extraStart = extraInfo->readUint32BE();
+ _itemExtras.entries[i].extraStop = extraInfo->readUint32BE();
+ }
+
+ delete extraInfo;
+
+ g_allItems.push_back(this);
+}
+
+Item::~Item() {
+ delete[] _sharedAreaInfo.entries;
+ delete[] _itemExtras.entries;
+}
+
+void Item::writeToStream(Common::WriteStream *stream) {
+ stream->writeUint16BE(_itemNeighborhood);
+ stream->writeUint16BE(_itemRoom);
+ stream->writeByte(_itemDirection);
+ stream->writeUint16BE(_itemOwnerID);
+ stream->writeUint16BE(_itemState);
+}
+
+void Item::readFromStream(Common::ReadStream *stream) {
+ _itemNeighborhood = stream->readUint16BE();
+ _itemRoom = stream->readUint16BE();
+ _itemDirection = stream->readByte();
+ _itemOwnerID = stream->readUint16BE();
+ _itemState = stream->readUint16BE();
+}
+
+ActorID Item::getItemOwner() const {
+ return _itemOwnerID;
+}
+
+void Item::setItemOwner(const ActorID owner) {
+ _itemOwnerID = owner;
+
+ if (owner == kNoActorID) {
+ if (isSelected())
+ deselect();
+ removedFromInventory();
+ } else {
+ addedToInventory();
+ }
+}
+
+WeightType Item::getItemWeight() {
+ return _itemWeight;
+}
+
+ItemState Item::getItemState() const {
+ return _itemState;
+}
+
+void Item::setItemState(const ItemState state) {
+ if (state != _itemState) {
+ _itemState = state;
+
+ if (getItemType() == kInventoryItemType && ((PegasusEngine *)g_engine)->getCurrentInventoryItem() == (InventoryItem *)this)
+ select();
+ else if (getItemType() == kBiochipItemType && ((PegasusEngine *)g_engine)->getCurrentBiochip() == (BiochipItem *)this)
+ select();
+ }
+}
+
+void Item::getItemRoom(NeighborhoodID &neighborhood, RoomID &room, DirectionConstant &direction) const {
+ neighborhood = _itemNeighborhood;
+ room = _itemRoom;
+ direction = _itemDirection;
+}
+
+void Item::setItemRoom(const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) {
+ _itemNeighborhood = neighborhood;
+ _itemRoom = room;
+ _itemDirection = direction;
+
+ if (neighborhood == kNoNeighborhoodID)
+ pickedUp();
+ else
+ dropped();
+}
+
+NeighborhoodID Item::getItemNeighborhood() const {
+ return _itemNeighborhood;
+}
+
+TimeValue Item::getSharedAreaTime() const {
+ if (!_sharedAreaInfo.entries)
+ return 0xffffffff;
+
+ TimeValue time;
+ ItemState state;
+
+ findItemStateEntryByState(_sharedAreaInfo, _itemState, time);
+ if (time == 0xffffffff)
+ getItemStateEntry(_sharedAreaInfo, 0, state, time);
+
+ return time;
+}
+
+// Must affect images in shared area.
+void Item::select() {
+ _isSelected = true;
+
+ if (g_AIArea) {
+ if (getItemType() == kInventoryItemType)
+ g_AIArea->setAIAreaToTime(kInventorySignature, kMiddleAreaSignature, getSharedAreaTime());
+ else
+ g_AIArea->setAIAreaToTime(kBiochipSignature, kMiddleAreaSignature, getSharedAreaTime());
+ }
+}
+
+void Item::deselect() {
+ _isActive = false;
+ _isSelected = false;
+
+ if (g_AIArea) {
+ if (getItemType() == kInventoryItemType)
+ g_AIArea->setAIAreaToTime(kInventorySignature, kMiddleAreaSignature, 0xffffffff);
+ else
+ g_AIArea->setAIAreaToTime(kBiochipSignature, kMiddleAreaSignature, 0xffffffff);
+ }
+}
+
+void Item::getItemStateEntry(ItemStateInfo info, uint32 index, ItemState &state, TimeValue &time) {
+ if (index < info.numEntries) {
+ state = info.entries[index].itemState;
+ time = info.entries[index].itemTime;
+ } else {
+ state = kNoItemState;
+ time = 0xffffffff;
+ }
+}
+
+void Item::findItemStateEntryByState(ItemStateInfo info, ItemState state, TimeValue &time) {
+ for (uint16 i = 0; i < info.numEntries; i++) {
+ if (info.entries[i].itemState == state) {
+ time = info.entries[i].itemTime;
+ return;
+ }
+ }
+
+ time = 0xffffffff;
+}
+
+ItemStateInfo Item::readItemState(Common::SeekableReadStream *stream) {
+ ItemStateInfo info;
+
+ info.numEntries = stream->readUint16BE();
+ info.entries = new ItemStateEntry[info.numEntries];
+ for (uint16 i = 0; i < info.numEntries; i++) {
+ info.entries[i].itemState = stream->readSint16BE();
+ info.entries[i].itemTime = stream->readUint32BE();
+ }
+
+ return info;
+}
+
+Sprite *Item::getDragSprite(const DisplayElementID id) const {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+ Sprite *result = new Sprite(id);
+ SpriteFrame *frame = new SpriteFrame();
+
+ frame->initFromPICTResource(vm->_resFork, _itemInfo.dragSpriteNormalID, true);
+ result->addFrame(frame, 0, 0);
+
+ if (_itemInfo.dragSpriteNormalID != _itemInfo.dragSpriteUsedID) {
+ frame = new SpriteFrame();
+ frame->initFromPICTResource(vm->_resFork, _itemInfo.dragSpriteUsedID, true);
+ }
+
+ result->addFrame(frame, 0, 0);
+ result->setCurrentFrameIndex(0);
+ return result;
+}
+
+TimeValue Item::getInfoLeftTime() const {
+ return _itemInfo.infoLeftTime;
+}
+
+void Item::getInfoRightTimes(TimeValue &start, TimeValue &stop) const {
+ start = _itemInfo.infoRightStart;
+ stop = _itemInfo.infoRightStop;
+}
+
+void Item::findItemExtra(const uint32 extraID, ItemExtraEntry &entry) {
+ for (uint32 i = 0; i < _itemExtras.numEntries; i++) {
+ if (_itemExtras.entries[i].extraID == extraID) {
+ entry = _itemExtras.entries[i];
+ return;
+ }
+ }
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/item.h b/engines/pegasus/items/item.h
new file mode 100644
index 0000000000..a1451b2a58
--- /dev/null
+++ b/engines/pegasus/items/item.h
@@ -0,0 +1,363 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_ITEMS_ITEM_H
+#define PEGASUS_ITEMS_ITEM_H
+
+#include "common/endian.h"
+
+#include "pegasus/types.h"
+#include "pegasus/util.h"
+
+namespace Common {
+ class Error;
+ class ReadStream;
+ class WriteStream;
+ class SeekableReadStream;
+}
+
+namespace Pegasus {
+
+// JMPItemInfo contains resource data used by all Items.
+
+struct JMPItemInfo {
+ TimeValue infoLeftTime;
+ TimeValue infoRightStart;
+ TimeValue infoRightStop;
+ uint32 dragSpriteNormalID;
+ uint32 dragSpriteUsedID;
+};
+
+// ItemStateEntry contains a single state/TimeValue pair. The TimeValue is
+// the time value to set the shared area movie that corresponds with the given
+// state of an inventory item.
+
+struct ItemStateEntry {
+ ItemState itemState;
+ TimeValue itemTime;
+};
+
+struct ItemStateInfo {
+ uint16 numEntries; // For easy ResEdit access
+ ItemStateEntry *entries;
+};
+
+// ItemExtraEntry
+
+static const short kLeftAreaExtra = 0;
+static const short kMiddleAreaExtra = 1;
+static const short kRightAreaExtra = 2;
+
+struct ItemExtraEntry {
+ uint32 extraID;
+ uint16 extraArea;
+ TimeValue extraStart;
+ TimeValue extraStop;
+};
+
+struct ItemExtraInfo {
+ uint16 numEntries; // For easy ResEdit access
+ ItemExtraEntry *entries;
+};
+
+// Inventory info resource type and ID:
+// Individual inventory items are stored in these resource types.
+// Resource ID is item ID + kItemBaseResID.
+
+static const uint32 kItemInfoResType = MKTAG('I', 't', 'e', 'm'); // JMPItemInfoHandle
+static const uint32 kLeftAreaInfoResType = MKTAG('L', 'e', 'f', 't'); // ItemStateInfoHandle
+static const uint32 kMiddleAreaInfoResType = MKTAG('M', 'i', 'd', 'l'); // ItemStateInfoHandle
+static const uint32 kRightAreaInfoResType = MKTAG('R', 'g', 'h', 't'); // ItemStateInfoHandle
+static const uint32 kItemExtraInfoResType = MKTAG('I', 'X', 't', 'r'); // ItemExtraInfoHandle
+
+static const uint16 kItemBaseResID = 128;
+
+// Item IDs.
+
+static const ItemID kAirMask = 7;
+static const ItemID kAntidote = 8;
+static const ItemID kArgonCanister = 9;
+static const ItemID kCardBomb = 10;
+static const ItemID kCrowbar = 11;
+static const ItemID kGasCanister = 12;
+static const ItemID kHistoricalLog = 13;
+static const ItemID kJourneymanKey = 14;
+static const ItemID kKeyCard = 15;
+static const ItemID kMachineGun = 16;
+static const ItemID kMarsCard = 17;
+static const ItemID kNitrogenCanister = 18;
+static const ItemID kOrangeJuiceGlassFull = 19;
+static const ItemID kOrangeJuiceGlassEmpty = 20;
+static const ItemID kPoisonDart = 21;
+static const ItemID kSinclairKey = 22;
+static const ItemID kStunGun = 23;
+static const ItemID kArgonPickup = 24;
+
+// Biochips.
+
+static const ItemID kAIBiochip = 0;
+static const ItemID kInterfaceBiochip = 1;
+static const ItemID kMapBiochip = 2;
+static const ItemID kOpticalBiochip = 3;
+static const ItemID kPegasusBiochip = 4;
+static const ItemID kRetinalScanBiochip = 5;
+static const ItemID kShieldBiochip = 6;
+
+static const ItemID kNumItems = 25;
+
+// Item States.
+
+static const ItemState kAI000 = 0;
+static const ItemState kAI005 = 1;
+static const ItemState kAI006 = 2;
+static const ItemState kAI010 = 3;
+static const ItemState kAI015 = 4;
+static const ItemState kAI016 = 5;
+static const ItemState kAI020 = 6;
+static const ItemState kAI024 = 7;
+static const ItemState kAI100 = 8;
+static const ItemState kAI101 = 9;
+static const ItemState kAI105 = 10;
+static const ItemState kAI106 = 11;
+static const ItemState kAI110 = 12;
+static const ItemState kAI111 = 13;
+static const ItemState kAI115 = 14;
+static const ItemState kAI116 = 15;
+static const ItemState kAI120 = 16;
+static const ItemState kAI121 = 17;
+static const ItemState kAI124 = 18;
+static const ItemState kAI125 = 19;
+static const ItemState kAI126 = 20;
+static const ItemState kAI200 = 21;
+static const ItemState kAI201 = 22;
+static const ItemState kAI202 = 23;
+static const ItemState kAI205 = 24;
+static const ItemState kAI206 = 25;
+static const ItemState kAI210 = 26;
+static const ItemState kAI211 = 27;
+static const ItemState kAI212 = 28;
+static const ItemState kAI215 = 29;
+static const ItemState kAI216 = 30;
+static const ItemState kAI220 = 31;
+static const ItemState kAI221 = 32;
+static const ItemState kAI222 = 33;
+static const ItemState kAI224 = 34;
+static const ItemState kAI225 = 35;
+static const ItemState kAI226 = 36;
+static const ItemState kAI300 = 37;
+static const ItemState kAI301 = 38;
+static const ItemState kAI302 = 39;
+static const ItemState kAI303 = 40;
+static const ItemState kAI305 = 41;
+static const ItemState kAI306 = 42;
+static const ItemState kAI310 = 43;
+static const ItemState kAI311 = 44;
+static const ItemState kAI312 = 45;
+static const ItemState kAI313 = 46;
+static const ItemState kAI315 = 47;
+static const ItemState kAI316 = 48;
+static const ItemState kAI320 = 49;
+static const ItemState kAI321 = 50;
+static const ItemState kAI322 = 51;
+static const ItemState kAI323 = 52;
+static const ItemState kAI324 = 53;
+static const ItemState kAI325 = 54;
+static const ItemState kAI326 = 55;
+static const ItemState kNormalItem = 56;
+static const ItemState kMapUnavailable = 57;
+static const ItemState kMapEngaged = 58;
+static const ItemState kOptical000 = 59;
+static const ItemState kOptical001 = 60;
+static const ItemState kOptical002 = 61;
+static const ItemState kOptical010 = 62;
+static const ItemState kOptical011 = 63;
+static const ItemState kOptical012 = 64;
+static const ItemState kOptical020 = 65;
+static const ItemState kOptical021 = 66;
+static const ItemState kOptical100 = 67;
+static const ItemState kOptical101 = 68;
+static const ItemState kOptical102 = 69;
+static const ItemState kOptical110 = 70;
+static const ItemState kOptical111 = 71;
+static const ItemState kOptical112 = 72;
+static const ItemState kOptical120 = 73;
+static const ItemState kOptical121 = 74;
+static const ItemState kOptical200 = 75;
+static const ItemState kOptical201 = 76;
+static const ItemState kOptical210 = 77;
+static const ItemState kOptical211 = 78;
+static const ItemState kPegasusTSA00 = 79;
+static const ItemState kPegasusTSA10 = 80;
+static const ItemState kPegasusPrehistoric00 = 81;
+static const ItemState kPegasusPrehistoric01 = 82;
+static const ItemState kPegasusPrehistoric10 = 83;
+static const ItemState kPegasusPrehistoric11 = 84;
+static const ItemState kPegasusMars00 = 85;
+static const ItemState kPegasusMars01 = 86;
+static const ItemState kPegasusMars10 = 87;
+static const ItemState kPegasusMars11 = 88;
+static const ItemState kPegasusNorad00 = 89;
+static const ItemState kPegasusNorad01 = 90;
+static const ItemState kPegasusNorad10 = 91;
+static const ItemState kPegasusNorad11 = 92;
+static const ItemState kPegasusWSC00 = 93;
+static const ItemState kPegasusWSC01 = 94;
+static const ItemState kPegasusWSC10 = 95;
+static const ItemState kPegasusWSC11 = 96;
+static const ItemState kPegasusCaldoria = 97;
+static const ItemState kRetinalSimulating = 98;
+static const ItemState kShieldNormal = 99;
+static const ItemState kShieldRadiation = 100;
+static const ItemState kShieldPlasma = 101;
+static const ItemState kShieldCardBomb = 102;
+static const ItemState kShieldDraining = 103;
+static const ItemState kAirMaskEmptyOff = 104;
+static const ItemState kAirMaskEmptyFilter = 105;
+static const ItemState kAirMaskLowOff = 106;
+static const ItemState kAirMaskLowFilter = 107;
+static const ItemState kAirMaskLowOn = 108;
+static const ItemState kAirMaskFullOff = 109;
+static const ItemState kAirMaskFullFilter = 110;
+static const ItemState kAirMaskFullOn = 111;
+static const ItemState kArgonEmpty = 112;
+static const ItemState kArgonFull = 113;
+static const ItemState kFlashlightOff = 114;
+static const ItemState kFlashlightOn = 115;
+static const ItemState kNitrogenEmpty = 116;
+static const ItemState kNitrogenFull = 117;
+static const ItemState kFullGlass = 118;
+
+// Extra IDs.
+
+static const uint32 kRetinalScanSearching = 0;
+static const uint32 kRetinalScanActivated = 1;
+static const uint32 kShieldIntro = 2;
+static const uint32 kRemoveAirMask = 3;
+static const uint32 kRemoveArgon = 4;
+static const uint32 kRemoveCrowbar = 5;
+static const uint32 kGasCanLoop = 6;
+static const uint32 kRemoveJourneymanKey = 7;
+static const uint32 kRemoveMarsCard = 8;
+static const uint32 kRemoveNitrogen = 9;
+static const uint32 kRemoveGlass = 10;
+static const uint32 kRemoveDart = 11;
+static const uint32 kRemoveSinclairKey = 12;
+
+enum ItemType {
+ kInventoryItemType,
+ kBiochipItemType
+};
+
+class Sprite;
+
+/*
+
+ Item is an object which can be picked up and carried around.
+ Items have
+ a location
+ an ID.
+ weight
+ an owner (kNoActorID if no one is carrying the Item)
+
+*/
+
+class Item : public IDObject {
+public:
+ Item(const ItemID id, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction);
+ virtual ~Item();
+
+ // WriteToStream writes everything EXCEPT the item's ID.
+ // It is assumed that the calling function will write and read the ID.
+ virtual void writeToStream(Common::WriteStream *stream);
+ virtual void readFromStream(Common::ReadStream *stream);
+
+ virtual ActorID getItemOwner() const;
+ virtual void setItemOwner(const ActorID owner);
+
+ void getItemRoom(NeighborhoodID &neighborhood, RoomID &room, DirectionConstant &direction) const;
+ void setItemRoom(const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction);
+ NeighborhoodID getItemNeighborhood() const;
+
+ virtual WeightType getItemWeight();
+
+ virtual void setItemState(const ItemState state);
+ virtual ItemState getItemState() const;
+
+ virtual ItemType getItemType() = 0;
+
+ TimeValue getInfoLeftTime() const;
+ void getInfoRightTimes(TimeValue &, TimeValue &) const;
+ TimeValue getSharedAreaTime() const;
+
+ Sprite *getDragSprite(const DisplayElementID) const;
+
+ /*
+ select -- called when this item becomes current. Also called when the inventory
+ panel holding this item is raised and this is the current item.
+ deselect -- called when this item is no longer current.
+ activate -- called on the current item when the panel is closed.
+ */
+ // In an override of these three member functions, you must call the inherited
+ // member functions.
+ virtual void select();
+ virtual void deselect();
+ virtual bool isSelected() { return _isSelected; }
+
+ virtual void activate() { _isActive = true; }
+ virtual bool isActive() { return _isActive; }
+ virtual void pickedUp() {}
+ virtual void addedToInventory() {}
+ virtual void removedFromInventory() {}
+ virtual void dropped() {}
+
+ // Called when the shared area is taken by another item, but this item is still
+ // selected.
+ virtual void giveUpSharedArea() {}
+ virtual void takeSharedArea() {}
+
+ void findItemExtra(const uint32 extraID, ItemExtraEntry &entry);
+
+protected:
+ NeighborhoodID _itemNeighborhood;
+ RoomID _itemRoom;
+ DirectionConstant _itemDirection;
+ ActorID _itemOwnerID;
+ WeightType _itemWeight;
+ ItemState _itemState;
+
+ JMPItemInfo _itemInfo;
+ ItemStateInfo _sharedAreaInfo;
+ ItemExtraInfo _itemExtras;
+ bool _isActive;
+ bool _isSelected;
+
+ static void getItemStateEntry(ItemStateInfo, uint32, ItemState &, TimeValue &);
+ static void findItemStateEntryByState(ItemStateInfo, ItemState, TimeValue &);
+ static ItemStateInfo readItemState(Common::SeekableReadStream *stream);
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/itemdragger.cpp b/engines/pegasus/items/itemdragger.cpp
new file mode 100644
index 0000000000..97fc5a97ac
--- /dev/null
+++ b/engines/pegasus/items/itemdragger.cpp
@@ -0,0 +1,193 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/elements.h"
+#include "pegasus/hotspot.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/items/itemdragger.h"
+
+namespace Pegasus {
+
+SpriteDragger::SpriteDragger() {
+ _draggingSprite = 0;
+ _limitRect = Common::Rect(-30000, -30000, 30000, 30000);
+ _slopRect = Common::Rect(-30000, -30000, 30000, 30000);
+ _dragOffset.x = 0;
+ _dragOffset.y = 0;
+ _lastHotspot = 0;
+}
+
+void SpriteDragger::setDragSprite(Sprite *newSprite) {
+ if (!isTracking())
+ _draggingSprite = newSprite;
+}
+
+void SpriteDragger::setDragConstraints(const Common::Rect &limitRect, const Common::Rect &slopRect) {
+ if (!isTracking()) {
+ _rawLimitRect = limitRect;
+ _slopRect = slopRect;
+ }
+}
+
+void SpriteDragger::getDragConstraints(Common::Rect &limitRect, Common::Rect &slopRect) const {
+ limitRect = _rawLimitRect;
+ slopRect = _slopRect;
+}
+
+void SpriteDragger::startTracking(const Input &input) {
+ if (_draggingSprite) {
+ Tracker::startTracking(input);
+
+ if (isTracking()) {
+ input.getInputLocation(_startPoint);
+ _lastRawPoint = _startRawPoint = _startPoint;
+
+ Common::Rect r;
+ _draggingSprite->getBounds(r);
+ _dragOffset.x = _startPoint.x - r.left;
+ _dragOffset.y = _startPoint.y - r.top;
+
+ _limitRect = _rawLimitRect;
+ _limitRect.left += _dragOffset.x;
+ _limitRect.top += _dragOffset.y;
+ _limitRect.right -= r.width() - _dragOffset.x;
+ _limitRect.bottom -= r.height() - _dragOffset.y;
+ pinPointInRect(_limitRect, _startPoint);
+
+ _lastPoint = _startPoint;
+ if (_startPoint != _startRawPoint) {
+ Common::Point pt = _startPoint - _dragOffset;
+ _draggingSprite->moveElementTo(pt.x, pt.y);
+ }
+
+ _lastHotspot = g_allHotspots.findHotspot(_lastRawPoint);
+ if (_lastHotspot)
+ enterHotspot(_lastHotspot);
+ }
+ }
+}
+
+void SpriteDragger::continueTracking(const Input &input) {
+ if (_draggingSprite) {
+ Common::Point rawPoint;
+ input.getInputLocation(rawPoint);
+
+ if (!_slopRect.contains(rawPoint))
+ rawPoint = _startRawPoint;
+
+ if (rawPoint != _lastRawPoint) {
+ Common::Point newPoint = rawPoint;
+ pinPointInRect(_limitRect, newPoint);
+ newPoint -= _dragOffset;
+
+ if (newPoint != _lastPoint) {
+ _draggingSprite->moveElementTo(newPoint.x, newPoint.y);
+ _lastPoint = newPoint;
+ }
+
+ Hotspot *newHotspot = g_allHotspots.findHotspot(rawPoint);
+ if (newHotspot != _lastHotspot) {
+ if (_lastHotspot)
+ exitHotspot(_lastHotspot);
+ if (newHotspot)
+ enterHotspot(newHotspot);
+ _lastHotspot = newHotspot;
+ }
+
+ _lastRawPoint = rawPoint;
+ }
+ }
+}
+
+void SpriteDragger::pinPointInRect(const Common::Rect &r, Common::Point &pt) {
+ pt.x = CLIP<int>(pt.x, r.left, r.right - 1);
+ pt.y = CLIP<int>(pt.y, r.top, r.bottom - 1);
+}
+
+ItemDragger::ItemDragger(PegasusEngine *owner) : _inventoryDropSpot(kInventoryDropSpotID), _biochipDropSpot(kBiochipDropSpotID),
+ _inventoryHighlight(kInventoryDropHighlightID), _biochipHighlight(kBiochipDropHighlightID) {
+ _owner = owner;
+
+ Common::Rect r(kInventoryDropLeft, kInventoryDropTop, kInventoryDropRight, kInventoryDropBottom);
+ _inventoryDropSpot.setArea(r);
+ _inventoryDropSpot.setHotspotFlags(kDropItemSpotFlag);
+ g_allHotspots.push_back(&_inventoryDropSpot);
+
+ r = Common::Rect(kBiochipDropLeft, kBiochipDropTop, kBiochipDropRight, kBiochipDropBottom);
+ _biochipDropSpot.setArea(r);
+ _biochipDropSpot.setHotspotFlags(kDropBiochipSpotFlag);
+ g_allHotspots.push_back(&_biochipDropSpot);
+}
+
+void ItemDragger::startTracking(const Input &input) {
+ _inventoryHighlight.setDisplayOrder(kInventoryHiliteOrder);
+ _inventoryHighlight.startDisplaying();
+
+ _biochipHighlight.setDisplayOrder(kBiochipHiliteOrder);
+ _biochipHighlight.startDisplaying();
+
+ SpriteDragger::startTracking(input);
+}
+
+void ItemDragger::stopTracking(const Input &input) {
+ SpriteDragger::stopTracking(input);
+ _inventoryHighlight.hide();
+ _biochipHighlight.hide();
+ _inventoryHighlight.stopDisplaying();
+ _biochipHighlight.stopDisplaying();
+ _owner->dragTerminated(input);
+}
+
+bool ItemDragger::stopTrackingInput(const Input &input) {
+ return !JMPPPInput::isDraggingInput(input);
+}
+
+void ItemDragger::enterHotspot(Hotspot *spot) {
+ if (spot->getObjectID() == kInventoryDropSpotID)
+ _inventoryHighlight.show();
+ else if (spot->getObjectID() == kBiochipDropSpotID)
+ _biochipHighlight.show();
+ else if ((spot->getHotspotFlags() & kDropItemSpotFlag) != 0)
+ _draggingSprite->setCurrentFrameIndex(1);
+}
+
+void ItemDragger::exitHotspot(Hotspot *spot) {
+ if (spot->getObjectID() == kInventoryDropSpotID)
+ _inventoryHighlight.hide();
+ else if (spot->getObjectID() == kBiochipDropSpotID)
+ _biochipHighlight.hide();
+ else if ((spot->getHotspotFlags() & kDropItemSpotFlag) != 0)
+ _draggingSprite->setCurrentFrameIndex(0);
+}
+
+void ItemDragger::setHighlightBounds() {
+ uint32 color = g_system->getScreenFormat().RGBToColor(0x48, 0x80, 0xD8);
+ _inventoryHighlight.setBounds(Common::Rect(76, 334, 172, 430));
+ _inventoryHighlight.setHighlightColor(color);
+ _biochipHighlight.setBounds(Common::Rect(364, 334, 460, 430));
+ _biochipHighlight.setHighlightColor(color);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/itemdragger.h b/engines/pegasus/items/itemdragger.h
new file mode 100644
index 0000000000..fce953d695
--- /dev/null
+++ b/engines/pegasus/items/itemdragger.h
@@ -0,0 +1,96 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_ITEMS_ITEMDRAGGER_H
+#define PEGASUS_ITEMS_ITEMDRAGGER_H
+
+#include "pegasus/elements.h"
+#include "pegasus/input.h"
+
+namespace Pegasus {
+
+// TODO: Merge SpriteDragger and ItemDragger
+
+class Hotspot;
+class Sprite;
+
+class SpriteDragger : public Tracker {
+public:
+ SpriteDragger();
+ virtual ~SpriteDragger() {}
+
+ void setDragSprite(Sprite *);
+ Sprite *getDragSprite() { return _draggingSprite; }
+
+ void setDragConstraints(const Common::Rect &, const Common::Rect &);
+ void getDragConstraints(Common::Rect &, Common::Rect &) const;
+
+ void startTracking(const Input &);
+ void continueTracking(const Input&);
+
+ Hotspot *getLastHotspot() const { return _lastHotspot; }
+
+protected:
+ virtual void enterHotspot(Hotspot *) {}
+ virtual void exitHotspot(Hotspot *) {}
+
+ Sprite *_draggingSprite;
+ Common::Point _startPoint, _lastPoint, _dragOffset;
+ Common::Point _startRawPoint, _lastRawPoint;
+ Common::Rect _rawLimitRect;
+ Common::Rect _limitRect;
+ Common::Rect _slopRect;
+ Hotspot *_lastHotspot;
+
+ // This is a replica of QuickDraw's PinPointInRect function
+ void pinPointInRect(const Common::Rect &, Common::Point &);
+};
+
+class PegasusEngine;
+
+class ItemDragger : public SpriteDragger {
+public:
+ ItemDragger(PegasusEngine *);
+ virtual ~ItemDragger() {}
+
+ void setHighlightBounds();
+ void startTracking(const Input &);
+ void stopTracking(const Input &);
+ bool stopTrackingInput(const Input &);
+
+protected:
+ virtual void enterHotspot(Hotspot *);
+ virtual void exitHotspot(Hotspot *);
+
+ PegasusEngine *_owner;
+ DropHighlight _inventoryHighlight;
+ Hotspot _inventoryDropSpot;
+ DropHighlight _biochipHighlight;
+ Hotspot _biochipDropSpot;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/items/itemlist.cpp b/engines/pegasus/items/itemlist.cpp
new file mode 100644
index 0000000000..ff8cae546b
--- /dev/null
+++ b/engines/pegasus/items/itemlist.cpp
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/error.h"
+#include "common/stream.h"
+
+#include "pegasus/pegasus.h"
+#include "pegasus/items/item.h"
+#include "pegasus/items/itemlist.h"
+
+namespace Pegasus {
+
+ItemList::ItemList() {
+}
+
+ItemList::~ItemList() {
+}
+
+void ItemList::writeToStream(Common::WriteStream *stream) {
+ stream->writeUint32BE(size());
+
+ for (ItemIterator it = begin(); it != end(); it++) {
+ stream->writeUint16BE((*it)->getObjectID());
+ (*it)->writeToStream(stream);
+ }
+}
+
+void ItemList::readFromStream(Common::ReadStream *stream) {
+ uint32 itemCount = stream->readUint32BE();
+
+ for (uint32 i = 0; i < itemCount; i++) {
+ ItemID itemID = stream->readUint16BE();
+ g_allItems.findItemByID(itemID)->readFromStream(stream);
+ }
+}
+
+Item *ItemList::findItemByID(const ItemID id) {
+ for (ItemIterator it = begin(); it != end(); it++)
+ if ((*it)->getObjectID() == id)
+ return *it;
+
+ return 0;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/items/itemlist.h b/engines/pegasus/items/itemlist.h
new file mode 100644
index 0000000000..9b59206ab3
--- /dev/null
+++ b/engines/pegasus/items/itemlist.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_ITEMS_ITEMLIST_H
+#define PEGASUS_ITEMS_ITEMLIST_H
+
+#include "common/list.h"
+
+#include "pegasus/types.h"
+
+namespace Common {
+ class ReadStream;
+ class WriteStream;
+}
+
+namespace Pegasus {
+
+class Item;
+
+class ItemList : public Common::List<Item *> {
+public:
+ ItemList();
+ virtual ~ItemList();
+
+ virtual void writeToStream(Common::WriteStream *stream);
+ virtual void readFromStream(Common::ReadStream *stream);
+
+ Item *findItemByID(const ItemID id);
+};
+
+typedef ItemList::iterator ItemIterator;
+
+#define g_allItems (((PegasusEngine *)g_engine)->getAllItems())
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/menu.cpp b/engines/pegasus/menu.cpp
new file mode 100644
index 0000000000..deaa460188
--- /dev/null
+++ b/engines/pegasus/menu.cpp
@@ -0,0 +1,1219 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/gamestate.h"
+#include "pegasus/menu.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/scoring.h"
+
+namespace Pegasus {
+
+GameMenu::GameMenu(const uint32 id) : IDObject(id), InputHandler((InputHandler *)((PegasusEngine *)g_engine)) {
+ _previousHandler = 0;
+ _lastCommand = kMenuCmdNoCommand;
+}
+
+void GameMenu::becomeCurrentHandler() {
+ _previousHandler = InputHandler::setInputHandler(this);
+}
+
+void GameMenu::restorePreviousHandler() {
+ InputHandler::setInputHandler(_previousHandler);
+}
+
+void GameMenu::drawScore(GameScoreType score, GameScoreType total, const Common::Rect &scoreBounds, Surface *numbers) {
+ CoordType x = scoreBounds.right;
+ drawNumber(total, x, scoreBounds.top, numbers);
+
+ x -= 12;
+ Common::Rect r1(120, 0, 132, 12); // The slash.
+ Common::Rect r2 = r1;
+ r2.moveTo(x, scoreBounds.top);
+ numbers->copyToCurrentPort(r1, r2);
+ drawNumber(score, x, scoreBounds.top, numbers);
+}
+
+void GameMenu::drawNumber(GameScoreType number, CoordType &x, CoordType y, Surface *numbers) {
+ Common::Rect r1(0, 0, 12, 12); // Width, height of one digit
+ Common::Rect r2 = r1;
+ r2.moveTo(x - 12, y);
+
+ do {
+ uint16 digit = number % 10;
+ number /= 10;
+ r1.moveTo(digit * 12, 0);
+ numbers->copyToCurrentPort(r1, r2);
+ r2.translate(-12, 0);
+ } while (number != 0);
+
+ x = r2.right;
+}
+
+enum {
+ kMainMenuStartDemo = 0,
+ kMainMenuCreditsDemo,
+ kMainMenuQuitDemo,
+ kFirstSelectionDemo = kMainMenuStartDemo,
+ kLastSelectionDemo = kMainMenuQuitDemo,
+
+ kMainMenuOverview = 0,
+ kMainMenuStart,
+ kMainMenuRestore,
+ kMainMenuDifficulty,
+ kMainMenuCredits,
+ kMainMenuQuit,
+ kFirstSelection = kMainMenuOverview,
+ kLastSelection = kMainMenuQuit
+};
+
+static const CoordType kStartLeftDemo = 44;
+static const CoordType kStartTopDemo = 336;
+
+static const CoordType kStartSelectLeftDemo = 40;
+static const CoordType kStartSelectTopDemo = 331;
+
+static const CoordType kCreditsLeftDemo = 44;
+static const CoordType kCreditsTopDemo = 372;
+
+static const CoordType kCreditsSelectLeftDemo = 40;
+static const CoordType kCreditsSelectTopDemo = 367;
+
+static const CoordType kMainMenuQuitLeftDemo = 32;
+static const CoordType kMainMenuQuitTopDemo = 412;
+
+static const CoordType kMainMenuQuitSelectLeftDemo = 28;
+static const CoordType kMainMenuQuitSelectTopDemo = 408;
+
+static const CoordType kOverviewLeft = 200;
+static const CoordType kOverviewTop = 208;
+
+static const CoordType kOverviewSelectLeft = 152;
+static const CoordType kOverviewSelectTop = 204;
+
+static const CoordType kStartLeft = 212;
+static const CoordType kStartTop = 256;
+
+static const CoordType kStartSelectLeft = 152;
+static const CoordType kStartSelectTop = 252;
+
+static const CoordType kRestoreLeft = 212;
+static const CoordType kRestoreTop = 296;
+
+static const CoordType kRestoreSelectLeft = 152;
+static const CoordType kRestoreSelectTop = 292;
+
+static const CoordType kDifficultyLeft = 320;
+static const CoordType kDifficultyTop = 340;
+
+static const CoordType kDifficultySelectLeft = 152;
+static const CoordType kDifficultySelectTop = 336;
+
+static const CoordType kCreditsLeft = 212;
+static const CoordType kCreditsTop = 388;
+
+static const CoordType kCreditsSelectLeft = 152;
+static const CoordType kCreditsSelectTop = 384;
+
+static const CoordType kMainMenuQuitLeft = 212;
+static const CoordType kMainMenuQuitTop = 428;
+
+static const CoordType kMainMenuQuitSelectLeft = 152;
+static const CoordType kMainMenuQuitSelectTop = 424;
+
+// Never set the current input handler to the MainMenu.
+MainMenu::MainMenu() : GameMenu(kMainMenuID), _menuBackground(0), _overviewButton(0),
+ _restoreButton(0), _adventureButton(0), _walkthroughButton(0), _startButton(0),
+ _creditsButton(0), _quitButton(0), _largeSelect(0), _smallSelect(0) {
+
+ bool isDemo = ((PegasusEngine *)g_engine)->isDemo();
+
+ if (isDemo)
+ _menuBackground.initFromPICTFile("Images/Demo/DemoMenu.pict");
+ else
+ _menuBackground.initFromPICTFile("Images/Main Menu/MainMenu.mac");
+ _menuBackground.setDisplayOrder(0);
+ _menuBackground.startDisplaying();
+ _menuBackground.show();
+
+ if (!isDemo) {
+ _overviewButton.initFromPICTFile("Images/Main Menu/pbOvervi.pict");
+ _overviewButton.setDisplayOrder(1);
+ _overviewButton.moveElementTo(kOverviewLeft, kOverviewTop);
+ _overviewButton.startDisplaying();
+
+ _restoreButton.initFromPICTFile("Images/Main Menu/pbRestor.pict");
+ _restoreButton.setDisplayOrder(1);
+ _restoreButton.moveElementTo(kRestoreLeft, kRestoreTop);
+ _restoreButton.startDisplaying();
+
+ _adventureButton.initFromPICTFile("Images/Main Menu/BtnAdv.pict");
+ _adventureButton.setDisplayOrder(1);
+ _adventureButton.moveElementTo(kDifficultyLeft, kDifficultyTop);
+ _adventureButton.startDisplaying();
+
+ _walkthroughButton.initFromPICTFile("Images/Main Menu/BtnWlk.pict");
+ _walkthroughButton.setDisplayOrder(1);
+ _walkthroughButton.moveElementTo(kDifficultyLeft, kDifficultyTop);
+ _walkthroughButton.startDisplaying();
+ }
+
+ if (isDemo)
+ _startButton.initFromPICTFile("Images/Demo/Start.pict");
+ else
+ _startButton.initFromPICTFile("Images/Main Menu/pbStart.pict");
+ _startButton.setDisplayOrder(1);
+ _startButton.moveElementTo(isDemo ? kStartLeftDemo : kStartLeft, isDemo ? kStartTopDemo : kStartTop);
+ _startButton.startDisplaying();
+
+ if (isDemo)
+ _creditsButton.initFromPICTFile("Images/Demo/Credits.pict");
+ else
+ _creditsButton.initFromPICTFile("Images/Main Menu/pbCredit.pict");
+ _creditsButton.setDisplayOrder(1);
+ _creditsButton.moveElementTo(isDemo ? kCreditsLeftDemo : kCreditsLeft, isDemo ? kCreditsTopDemo : kCreditsTop);
+ _creditsButton.startDisplaying();
+
+ if (isDemo)
+ _quitButton.initFromPICTFile("Images/Demo/Quit.pict");
+ else
+ _quitButton.initFromPICTFile("Images/Main Menu/pbQuit.pict");
+ _quitButton.setDisplayOrder(1);
+ _quitButton.moveElementTo(isDemo ? kMainMenuQuitLeftDemo : kMainMenuQuitLeft, isDemo ? kMainMenuQuitTopDemo : kMainMenuQuitTop);
+ _quitButton.startDisplaying();
+
+ if (isDemo)
+ _largeSelect.initFromPICTFile("Images/Demo/SelectL.pict", true);
+ else
+ _largeSelect.initFromPICTFile("Images/Main Menu/SelectL.pict", true);
+ _largeSelect.setDisplayOrder(1);
+ _largeSelect.startDisplaying();
+
+ if (isDemo)
+ _smallSelect.initFromPICTFile("Images/Demo/SelectS.pict", true);
+ else
+ _smallSelect.initFromPICTFile("Images/Main Menu/SelectS.pict", true);
+ _smallSelect.setDisplayOrder(1);
+ _smallSelect.startDisplaying();
+
+ _menuSelection = isDemo ? kFirstSelectionDemo : kFirstSelection;
+
+ _adventureMode = true;
+
+ _menuLoop.attachFader(&_menuFader);
+ _menuLoop.initFromAIFFFile("Sounds/Main Menu.aiff");
+
+ updateDisplay();
+}
+
+MainMenu::~MainMenu() {
+ if (_menuLoop.isPlaying())
+ stopMainMenuLoop();
+}
+
+void MainMenu::startMainMenuLoop() {
+ FaderMoveSpec spec;
+
+ _menuLoop.loopSound();
+ spec.makeTwoKnotFaderSpec(30, 0, 0, 30, 255);
+ _menuFader.startFaderSync(spec);
+}
+
+void MainMenu::stopMainMenuLoop() {
+ FaderMoveSpec spec;
+
+ spec.makeTwoKnotFaderSpec(30, 0, 255, 30, 0);
+ _menuFader.startFaderSync(spec);
+ _menuLoop.stopSound();
+}
+
+void MainMenu::handleInput(const Input &input, const Hotspot *cursorSpot) {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+ bool isDemo = vm->isDemo();
+
+ if (input.upButtonDown()) {
+ if (_menuSelection > (isDemo ? kFirstSelectionDemo : kFirstSelection)) {
+ _menuSelection--;
+ updateDisplay();
+ }
+ } else if (input.downButtonDown()) {
+ if (_menuSelection < (isDemo ? kLastSelectionDemo : kLastSelection)) {
+ _menuSelection++;
+ updateDisplay();
+ }
+ } else if (!isDemo && (input.leftButtonDown() || input.rightButtonDown())) {
+ if (_menuSelection == kMainMenuDifficulty) {
+ _adventureMode = !_adventureMode;
+ updateDisplay();
+ }
+ } else if (JMPPPInput::isMenuButtonPressInput(input)) {
+ if (isDemo) {
+ switch (_menuSelection) {
+ case kMainMenuCreditsDemo:
+ _creditsButton.show();
+ vm->delayShell(kMenuButtonHiliteTime, kMenuButtonHiliteScale);
+ _creditsButton.hide();
+ setLastCommand(kMenuCmdCredits);
+ break;
+ case kMainMenuStartDemo:
+ _startButton.show();
+ vm->delayShell(kMenuButtonHiliteTime, kMenuButtonHiliteScale);
+ _startButton.hide();
+ setLastCommand(kMenuCmdStartAdventure);
+ break;
+ case kMainMenuQuitDemo:
+ _quitButton.show();
+ vm->delayShell(kMenuButtonHiliteTime, kMenuButtonHiliteScale);
+ _quitButton.hide();
+ setLastCommand(kMenuCmdQuit);
+ break;
+ }
+ } else {
+ switch (_menuSelection) {
+ case kMainMenuOverview:
+ _overviewButton.show();
+ vm->delayShell(kMenuButtonHiliteTime, kMenuButtonHiliteScale);
+ _overviewButton.hide();
+ setLastCommand(kMenuCmdOverview);
+ break;
+ case kMainMenuRestore:
+ _restoreButton.show();
+ vm->delayShell(kMenuButtonHiliteTime, kMenuButtonHiliteScale);
+ _restoreButton.hide();
+ setLastCommand(kMenuCmdRestore);
+ break;
+ case kMainMenuCredits:
+ _creditsButton.show();
+ vm->delayShell(kMenuButtonHiliteTime, kMenuButtonHiliteScale);
+ _creditsButton.hide();
+ setLastCommand(kMenuCmdCredits);
+ break;
+ case kMainMenuStart:
+ _startButton.show();
+ vm->delayShell(kMenuButtonHiliteTime, kMenuButtonHiliteScale);
+ _startButton.hide();
+ if (_adventureMode)
+ setLastCommand(kMenuCmdStartAdventure);
+ else
+ setLastCommand(kMenuCmdStartWalkthrough);
+ break;
+ case kMainMenuDifficulty:
+ _adventureMode = !_adventureMode;
+ updateDisplay();
+ break;
+ case kMainMenuQuit:
+ _quitButton.show();
+ vm->delayShell(kMenuButtonHiliteTime, kMenuButtonHiliteScale);
+ _quitButton.hide();
+ setLastCommand(kMenuCmdQuit);
+ break;
+ }
+ }
+ }
+
+ InputHandler::handleInput(input, cursorSpot);
+}
+
+void MainMenu::updateDisplay() {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ if (vm->isDemo()) {
+ switch (_menuSelection) {
+ case kMainMenuStartDemo:
+ _smallSelect.moveElementTo(kStartSelectLeftDemo, kStartSelectTopDemo);
+ _smallSelect.show();
+ _largeSelect.hide();
+ break;
+ case kMainMenuCreditsDemo:
+ _smallSelect.moveElementTo(kCreditsSelectLeftDemo, kCreditsSelectTopDemo);
+ _smallSelect.show();
+ _largeSelect.hide();
+ break;
+ case kMainMenuQuitDemo:
+ _largeSelect.moveElementTo(kMainMenuQuitSelectLeftDemo, kMainMenuQuitSelectTopDemo);
+ _largeSelect.show();
+ _smallSelect.hide();
+ break;
+ }
+ } else {
+ switch (_menuSelection) {
+ case kMainMenuOverview:
+ _largeSelect.moveElementTo(kOverviewSelectLeft, kOverviewSelectTop);
+ _largeSelect.show();
+ _smallSelect.hide();
+ break;
+ case kMainMenuRestore:
+ _smallSelect.moveElementTo(kRestoreSelectLeft, kRestoreSelectTop);
+ _smallSelect.show();
+ _largeSelect.hide();
+ break;
+ case kMainMenuDifficulty:
+ if (_adventureMode) {
+ _adventureButton.show();
+ _walkthroughButton.hide();
+ } else {
+ _walkthroughButton.show();
+ _adventureButton.hide();
+ }
+
+ _largeSelect.moveElementTo(kDifficultySelectLeft, kDifficultySelectTop);
+ _largeSelect.show();
+ _smallSelect.hide();
+ break;
+ case kMainMenuStart:
+ _smallSelect.moveElementTo(kStartSelectLeft, kStartSelectTop);
+ _smallSelect.show();
+ _largeSelect.hide();
+ break;
+ case kMainMenuCredits:
+ _smallSelect.moveElementTo(kCreditsSelectLeft, kCreditsSelectTop);
+ _smallSelect.show();
+ _largeSelect.hide();
+ break;
+ case kMainMenuQuit:
+ _smallSelect.moveElementTo(kMainMenuQuitSelectLeft, kMainMenuQuitSelectTop);
+ _smallSelect.show();
+ _largeSelect.hide();
+ break;
+ }
+
+ vm->resetIntroTimer();
+ }
+}
+
+enum {
+ kCreditsMenuCoreTeam,
+ kCreditsMenuSupportTeam,
+ kCreditsMenuOriginalTeam,
+ kCreditsMenuTalent,
+ kCreditsMenuOtherTitles,
+ kCreditsMenuMainMenu,
+
+ kCreditsFirstSelection = kCreditsMenuCoreTeam,
+ kCreditsLastSelection = kCreditsMenuMainMenu
+};
+
+static const CoordType kCreditsMovieLeft = 288;
+static const CoordType kCreditsMovieTop = 0;
+
+static const CoordType kCoreTeamSelectLeft = 40;
+static const CoordType kCoreTeamSelectTop = 223;
+
+static const CoordType kSupportTeamSelectLeft = 40;
+static const CoordType kSupportTeamSelectTop = 259;
+
+static const CoordType kOriginalTeamSelectLeft = 40;
+static const CoordType kOriginalTeamSelectTop = 295;
+
+static const CoordType kTalentSelectLeft = 40;
+static const CoordType kTalentSelectTop = 331;
+
+static const CoordType kOtherTitlesSelectLeft = 40;
+static const CoordType kOtherTitlesSelectTop = 367;
+
+static const CoordType kCreditsMainMenuLeft = 32;
+static const CoordType kCreditsMainMenuTop = 412;
+
+static const CoordType kCreditsMainMenuSelectLeft = 30;
+static const CoordType kCreditsMainMenuSelectTop = 408;
+
+static const TimeValue kCoreTeamTime = 0;
+static const TimeValue kSupportTeamTime = 1920;
+static const TimeValue kOriginalTeamTime = 3000;
+static const TimeValue kTalentTime = 4440;
+static const TimeValue kOtherTitlesTime = 4680;
+
+static const TimeValue kFrameIncrement = 120; // Three frames...
+
+// Never set the current input handler to the CreditsMenu.
+CreditsMenu::CreditsMenu() : GameMenu(kCreditsMenuID), _menuBackground(0), _creditsMovie(0),
+ _mainMenuButton(0), _largeSelect(0), _smallSelect(0) {
+
+ _menuBackground.initFromPICTFile("Images/Credits/CredScrn.pict");
+ _menuBackground.setDisplayOrder(0);
+ _menuBackground.startDisplaying();
+ _menuBackground.show();
+
+ _creditsMovie.initFromMovieFile("Images/Credits/Credits.movie");
+ _creditsMovie.setDisplayOrder(1);
+ _creditsMovie.moveElementTo(kCreditsMovieLeft, kCreditsMovieTop);
+ _creditsMovie.startDisplaying();
+ _creditsMovie.show();
+ _creditsMovie.redrawMovieWorld();
+
+ _mainMenuButton.initFromPICTFile("Images/Credits/MainMenu.pict");
+ _mainMenuButton.setDisplayOrder(1);
+ _mainMenuButton.moveElementTo(kCreditsMainMenuLeft, kCreditsMainMenuTop);
+ _mainMenuButton.startDisplaying();
+
+ _largeSelect.initFromPICTFile("Images/Credits/SelectL.pict", true);
+ _largeSelect.setDisplayOrder(2);
+ _largeSelect.moveElementTo(kCreditsMainMenuSelectLeft, kCreditsMainMenuSelectTop);
+ _largeSelect.startDisplaying();
+
+ _smallSelect.initFromPICTFile("Images/Credits/SelectS.pict", true);
+ _smallSelect.setDisplayOrder(2);
+ _smallSelect.show();
+ _smallSelect.startDisplaying();
+
+ _menuSelection = -1;
+
+ newMenuSelection(kCreditsMenuCoreTeam);
+}
+
+// Assumes the new selection is never more than one away from the old...
+void CreditsMenu::newMenuSelection(const int newSelection) {
+ if (newSelection != _menuSelection) {
+ switch (newSelection) {
+ case kCreditsMenuCoreTeam:
+ _smallSelect.moveElementTo(kCoreTeamSelectLeft, kCoreTeamSelectTop);
+ _creditsMovie.setTime(kCoreTeamTime);
+ _creditsMovie.redrawMovieWorld();
+ break;
+ case kCreditsMenuSupportTeam:
+ _smallSelect.moveElementTo(kSupportTeamSelectLeft, kSupportTeamSelectTop);
+ _creditsMovie.setTime(kSupportTeamTime);
+ _creditsMovie.redrawMovieWorld();
+ break;
+ case kCreditsMenuOriginalTeam:
+ _smallSelect.moveElementTo(kOriginalTeamSelectLeft, kOriginalTeamSelectTop);
+ _creditsMovie.setTime(kOriginalTeamTime);
+ _creditsMovie.redrawMovieWorld();
+ break;
+ case kCreditsMenuTalent:
+ _smallSelect.moveElementTo(kTalentSelectLeft, kTalentSelectTop);
+ _creditsMovie.setTime(kTalentTime);
+ _creditsMovie.redrawMovieWorld();
+ break;
+ case kCreditsMenuOtherTitles:
+ _smallSelect.moveElementTo(kOtherTitlesSelectLeft, kOtherTitlesSelectTop);
+ _smallSelect.show();
+ _largeSelect.hide();
+ _creditsMovie.setTime(kOtherTitlesTime);
+ _creditsMovie.redrawMovieWorld();
+ break;
+ case kCreditsMenuMainMenu:
+ _smallSelect.hide();
+ _largeSelect.show();
+ break;
+ }
+
+ _menuSelection = newSelection;
+ }
+}
+
+void CreditsMenu::newMovieTime(const TimeValue newTime) {
+ if (newTime < kSupportTeamTime) {
+ _smallSelect.moveElementTo(kCoreTeamSelectLeft, kCoreTeamSelectTop);
+ _menuSelection = kCreditsMenuCoreTeam;
+ } else if (newTime < kOriginalTeamTime) {
+ _smallSelect.moveElementTo(kSupportTeamSelectLeft, kSupportTeamSelectTop);
+ _menuSelection = kCreditsMenuSupportTeam;
+ } else if (newTime < kTalentTime) {
+ _smallSelect.moveElementTo(kOriginalTeamSelectLeft, kOriginalTeamSelectTop);
+ _menuSelection = kCreditsMenuOriginalTeam;
+ } else if (newTime < kOtherTitlesTime) {
+ _smallSelect.moveElementTo(kTalentSelectLeft, kTalentSelectTop);
+ _smallSelect.show();
+ _largeSelect.hide();
+ _menuSelection = kCreditsMenuTalent;
+ } else if ((int)newTime == -120) {
+ // HACK: Avoid getting sent to the bottom button in the default case
+ return;
+ } else {
+ _smallSelect.moveElementTo(kOtherTitlesSelectLeft, kOtherTitlesSelectTop);
+ _smallSelect.show();
+ _largeSelect.hide();
+ _menuSelection = kCreditsMenuOtherTitles;
+ }
+
+ _creditsMovie.setTime(newTime);
+ _creditsMovie.redrawMovieWorld();
+}
+
+void CreditsMenu::handleInput(const Input &input, const Hotspot *cursorSpot) {
+ if (input.upButtonDown()) {
+ if (_menuSelection > kCreditsFirstSelection)
+ newMenuSelection(_menuSelection - 1);
+ } else if (input.downButtonDown()) {
+ if (_menuSelection < kCreditsLastSelection)
+ newMenuSelection(_menuSelection + 1);
+ } else if (input.leftButtonDown()) {
+ newMovieTime(_creditsMovie.getTime() - kFrameIncrement);
+ } else if (input.rightButtonDown()) {
+ newMovieTime(_creditsMovie.getTime() + kFrameIncrement);
+ } else if (JMPPPInput::isMenuButtonPressInput(input)) {
+ if (_menuSelection == kCreditsMenuMainMenu) {
+ _mainMenuButton.show();
+ ((PegasusEngine *)g_engine)->delayShell(kMenuButtonHiliteTime, kMenuButtonHiliteScale);
+ _mainMenuButton.hide();
+ setLastCommand(kMenuCmdCreditsMainMenu);
+ }
+ }
+
+ InputHandler::handleInput(input, cursorSpot);
+}
+
+static const CoordType kContinueLeft = 44;
+static const CoordType kContinueTop = 336;
+
+static const CoordType kContinueSelectLeft = 40;
+static const CoordType kContinueSelectTopDemo = 331;
+static const CoordType kContinueSelectTop = 332;
+
+static const CoordType kMainMenuLeftDemo = 44;
+static const CoordType kMainMenuTopDemo = 372;
+
+static const CoordType kMainMenuSelectLeftDemo = 40;
+static const CoordType kMainMenuSelectTopDemo = 367;
+
+static const CoordType kQuitLeftDemo = 32;
+static const CoordType kQuitTopDemo = 412;
+
+static const CoordType kQuitSelectLeftDemo = 28;
+static const CoordType kQuitSelectTopDemo = 408;
+
+static const CoordType kRestoreLeftDeath = 44;
+static const CoordType kRestoreTopDeath = 372;
+
+static const CoordType kRestoreSelectLeftDeath = 40;
+static const CoordType kRestoreSelectTopDeath = 368;
+
+static const CoordType kMainMenuLeft = 32;
+static const CoordType kMainMenuTop = 412;
+
+static const CoordType kMainMenuSelectLeft = 28;
+static const CoordType kMainMenuSelectTop = 408;
+
+enum {
+ kDeathScreenContinueDemo = 0,
+ kDeathScreenMainMenuDemo,
+ kDeathScreenQuitDemo,
+
+ kFirstDeathSelectionDemo = kDeathScreenContinueDemo,
+ kLastDeathSelectionDemo = kDeathScreenQuitDemo,
+
+ kDeathScreenContinue = 0,
+ kDeathScreenRestore,
+ kDeathScreenMainMenu,
+
+ kFirstDeathSelection = kDeathScreenContinue,
+ kLastDeathSelection = kDeathScreenMainMenu
+};
+
+// Never set the current input handler to the DeathMenu.
+DeathMenu::DeathMenu(const DeathReason deathReason) : GameMenu(kDeathMenuID), _deathBackground(0), _continueButton(0),
+ _mainMenuButton(0), _quitButton(0), _restoreButton(0), _largeSelect(0), _smallSelect(0) {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+ bool isDemo = vm->isDemo();
+
+ _playerWon = (deathReason == kPlayerWonGame);
+
+ Common::String prefix = "Images/";
+ Common::String imageName;
+ if (isDemo) {
+ prefix += "Demo/";
+ imageName = prefix;
+
+ switch (deathReason) {
+ case kDeathFallOffCliff:
+ imageName += "dPfall";
+ break;
+ case kDeathEatenByDinosaur:
+ imageName += "dPdino";
+ break;
+ case kDeathStranded:
+ imageName += "dPstuck";
+ break;
+ default:
+ imageName += "dPdemowin";
+ break;
+ }
+
+ imageName += ".pict";
+ } else {
+ prefix += "Death Screens/";
+ imageName = prefix;
+
+ static const char *fileNames[] = {
+ "dAunmade", "dAbombed", "dAshot", "dAassass", "dAnuked",
+ "dTunmade", "dTshot", "dPfall", "dPdino", "dPstuck",
+ "dNchoke", "dNcaught", "dNcaught", "dNsub", "dNrobot1",
+ "dNrobot2", "dMfall", "dMcaught", "dMtracks", "dMrobot",
+ "dMtoast", "dMexplo1", "dMexplo2", "dMchoke1", "dMchoke2",
+ "dMdroid", "dMfall", "dMgears", "dMshutt1", "dMshutt2",
+ "dWpoison", "dWcaught", "dWplasma", "dWshot", "dAfinale"
+ };
+
+ imageName += fileNames[deathReason - 1];
+ imageName += ".pict";
+ }
+
+ _deathBackground.initFromPICTFile(imageName);
+ _deathReason = deathReason;
+
+ if (!isDemo) {
+ vm->_gfx->setCurSurface(_deathBackground.getSurface());
+ drawAllScores();
+ vm->_gfx->setCurSurface(vm->_gfx->getWorkArea());
+ }
+
+ _deathBackground.setDisplayOrder(0);
+ _deathBackground.startDisplaying();
+ _deathBackground.show();
+
+ if (isDemo) {
+ if (_playerWon) // Make credits button...
+ _continueButton.initFromPICTFile(prefix + "Credits.pict");
+ else // Make continue button...
+ _continueButton.initFromPICTFile(prefix + "Continue.pict");
+
+ _mainMenuButton.initFromPICTFile(prefix + "MainMenu.pict");
+ _mainMenuButton.setDisplayOrder(1);
+ _mainMenuButton.moveElementTo(kMainMenuLeftDemo, kMainMenuTopDemo);
+ _mainMenuButton.startDisplaying();
+
+ _quitButton.initFromPICTFile(prefix + "Quit.pict");
+ _quitButton.setDisplayOrder(1);
+ _quitButton.moveElementTo(kQuitLeftDemo, kQuitTopDemo);
+ _quitButton.startDisplaying();
+
+ _menuSelection = kDeathScreenContinueDemo;
+ } else {
+ if (!_playerWon) {
+ _mainMenuButton.initFromPICTFile(prefix + "MainMenu.pict");
+ _mainMenuButton.setDisplayOrder(1);
+ _mainMenuButton.moveElementTo(kMainMenuLeft, kMainMenuTop);
+ _mainMenuButton.startDisplaying();
+
+ _restoreButton.initFromPICTFile(prefix + "Restore.pict");
+ _restoreButton.setDisplayOrder(1);
+ _restoreButton.moveElementTo(kRestoreLeftDeath, kRestoreTopDeath);
+ _restoreButton.startDisplaying();
+ }
+
+ _continueButton.initFromPICTFile(prefix + "Continue.pict");
+
+ _menuSelection = kDeathScreenContinue;
+ }
+
+ _smallSelect.initFromPICTFile(prefix + "SelectS.pict", true);
+ _smallSelect.setDisplayOrder(2);
+ _smallSelect.startDisplaying();
+
+ _continueButton.setDisplayOrder(1);
+ _continueButton.moveElementTo(kContinueLeft, kContinueTop);
+ _continueButton.startDisplaying();
+
+ if (isDemo || !_playerWon) {
+ _largeSelect.initFromPICTFile(prefix + "SelectL.pict", true);
+ _largeSelect.setDisplayOrder(2);
+ _largeSelect.startDisplaying();
+ } else {
+ _triumphSound.initFromQuickTime("Sounds/Caldoria/Galactic Triumph");
+ _triumphSound.playSound();
+ }
+
+ updateDisplay();
+}
+
+void DeathMenu::handleInput(const Input &input, const Hotspot *cursorSpot) {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ if (input.upButtonDown()) {
+ if (_menuSelection > (vm->isDemo() ? kFirstDeathSelectionDemo : kFirstDeathSelection)) {
+ _menuSelection--;
+ updateDisplay();
+ }
+ } else if (input.downButtonDown() && (vm->isDemo() || !_playerWon)) {
+ if (_menuSelection < (vm->isDemo() ? kLastDeathSelectionDemo : kLastDeathSelection)) {
+ _menuSelection++;
+ updateDisplay();
+ }
+ } else if (JMPPPInput::isMenuButtonPressInput(input)) {
+ if (vm->isDemo()) {
+ switch (_menuSelection) {
+ case kDeathScreenContinueDemo:
+ _continueButton.show();
+ vm->delayShell(kMenuButtonHiliteTime, kMenuButtonHiliteScale);
+ _continueButton.hide();
+ setLastCommand(kMenuCmdDeathContinue);
+ break;
+ case kDeathScreenQuitDemo:
+ _quitButton.show();
+ vm->delayShell(kMenuButtonHiliteTime, kMenuButtonHiliteScale);
+ _quitButton.hide();
+ setLastCommand(kMenuCmdDeathQuitDemo);
+ break;
+ case kDeathScreenMainMenuDemo:
+ _mainMenuButton.show();
+ vm->delayShell(kMenuButtonHiliteTime, kMenuButtonHiliteScale);
+ _mainMenuButton.hide();
+ setLastCommand(kMenuCmdDeathMainMenuDemo);
+ break;
+ }
+ } else {
+ switch (_menuSelection) {
+ case kDeathScreenContinue:
+ _continueButton.show();
+ vm->delayShell(kMenuButtonHiliteTime, kMenuButtonHiliteScale);
+ _continueButton.hide();
+ setLastCommand(kMenuCmdDeathContinue);
+ break;
+ case kDeathScreenRestore:
+ _restoreButton.show();
+ vm->delayShell(kMenuButtonHiliteTime, kMenuButtonHiliteScale);
+ _restoreButton.hide();
+ setLastCommand(kMenuCmdDeathRestore);
+ break;
+ case kDeathScreenMainMenu:
+ _mainMenuButton.show();
+ vm->delayShell(kMenuButtonHiliteTime, kMenuButtonHiliteScale);
+ _mainMenuButton.hide();
+ setLastCommand(kMenuCmdDeathMainMenu);
+ break;
+ }
+ }
+ }
+
+ InputHandler::handleInput(input, cursorSpot);
+}
+
+void DeathMenu::updateDisplay() {
+ if (((PegasusEngine *)g_engine)->isDemo()) {
+ switch (_menuSelection) {
+ case kDeathScreenContinueDemo:
+ _smallSelect.moveElementTo(kContinueSelectLeft, kContinueSelectTopDemo);
+ _smallSelect.show();
+ _largeSelect.hide();
+ break;
+ case kDeathScreenQuitDemo:
+ _largeSelect.moveElementTo(kQuitSelectLeftDemo, kQuitSelectTopDemo);
+ _largeSelect.show();
+ _smallSelect.hide();
+ break;
+ case kDeathScreenMainMenuDemo:
+ _smallSelect.moveElementTo(kMainMenuSelectLeftDemo, kMainMenuSelectTopDemo);
+ _smallSelect.show();
+ _largeSelect.hide();
+ break;
+ }
+ } else {
+ switch (_menuSelection) {
+ case kDeathScreenContinue:
+ _smallSelect.moveElementTo(kContinueSelectLeft, kContinueSelectTop);
+ _smallSelect.show();
+ _largeSelect.hide();
+ break;
+ case kDeathScreenRestore:
+ _smallSelect.moveElementTo(kRestoreSelectLeftDeath, kRestoreSelectTopDeath);
+ _smallSelect.show();
+ _largeSelect.hide();
+ break;
+ case kDeathScreenMainMenu:
+ _largeSelect.moveElementTo(kMainMenuSelectLeft, kMainMenuSelectTop);
+ _largeSelect.show();
+ _smallSelect.hide();
+ break;
+ }
+ }
+}
+
+void DeathMenu::drawAllScores() {
+ Surface numbers;
+ numbers.getImageFromPICTFile("Images/Death Screens/Numbers.pict");
+
+ Common::Rect scoreBounds;
+ GameScoreType caldoriaTotal = 0;
+
+ switch (_deathReason) {
+ case kDeathCardBomb:
+ case kDeathShotBySinclair:
+ case kDeathSinclairShotDelegate:
+ case kDeathNuclearExplosion:
+ case kDeathGassedInNorad:
+ case kDeathWokeUpNorad:
+ case kDeathArrestedInNorad:
+ case kDeathSubDestroyed:
+ case kDeathRobotThroughNoradDoor:
+ case kDeathRobotSubControlRoom:
+ case kDeathWrongShuttleLock:
+ case kDeathArrestedInMars:
+ case kDeathRunOverByPod:
+ case kDeathDidntGetOutOfWay:
+ case kDeathReactorBurn:
+ case kDeathDidntFindMarsBomb:
+ case kDeathDidntDisarmMarsBomb:
+ case kDeathNoMaskInMaze:
+ case kDeathNoAirInMaze:
+ case kDeathGroundByMazebot:
+ case kDeathMissedOreBucket:
+ case kDeathDidntLeaveBucket:
+ case kDeathRanIntoCanyonWall:
+ case kDeathRanIntoSpaceJunk:
+ case kDeathDidntStopPoison:
+ case kDeathArrestedInWSC:
+ case kDeathHitByPlasma:
+ case kDeathShotOnCatwalk:
+ case kPlayerWonGame:
+ caldoriaTotal += kMaxCaldoriaTSAScoreAfter;
+ scoreBounds = Common::Rect(kDeathScreenScoreLeft, kDeathScreenScoreTop - kDeathScreenScoreSkipVert * 5,
+ kDeathScreenScoreLeft + kDeathScreenScoreWidth, kDeathScreenScoreTop - kDeathScreenScoreSkipVert * 5 + kDeathScreenScoreHeight);
+ drawScore(GameState.getGandhiScore(), kMaxGandhiScore, scoreBounds, &numbers);
+
+ scoreBounds.translate(0, kDeathScreenScoreSkipVert);
+ drawScore(GameState.getWSCScore(), kMaxWSCScore, scoreBounds, &numbers);
+
+ scoreBounds.translate(0, kDeathScreenScoreSkipVert);
+ drawScore(GameState.getNoradScore(), kMaxNoradScore, scoreBounds, &numbers);
+
+ scoreBounds.translate(0, kDeathScreenScoreSkipVert);
+ drawScore(GameState.getMarsScore(), kMaxMarsScore, scoreBounds, &numbers);
+ // fall through
+ case kDeathFallOffCliff:
+ case kDeathEatenByDinosaur:
+ case kDeathStranded:
+ case kDeathShotByTSARobots:
+ scoreBounds = Common::Rect(kDeathScreenScoreLeft, kDeathScreenScoreTop - kDeathScreenScoreSkipVert,
+ kDeathScreenScoreLeft + kDeathScreenScoreWidth, kDeathScreenScoreTop - kDeathScreenScoreSkipVert + kDeathScreenScoreHeight);
+ drawScore(GameState.getPrehistoricScore(), kMaxPrehistoricScore, scoreBounds, &numbers);
+ // fall through
+ case kDeathUncreatedInCaldoria:
+ case kDeathUncreatedInTSA:
+ scoreBounds = Common::Rect(kDeathScreenScoreLeft, kDeathScreenScoreTop, kDeathScreenScoreLeft + kDeathScreenScoreWidth,
+ kDeathScreenScoreTop + kDeathScreenScoreHeight);
+ caldoriaTotal += kMaxCaldoriaTSAScoreBefore;
+ drawScore(GameState.getCaldoriaTSAScore(), caldoriaTotal, scoreBounds, &numbers);
+
+ scoreBounds = Common::Rect(kDeathScreenScoreLeft, kDeathScreenScoreTop - kDeathScreenScoreSkipVert * 6,
+ kDeathScreenScoreLeft + kDeathScreenScoreWidth, kDeathScreenScoreTop - kDeathScreenScoreSkipVert * 6 + kDeathScreenScoreHeight);
+
+ drawScore(GameState.getTotalScore(), kMaxTotalScore, scoreBounds, &numbers);
+ break;
+ }
+}
+
+enum {
+ kPauseMenuSave,
+ kPauseMenuContinue,
+ kPauseMenuRestore,
+ kPauseMenuSoundFX,
+ kPauseMenuAmbience,
+ kPauseMenuWalkthru,
+ kPauseMenuQuitToMainMenu,
+
+ kFirstPauseSelection = kPauseMenuSave,
+ kLastPauseSelection = kPauseMenuQuitToMainMenu
+};
+
+static const CoordType kPauseLeft = 194;
+static const CoordType kPauseTop = 68;
+
+static const CoordType kSaveGameLeft = kPauseLeft + 6;
+static const CoordType kSaveGameTop = kPauseTop + 56;
+
+static const CoordType kSaveGameSelectLeft = kPauseLeft - 44;
+static const CoordType kSaveGameSelectTop = kPauseTop + 52;
+
+static const CoordType kPauseContinueLeft = kPauseLeft + 18;
+static const CoordType kPauseContinueTop = kPauseTop + 100;
+
+static const CoordType kPauseContinueSelectLeft = kPauseLeft - 44;
+static const CoordType kPauseContinueSelectTop = kPauseTop + 95;
+
+static const CoordType kPauseRestoreLeft = kPauseLeft + 18;
+static const CoordType kPauseRestoreTop = kPauseTop + 136;
+
+static const CoordType kPauseRestoreSelectLeft = kPauseLeft - 44;
+static const CoordType kPauseRestoreSelectTop = kPauseTop + 131;
+
+static const CoordType kSoundFXLeft = kPauseLeft + 128;
+static const CoordType kSoundFXTop = kPauseTop + 187;
+static const CoordType kSoundFXRight = kSoundFXLeft + 96;
+static const CoordType kSoundFXBottom = kSoundFXTop + 14;
+
+static const CoordType kSoundFXSelectLeft = kPauseLeft - 44;
+static const CoordType kSoundFXSelectTop = kPauseTop + 172;
+
+static const CoordType kAmbienceLeft = kPauseLeft + 128;
+static const CoordType kAmbienceTop = kPauseTop + 227;
+static const CoordType kAmbienceRight = kAmbienceLeft + 96;
+static const CoordType kAmbienceBottom = kAmbienceTop + 14;
+
+static const CoordType kAmbienceSelectLeft = kPauseLeft - 44;
+static const CoordType kAmbienceSelectTop = kPauseTop + 212;
+
+static const CoordType kWalkthruLeft = kPauseLeft + 128;
+static const CoordType kWalkthruTop = kPauseTop + 264;
+
+static const CoordType kWalkthruSelectLeft = kPauseLeft - 44;
+static const CoordType kWalkthruSelectTop = kPauseTop + 255;
+
+static const CoordType kQuitLeft = kPauseLeft + 18;
+static const CoordType kQuitTop = kPauseTop + 302;
+
+static const CoordType kQuitSelectLeft = kPauseLeft - 44;
+static const CoordType kQuitSelectTop = kPauseTop + 297;
+
+// These are relative to the pause background.
+static const CoordType kPauseScoreLeft = 130;
+static const CoordType kPauseScoreTop = 34;
+static const CoordType kPauseScoreRight = kPauseScoreLeft + 108;
+static const CoordType kPauseScoreBottom = kPauseScoreTop + 12;
+
+// Never set the current input handler to the CPauseMenu.
+PauseMenu::PauseMenu() : GameMenu(kPauseMenuID), _pauseBackground(0), _saveButton(0), _restoreButton(0),
+ _walkthroughButton(0), _continueButton(0), _soundFXLevel(0), _ambienceLevel(0), _quitButton(0),
+ _largeSelect(0), _smallSelect(0) {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ _pauseBackground.initFromPICTFile("Images/Pause Screen/PausScrn.pict", true);
+
+ if (!vm->isDemo()) {
+ Surface numbers;
+ numbers.getImageFromPICTFile("Images/Pause Screen/Numbers.pict");
+ vm->_gfx->setCurSurface(_pauseBackground.getSurface());
+ drawScore(GameState.getTotalScore(), kMaxTotalScore,
+ Common::Rect(kPauseScoreLeft, kPauseScoreTop, kPauseScoreRight, kPauseScoreBottom), &numbers);
+ vm->_gfx->setCurSurface(vm->_gfx->getWorkArea());
+ }
+
+ _pauseBackground.setDisplayOrder(kPauseMenuOrder);
+ _pauseBackground.moveElementTo(kPauseLeft, kPauseTop);
+ _pauseBackground.startDisplaying();
+ _pauseBackground.show();
+
+ if (!vm->isDemo()) {
+ _saveButton.initFromPICTFile("Images/Pause Screen/SaveGame.pict");
+ _saveButton.setDisplayOrder(kSaveGameOrder);
+ _saveButton.moveElementTo(kSaveGameLeft, kSaveGameTop);
+ _saveButton.startDisplaying();
+
+ _restoreButton.initFromPICTFile("Images/Pause Screen/Restore.pict");
+ _restoreButton.setDisplayOrder(kRestoreOrder);
+ _restoreButton.moveElementTo(kPauseRestoreLeft, kPauseRestoreTop);
+ _restoreButton.startDisplaying();
+
+ _walkthroughButton.initFromPICTFile("Images/Pause Screen/Walkthru.pict");
+ _walkthroughButton.setDisplayOrder(kWalkthruOrder);
+ _walkthroughButton.moveElementTo(kWalkthruLeft, kWalkthruTop);
+ _walkthroughButton.startDisplaying();
+
+ if (GameState.getWalkthroughMode())
+ _walkthroughButton.show();
+ }
+
+ _continueButton.initFromPICTFile("Images/Pause Screen/Continue.pict");
+ _continueButton.setDisplayOrder(kContinueOrder);
+ _continueButton.moveElementTo(kPauseContinueLeft, kPauseContinueTop);
+ _continueButton.startDisplaying();
+
+ _soundFXLevel.setDisplayOrder(kSoundFXOrder);
+ _soundFXLevel.setBounds(Common::Rect(kSoundFXLeft, kSoundFXTop, kSoundFXRight, kSoundFXBottom));
+ _soundFXLevel.startDisplaying();
+ _soundFXLevel.show();
+ _soundFXLevel.setSoundLevel(vm->getSoundFXLevel());
+
+ _ambienceLevel.setDisplayOrder(kAmbienceOrder);
+ _ambienceLevel.setBounds(Common::Rect(kAmbienceLeft, kAmbienceTop, kAmbienceRight, kAmbienceBottom));
+ _ambienceLevel.startDisplaying();
+ _ambienceLevel.show();
+ _ambienceLevel.setSoundLevel(vm->getAmbienceLevel());
+
+ _quitButton.initFromPICTFile("Images/Pause Screen/Quit2MM.pict");
+ _quitButton.setDisplayOrder(kQuitToMainMenuOrder);
+ _quitButton.moveElementTo(kQuitLeft, kQuitTop);
+ _quitButton.startDisplaying();
+
+ _largeSelect.initFromPICTFile("Images/Pause Screen/SelectL.pict", true);
+ _largeSelect.setDisplayOrder(kPauseLargeHiliteOrder);
+ _largeSelect.startDisplaying();
+
+ _smallSelect.initFromPICTFile("Images/Pause Screen/SelectS.pict", true);
+ _smallSelect.setDisplayOrder(kPauseSmallHiliteOrder);
+ _smallSelect.startDisplaying();
+
+ _menuSelection = (vm->isDemo()) ? kPauseMenuContinue : kPauseMenuSave;
+
+ updateDisplay();
+}
+
+void PauseMenu::handleInput(const Input &input, const Hotspot *cursorSpot) {
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ if (input.upButtonDown()) {
+ if (vm->isDemo()) {
+ if (_menuSelection > kPauseMenuContinue) {
+ switch (_menuSelection) {
+ case kPauseMenuSoundFX:
+ _menuSelection = kPauseMenuContinue;
+ break;
+ case kPauseMenuAmbience:
+ _menuSelection = kPauseMenuSoundFX;
+ break;
+ case kPauseMenuQuitToMainMenu:
+ _menuSelection = kPauseMenuAmbience;
+ break;
+ }
+ updateDisplay();
+ }
+ } else {
+ if (_menuSelection > kFirstPauseSelection) {
+ _menuSelection--;
+ updateDisplay();
+ }
+ }
+ } else if (input.downButtonDown()) {
+ if (vm->isDemo()) {
+ if (_menuSelection < kPauseMenuQuitToMainMenu) {
+ switch (_menuSelection) {
+ case kPauseMenuContinue:
+ _menuSelection = kPauseMenuSoundFX;
+ break;
+ case kPauseMenuSoundFX:
+ _menuSelection = kPauseMenuAmbience;
+ break;
+ case kPauseMenuAmbience:
+ _menuSelection = kPauseMenuQuitToMainMenu;
+ break;
+ }
+ updateDisplay();
+ }
+ } else {
+ if (_menuSelection < kLastPauseSelection) {
+ _menuSelection++;
+ updateDisplay();
+ }
+ }
+ } else if (input.leftButtonDown()) {
+ if (_menuSelection == kPauseMenuSoundFX) {
+ _soundFXLevel.decrementLevel();
+ vm->setSoundFXLevel(_soundFXLevel.getSoundLevel());
+ } else if (_menuSelection == kPauseMenuAmbience) {
+ _ambienceLevel.decrementLevel();
+ vm->setAmbienceLevel(_ambienceLevel.getSoundLevel());
+ } else if (!vm->isDemo() && _menuSelection == kPauseMenuWalkthru) {
+ GameState.setWalkthroughMode(!GameState.getWalkthroughMode());
+ if (GameState.getWalkthroughMode())
+ _walkthroughButton.show();
+ else
+ _walkthroughButton.hide();
+ }
+ } else if (input.rightButtonDown()) {
+ if (_menuSelection == kPauseMenuSoundFX) {
+ _soundFXLevel.incrementLevel();
+ vm->setSoundFXLevel(_soundFXLevel.getSoundLevel());
+ } else if (_menuSelection == kPauseMenuAmbience) {
+ _ambienceLevel.incrementLevel();
+ vm->setAmbienceLevel(_ambienceLevel.getSoundLevel());
+ } else if (!vm->isDemo() && _menuSelection == kPauseMenuWalkthru) {
+ GameState.setWalkthroughMode(!GameState.getWalkthroughMode());
+ if (GameState.getWalkthroughMode())
+ _walkthroughButton.show();
+ else
+ _walkthroughButton.hide();
+ }
+ } else if (JMPPPInput::isMenuButtonPressInput(input)) {
+ switch (_menuSelection) {
+ case kPauseMenuSave:
+ _saveButton.show();
+ vm->delayShell(kMenuButtonHiliteTime, kMenuButtonHiliteScale);
+ _saveButton.hide();
+ setLastCommand(kMenuCmdPauseSave);
+ break;
+ case kPauseMenuRestore:
+ _restoreButton.show();
+ vm->delayShell(kMenuButtonHiliteTime, kMenuButtonHiliteScale);
+ _restoreButton.hide();
+ setLastCommand(kMenuCmdPauseRestore);
+ break;
+ case kPauseMenuContinue:
+ _continueButton.show();
+ vm->delayShell(kMenuButtonHiliteTime, kMenuButtonHiliteScale);
+ _continueButton.hide();
+ setLastCommand(kMenuCmdPauseContinue);
+ break;
+ case kPauseMenuWalkthru:
+ GameState.setWalkthroughMode(!GameState.getWalkthroughMode());
+ if (GameState.getWalkthroughMode())
+ _walkthroughButton.show();
+ else
+ _walkthroughButton.hide();
+ break;
+ case kPauseMenuQuitToMainMenu:
+ _quitButton.show();
+ vm->delayShell(kMenuButtonHiliteTime, kMenuButtonHiliteScale);
+ _quitButton.hide();
+ setLastCommand(kMenuCmdPauseQuit);
+ break;
+ }
+ }
+
+ InputHandler::handleInput(input, cursorSpot);
+}
+
+void PauseMenu::updateDisplay() {
+ switch (_menuSelection) {
+ case kPauseMenuSave:
+ _largeSelect.moveElementTo(kSaveGameSelectLeft, kSaveGameSelectTop);
+ _largeSelect.show();
+ _smallSelect.hide();
+ break;
+ case kPauseMenuContinue:
+ _smallSelect.moveElementTo(kPauseContinueSelectLeft, kPauseContinueSelectTop);
+ _smallSelect.show();
+ _largeSelect.hide();
+ break;
+ case kPauseMenuRestore:
+ _smallSelect.moveElementTo(kPauseRestoreSelectLeft, kPauseRestoreSelectTop);
+ _smallSelect.show();
+ _largeSelect.hide();
+ break;
+ case kPauseMenuSoundFX:
+ _largeSelect.moveElementTo(kSoundFXSelectLeft, kSoundFXSelectTop);
+ _largeSelect.show();
+ _smallSelect.hide();
+ break;
+ case kPauseMenuAmbience:
+ _largeSelect.moveElementTo(kAmbienceSelectLeft, kAmbienceSelectTop);
+ _largeSelect.show();
+ _smallSelect.hide();
+ break;
+ case kPauseMenuWalkthru:
+ _largeSelect.moveElementTo(kWalkthruSelectLeft, kWalkthruSelectTop);
+ _largeSelect.show();
+ _smallSelect.hide();
+ break;
+ case kPauseMenuQuitToMainMenu:
+ _smallSelect.moveElementTo(kQuitSelectLeft, kQuitSelectTop);
+ _smallSelect.show();
+ _largeSelect.hide();
+ break;
+ }
+
+ ((PegasusEngine *)g_engine)->resetIntroTimer();
+}
+
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/menu.h b/engines/pegasus/menu.h
new file mode 100644
index 0000000000..288b846093
--- /dev/null
+++ b/engines/pegasus/menu.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_MENU_H
+#define PEGASUS_MENU_H
+
+#include "pegasus/constants.h"
+#include "pegasus/fader.h"
+#include "pegasus/input.h"
+#include "pegasus/movie.h"
+#include "pegasus/sound.h"
+#include "pegasus/surface.h"
+#include "pegasus/util.h"
+
+namespace Pegasus {
+
+class GameMenu : public IDObject, public InputHandler {
+public:
+ GameMenu(const uint32);
+ virtual ~GameMenu() {}
+
+ virtual void becomeCurrentHandler();
+ virtual void restorePreviousHandler();
+
+ GameMenuCommand getLastCommand() { return _lastCommand; }
+ void clearLastCommand() { _lastCommand = kMenuCmdNoCommand; }
+
+protected:
+ void setLastCommand(const GameMenuCommand command) { _lastCommand = command; }
+
+ InputHandler *_previousHandler;
+ GameMenuCommand _lastCommand;
+
+ void drawScore(GameScoreType, GameScoreType, const Common::Rect &, Surface *);
+
+private:
+ void drawNumber(GameScoreType, CoordType &, CoordType, Surface *);
+};
+
+class Hotspot;
+
+class MainMenu : public GameMenu {
+public:
+ MainMenu();
+ virtual ~MainMenu();
+
+ virtual void handleInput(const Input &input, const Hotspot *);
+ void startMainMenuLoop();
+ void stopMainMenuLoop();
+
+protected:
+ void updateDisplay();
+
+ uint32 _menuSelection;
+
+ // Full and Demo
+ Picture _menuBackground;
+ Picture _startButton;
+ Picture _creditsButton;
+ Picture _quitButton;
+ Picture _largeSelect;
+ Picture _smallSelect;
+
+ // Full only
+ bool _adventureMode;
+ Picture _overviewButton;
+ Picture _restoreButton;
+ Picture _adventureButton;
+ Picture _walkthroughButton;
+
+ Sound _menuLoop;
+ SoundFader _menuFader;
+};
+
+class CreditsMenu : public GameMenu {
+public:
+ CreditsMenu();
+ virtual ~CreditsMenu() {}
+
+ virtual void handleInput(const Input &input, const Hotspot *);
+
+protected:
+ void newMenuSelection(const int);
+ void newMovieTime(const TimeValue);
+
+ int _menuSelection;
+ Picture _menuBackground;
+ Movie _creditsMovie;
+ Picture _mainMenuButton;
+ Picture _largeSelect;
+ Picture _smallSelect;
+};
+
+class DeathMenu : public GameMenu {
+public:
+ DeathMenu(const DeathReason);
+ virtual ~DeathMenu() {}
+
+ virtual void handleInput(const Input &input, const Hotspot *);
+
+ bool playerWon() { return _playerWon; }
+
+protected:
+ void drawAllScores();
+
+ void updateDisplay();
+
+ bool _playerWon;
+ int _menuSelection;
+ DeathReason _deathReason;
+
+ Picture _deathBackground;
+ Picture _continueButton;
+ Picture _restoreButton;
+ Picture _mainMenuButton;
+ Picture _quitButton;
+
+ Picture _largeSelect;
+ Picture _smallSelect;
+
+ Sound _triumphSound;
+};
+
+class PauseMenu : public GameMenu {
+public:
+ PauseMenu();
+ virtual ~PauseMenu() {}
+
+ virtual void handleInput(const Input &input, const Hotspot *);
+
+protected:
+ void updateDisplay();
+
+ uint32 _menuSelection;
+ Picture _pauseBackground;
+ Picture _saveButton;
+ Picture _restoreButton;
+ Picture _walkthroughButton;
+ Picture _continueButton;
+ SoundLevel _soundFXLevel;
+ SoundLevel _ambienceLevel;
+ Picture _quitButton;
+ Picture _largeSelect;
+ Picture _smallSelect;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/module.mk b/engines/pegasus/module.mk
new file mode 100644
index 0000000000..cb44a04171
--- /dev/null
+++ b/engines/pegasus/module.mk
@@ -0,0 +1,100 @@
+MODULE := engines/pegasus
+
+MODULE_OBJS = \
+ compass.o \
+ console.o \
+ cursor.o \
+ detection.o \
+ elements.o \
+ energymonitor.o \
+ fader.o \
+ gamestate.o \
+ graphics.o \
+ hotspot.o \
+ input.o \
+ interface.o \
+ menu.o \
+ movie.o \
+ notification.o \
+ pegasus.o \
+ sound.o \
+ surface.o \
+ timers.o \
+ transition.o \
+ util.o \
+ ai/ai_action.o \
+ ai/ai_area.o \
+ ai/ai_condition.o \
+ ai/ai_rule.o \
+ items/autodragger.o \
+ items/inventory.o \
+ items/inventorypicture.o \
+ items/item.o \
+ items/itemdragger.o \
+ items/itemlist.o \
+ items/biochips/aichip.o \
+ items/biochips/biochipitem.o \
+ items/biochips/mapchip.o \
+ items/biochips/mapimage.o \
+ items/biochips/opticalchip.o \
+ items/biochips/pegasuschip.o \
+ items/biochips/retscanchip.o \
+ items/biochips/shieldchip.o \
+ items/inventory/airmask.o \
+ items/inventory/gascanister.o \
+ items/inventory/inventoryitem.o \
+ items/inventory/keycard.o \
+ neighborhood/door.o \
+ neighborhood/exit.o \
+ neighborhood/extra.o \
+ neighborhood/hotspotinfo.o \
+ neighborhood/neighborhood.o \
+ neighborhood/spot.o \
+ neighborhood/turn.o \
+ neighborhood/view.o \
+ neighborhood/zoom.o \
+ neighborhood/caldoria/caldoria.o \
+ neighborhood/caldoria/caldoria4dsystem.o \
+ neighborhood/caldoria/caldoriabomb.o \
+ neighborhood/caldoria/caldoriamessages.o \
+ neighborhood/caldoria/caldoriamirror.o \
+ neighborhood/mars/energybeam.o \
+ neighborhood/mars/gravitoncannon.o \
+ neighborhood/mars/hermite.o \
+ neighborhood/mars/mars.o \
+ neighborhood/mars/planetmover.o \
+ neighborhood/mars/reactor.o \
+ neighborhood/mars/robotship.o \
+ neighborhood/mars/shuttleenergymeter.o \
+ neighborhood/mars/shuttlehud.o \
+ neighborhood/mars/shuttleweapon.o \
+ neighborhood/mars/spacechase3d.o \
+ neighborhood/mars/spacejunk.o \
+ neighborhood/mars/tractorbeam.o \
+ neighborhood/norad/norad.o \
+ neighborhood/norad/noradelevator.o \
+ neighborhood/norad/pressuredoor.o \
+ neighborhood/norad/pressuretracker.o \
+ neighborhood/norad/subcontrolroom.o \
+ neighborhood/norad/subplatform.o \
+ neighborhood/norad/alpha/ecrmonitor.o \
+ neighborhood/norad/alpha/fillingstation.o \
+ neighborhood/norad/alpha/noradalpha.o \
+ neighborhood/norad/alpha/panorama.o \
+ neighborhood/norad/alpha/panoramascroll.o \
+ neighborhood/norad/delta/globegame.o \
+ neighborhood/norad/delta/noraddelta.o \
+ neighborhood/prehistoric/prehistoric.o \
+ neighborhood/tsa/fulltsa.o \
+ neighborhood/tsa/tinytsa.o \
+ neighborhood/wsc/moleculebin.o \
+ neighborhood/wsc/wsc.o
+
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_PEGASUS), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/pegasus/movie.cpp b/engines/pegasus/movie.cpp
new file mode 100644
index 0000000000..75c287c7a6
--- /dev/null
+++ b/engines/pegasus/movie.cpp
@@ -0,0 +1,280 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "graphics/surface.h"
+#include "video/qt_decoder.h"
+#include "video/video_decoder.h"
+
+#include "pegasus/movie.h"
+
+namespace Pegasus {
+
+Movie::Movie(const DisplayElementID id) : Animation(id) {
+ _video = 0;
+ setScale(600);
+}
+
+Movie::~Movie() {
+ releaseMovie();
+}
+
+// *** Make sure this will stop displaying the movie.
+
+void Movie::releaseMovie() {
+ if (_video) {
+ delete _video;
+ _video = 0;
+ disposeAllCallBacks();
+ deallocateSurface();
+ }
+
+ setBounds(Common::Rect(0, 0, 0, 0));
+}
+
+void Movie::initFromMovieFile(const Common::String &fileName, bool transparent) {
+ _transparent = transparent;
+
+ releaseMovie();
+ _video = new Video::QuickTimeDecoder();
+ if (!_video->loadFile(fileName)) {
+ // Replace any colon with an underscore, since only Mac OS X
+ // supports that. See PegasusEngine::detectOpeningClosingDirectory()
+ // for more info.
+ Common::String newName(fileName);
+ if (newName.contains(':'))
+ for (uint i = 0; i < newName.size(); i++)
+ if (newName[i] == ':')
+ newName.setChar('_', i);
+
+ if (!_video->loadFile(newName))
+ error("Could not load video '%s'", fileName.c_str());
+ }
+
+ Common::Rect bounds(0, 0, _video->getWidth(), _video->getHeight());
+ sizeElement(_video->getWidth(), _video->getHeight());
+ _movieBox = bounds;
+
+ if (!isSurfaceValid())
+ allocateSurface(bounds);
+
+ setStart(0, getScale());
+ TimeBase::setStop(_video->getDuration().convertToFramerate(getScale()).totalNumberOfFrames(), getScale());
+}
+
+void Movie::redrawMovieWorld() {
+ if (_video && _video->needsUpdate()) {
+ const Graphics::Surface *frame = _video->decodeNextFrame();
+
+ if (!frame)
+ return;
+
+ // Make sure we have a surface in the current pixel format
+ Graphics::Surface *convertedFrame = 0;
+
+ if (frame->format != g_system->getScreenFormat()) {
+ convertedFrame = frame->convertTo(g_system->getScreenFormat());
+ frame = convertedFrame;
+ }
+
+ // Copy to the surface using _movieBox
+ uint16 width = MIN<int>(frame->w, _movieBox.width());
+ uint16 height = MIN<int>(frame->h, _movieBox.height());
+
+ for (uint16 y = 0; y < height; y++)
+ memcpy((byte *)_surface->getBasePtr(_movieBox.left, _movieBox.top + y), (const byte *)frame->getBasePtr(0, y), width * frame->format.bytesPerPixel);
+
+ if (convertedFrame) {
+ convertedFrame->free();
+ delete convertedFrame;
+ }
+
+ triggerRedraw();
+ }
+}
+
+void Movie::draw(const Common::Rect &r) {
+ Common::Rect worldBounds = _movieBox;
+ Common::Rect elementBounds;
+ getBounds(elementBounds);
+
+ worldBounds.moveTo(elementBounds.left, elementBounds.top);
+ Common::Rect r1 = r.findIntersectingRect(worldBounds);
+
+ Common::Rect r2 = r1;
+ r2.translate(_movieBox.left - elementBounds.left, _movieBox.top - elementBounds.top);
+ drawImage(r2, r1);
+}
+
+void Movie::moveMovieBoxTo(const CoordType h, const CoordType v) {
+ _movieBox.moveTo(h, v);
+}
+
+void Movie::setStop(const TimeValue stopTime, const TimeScale scale) {
+ TimeBase::setStop(stopTime, scale);
+
+ if (_video)
+ _video->setEndTime(Audio::Timestamp(0, _stopTime, _stopScale));
+}
+
+void Movie::setVolume(uint16 volume) {
+ if (_video)
+ _video->setVolume(MIN<uint>(volume, 0xFF));
+}
+
+void Movie::setTime(const TimeValue time, const TimeScale scale) {
+ if (_video) {
+ // Don't go past the ends of the movie
+ Common::Rational timeFrac = Common::Rational(time, ((scale == 0) ? getScale() : scale));
+
+ if (timeFrac < Common::Rational(_startTime, _startScale))
+ timeFrac = Common::Rational(_startTime, _startScale);
+ else if (timeFrac >= Common::Rational(_stopTime, _stopScale))
+ return;
+
+ _video->seek(Audio::Timestamp(0, timeFrac.getNumerator(), timeFrac.getDenominator()));
+ _time = timeFrac;
+ _lastMillis = 0;
+ }
+}
+
+void Movie::setRate(const Common::Rational rate) {
+ if (rate != 1 && rate != 0) {
+ warning("Cannot set movie rate");
+ start();
+ return;
+ }
+
+ TimeBase::setRate(rate);
+}
+
+void Movie::start() {
+ if (_video)
+ _video->start();
+
+ TimeBase::start();
+}
+
+void Movie::stop() {
+ if (_video)
+ _video->stop();
+
+ TimeBase::stop();
+}
+
+void Movie::resume() {
+ if (_paused) {
+ if (_video)
+ _video->pauseVideo(false);
+
+ _paused = false;
+ }
+}
+
+void Movie::pause() {
+ if (isRunning() && !_paused) {
+ if (_video)
+ _video->pauseVideo(true);
+
+ _paused = true;
+ _pauseStart = g_system->getMillis();
+ }
+}
+
+TimeValue Movie::getDuration(const TimeScale scale) const {
+ // Unlike TimeBase::getDuration(), this returns the whole duration of the movie
+ // The original source has a TODO to make this behave like TimeBase::getDuration(),
+ // but the problem is that too much code requires this function to behave this way...
+
+ if (_video)
+ return _video->getDuration().convertToFramerate(((scale == 0) ? getScale() : scale)).totalNumberOfFrames();
+
+ return 0;
+}
+
+void Movie::updateTime() {
+ // The reason why we overrode TimeBase's updateTime():
+ // Again, avoiding timers and handling it here
+ if (_video && _video->isPlaying() && !_video->isPaused()) {
+ redrawMovieWorld();
+
+ uint32 startTime = _startTime * getScale() / _startScale;
+ uint32 stopTime = _stopTime * getScale() / _stopScale;
+ uint32 actualTime = CLIP<int>(_video->getTime() * getScale() / 1000, startTime, stopTime);
+
+ // HACK: Due to the inaccuracy of the time, we won't actually allow us to hit
+ // the stop time unless we've actually reached the end of the segment.
+ if (actualTime == stopTime && !_video->endOfVideo())
+ actualTime--;
+
+ _time = Common::Rational(actualTime, getScale());
+ }
+}
+
+GlowingMovie::GlowingMovie(const DisplayElementID id) : Movie(id) {
+ _glowing = false;
+}
+
+void GlowingMovie::draw(const Common::Rect &r) {
+ // Make sure the rectangles are clipped properly, OR guarantee that _bounds will
+ // never fall off the screen.
+ if (_glowing) {
+ Common::Rect bounds;
+ getBounds(bounds);
+
+ copyToCurrentPortTransparentGlow(_movieBox, bounds);
+ } else {
+ Movie::draw(r);
+ }
+}
+
+void GlowingMovie::setBounds(const Common::Rect &r) {
+ Common::Rect bounds;
+ getBounds(bounds);
+
+ if (r != bounds) {
+ // Avoid Movie::setBounds.
+ // clone2727 asks why, but goes along with it
+ Animation::setBounds(r);
+ }
+}
+
+ScalingMovie::ScalingMovie(const DisplayElementID id) : GlowingMovie(id) {
+}
+
+void ScalingMovie::draw(const Common::Rect &) {
+ // Make sure the rectangles are clipped properly, OR guarantee that _bounds will
+ // never fall off the screen.
+
+ Common::Rect bounds;
+ getBounds(bounds);
+
+ if (_glowing)
+ scaleTransparentCopyGlow(_movieBox, bounds);
+ else
+ scaleTransparentCopy(_movieBox, bounds);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/movie.h b/engines/pegasus/movie.h
new file mode 100644
index 0000000000..9b9cc2bdbe
--- /dev/null
+++ b/engines/pegasus/movie.h
@@ -0,0 +1,105 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_MOVIE_H
+#define PEGASUS_MOVIE_H
+
+#include "common/str.h"
+
+#include "pegasus/elements.h"
+#include "pegasus/surface.h"
+
+namespace Video {
+class VideoDecoder;
+}
+
+namespace Pegasus {
+
+class Movie : public Animation, public PixelImage {
+public:
+ Movie(const DisplayElementID);
+ virtual ~Movie();
+
+ virtual void initFromMovieFile(const Common::String &fileName, bool transparent = false);
+
+ bool isMovieValid() { return _video != 0; }
+
+ virtual void releaseMovie();
+
+ virtual void draw(const Common::Rect &);
+ virtual void redrawMovieWorld();
+
+ virtual void setTime(const TimeValue, const TimeScale = 0);
+
+ virtual void setRate(const Common::Rational);
+
+ virtual void start();
+ virtual void stop();
+ virtual void resume();
+ virtual void pause();
+
+ virtual void moveMovieBoxTo(const CoordType, const CoordType);
+
+ virtual void setStop(const TimeValue, const TimeScale = 0);
+
+ virtual TimeValue getDuration(const TimeScale = 0) const;
+
+ // *** HACK ALERT
+ Video::VideoDecoder *getMovie() { return _video; }
+ void setVolume(uint16);
+
+protected:
+ void updateTime();
+
+ Video::VideoDecoder *_video;
+ Common::Rect _movieBox;
+};
+
+class GlowingMovie : public Movie {
+public:
+ GlowingMovie(DisplayElementID);
+ virtual ~GlowingMovie() {}
+
+ virtual void draw(const Common::Rect &);
+
+ void setBounds(const Common::Rect &);
+
+ void setGlowing(const bool glowing) { _glowing = glowing; }
+
+protected:
+ bool _glowing;
+};
+
+class ScalingMovie : public GlowingMovie {
+public:
+ ScalingMovie(DisplayElementID);
+ virtual ~ScalingMovie() {}
+
+ virtual void draw(const Common::Rect &);
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/caldoria/caldoria.cpp b/engines/pegasus/neighborhood/caldoria/caldoria.cpp
new file mode 100644
index 0000000000..140e6e8093
--- /dev/null
+++ b/engines/pegasus/neighborhood/caldoria/caldoria.cpp
@@ -0,0 +1,1962 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "video/qt_decoder.h"
+
+#include "pegasus/cursor.h"
+#include "pegasus/energymonitor.h"
+#include "pegasus/gamestate.h"
+#include "pegasus/interface.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/biochips/biochipitem.h"
+#include "pegasus/neighborhood/caldoria/caldoria.h"
+#include "pegasus/neighborhood/caldoria/caldoria4dsystem.h"
+#include "pegasus/neighborhood/caldoria/caldoriabomb.h"
+#include "pegasus/neighborhood/caldoria/caldoriamessages.h"
+#include "pegasus/neighborhood/caldoria/caldoriamirror.h"
+#include "pegasus/neighborhood/tsa/fulltsa.h"
+
+namespace Pegasus {
+
+static const int16 kVidPhoneAngle = 30;
+static const int16 kReplicatorAngle = 50;
+static const int16 kDrawersAngle = -30;
+static const int16 kCaldoria53Angle = 45;
+static const int16 kCaldoria55Angle = -45;
+
+static const TimeValue kSinclairInterruptionTime1 = 2955;
+static const TimeValue kSinclairInterruptionTime2 = 6835;
+static const TimeValue kSinclairInterruptionTime3 = 9835;
+static const TimeValue kSinclairInterruptionTime4 = 12555;
+
+static const InputBits kPullbackInterruptFilter = kFilterAllInput;
+static const InputBits kRecalibrationInterruptFilter = kFilterAllInput;
+
+static const TimeValue kCaldoriaReplicatorIntroIn = 4933;
+static const TimeValue kCaldoriaReplicatorIntroOut = 6557;
+
+static const TimeValue kCaldoriaReplicatorWrongChoiceIn = 6557;
+static const TimeValue kCaldoriaReplicatorWrongChoiceOut = 8586;
+
+static const TimeValue kCaldoriaReplicatorOJChoiceIn = 8586;
+static const TimeValue kCaldoriaReplicatorOJChoiceOut = 11687;
+
+static const TimeValue kCaldoriaMessagesIntroIn = 11687;
+static const TimeValue kCaldoriaMessagesIntroOut = 13641;
+
+static const TimeValue kCaldoriaFirstMessageIn = 13641;
+static const TimeValue kCaldoriaFirstMessageOut = 14203;
+
+static const TimeValue kCaldoriaSecondMessageIn = 14203;
+static const TimeValue kCaldoriaSecondMessageOut = 14750;
+
+static const TimeValue kCaldoriaDoorCloseIn = 14750;
+static const TimeValue kCaldoriaDoorCloseOut = 15472;
+
+static const TimeValue kCaldoriaElevatorCloseIn = 15472;
+static const TimeValue kCaldoriaElevatorCloseOut = 16336;
+
+static const TimeValue kCaldoriaShowerCloseIn = 16336;
+static const TimeValue kCaldoriaShowerCloseOut = 17101;
+
+static const TimeValue kCaldoriaGTDoorCloseIn = 17101;
+static const TimeValue kCaldoriaGTDoorCloseOut = 18523;
+
+static const TimeValue kCaldoriaNobodyHomeIn = 18523;
+static const TimeValue kCaldoriaNobodyHomeOut = 21469;
+
+static const TimeValue kCaldoriaNoOtherFloorIn = 21469;
+static const TimeValue kCaldoriaNoOtherFloorOut = 28013;
+
+static const TimeValue kCaldoria4DInstructionsIn = 28013;
+static const TimeValue kCaldoria4DInstructionsOut = 29730;
+
+static const TimeValue kCaldoriaDrinkOJIn = 33910;
+static const TimeValue kCaldoriaDrinkOJOut = 35846;
+
+static const TimeValue kCaldoriaNoOtherDestinationIn = 35846;
+static const TimeValue kCaldoriaNoOtherDestinationOut = 37877;
+
+static const TimeValue kCaldoriaUhghIn = 37877;
+static const TimeValue kCaldoriaUhghOut = 38025;
+
+static const TimeValue kCaldoriaSinclairShootsOSIn = 38025;
+static const TimeValue kCaldoriaSinclairShootsOSOut = 40649;
+
+static const TimeValue kCaldoriaScreamingAfterIn = 40649;
+static const TimeValue kCaldoriaScreamingAfterOut = 47661;
+
+static const TimeValue k4FloorTime = 0;
+
+static const TimeValue k4To1Start = 40;
+static const TimeValue k4To1Stop = 7720;
+
+static const TimeValue k4To5Start = 7720;
+static const TimeValue k4To5Stop = 10280;
+
+static const TimeValue k4To2Time = 10280;
+
+static const TimeValue k4To3Time = 10320;
+
+static const TimeValue k1FloorTime = 10360;
+
+static const TimeValue k1To4Start = 10400;
+static const TimeValue k1To4Stop = 18080;
+
+static const TimeValue k1To5Start = 18080;
+static const TimeValue k1To5Stop = 28320;
+
+static const TimeValue k1To2Time = 28320;
+
+static const TimeValue k1To3Time = 28360;
+
+static const TimeValue k5FloorTime = 28400;
+
+static const TimeValue k5To1Start = 28440;
+static const TimeValue k5To1Stop = 38680;
+
+static const TimeValue k5To4Start = 38680;
+static const TimeValue k5To4Stop = 41240;
+
+static const TimeValue k5To2Time = 41240;
+
+static const TimeValue k5To3Time = 41280;
+
+// FuseFunction functions...
+
+const NotificationFlags kSinclairLoopDoneFlag = kLastNeighborhoodNotificationFlag << 1;
+
+SinclairCallBack::SinclairCallBack(Caldoria *caldoria) {
+ _caldoria = caldoria;
+}
+
+void SinclairCallBack::callBack() {
+ _caldoria->checkInterruptSinclair();
+}
+
+Caldoria::Caldoria(InputHandler* nextHandler, PegasusEngine *owner)
+ : Neighborhood(nextHandler, owner, "Caldoria", kCaldoriaID), _sinclairInterrupt(this) {
+ setIsItemTaken(kKeyCard);
+ setIsItemTaken(kOrangeJuiceGlassEmpty);
+ GameState.setTakenItemID(kOrangeJuiceGlassFull, GameState.isTakenItemID(kOrangeJuiceGlassEmpty));
+ _zoomOutSpot = 0;
+ _gunSprite = 0;
+}
+
+Caldoria::~Caldoria() {
+ _sinclairInterrupt.releaseCallBack();
+}
+
+void Caldoria::init() {
+ Neighborhood::init();
+
+ // We need this notification flag as well.
+ _neighborhoodNotification.notifyMe(this, kSinclairLoopDoneFlag, kSinclairLoopDoneFlag);
+
+ _sinclairInterrupt.initCallBack(&_navMovie, kCallBackAtTime);
+
+ forceStridingStop(kCaldoria55, kSouth, kAltCaldoriaSinclairDown);
+ forceStridingStop(kCaldoria50, kNorth, kAltCaldoriaSinclairDown);
+}
+
+void Caldoria::start() {
+ g_energyMonitor->stopEnergyDraining();
+
+ if (!GameState.getCaldoriaSeenPullback()) {
+ _vm->_gfx->doFadeOutSync(kOneSecond * kFifteenTicksPerSecond, kFifteenTicksPerSecond);
+
+ g_system->delayMillis(2 * 1000);
+
+ Video::VideoDecoder *pullbackMovie = new Video::QuickTimeDecoder();
+
+ if (!pullbackMovie->loadFile("Images/Caldoria/Pullback.movie"))
+ error("Could not load pullback movie");
+
+ // Draw the first frame so we can fade to it
+ 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);
+ _vm->_gfx->doFadeInSync(kTwoSeconds * kFifteenTicksPerSecond, kFifteenTicksPerSecond);
+
+ bool saveAllowed = _vm->swapSaveAllowed(false);
+ bool openAllowed = _vm->swapLoadAllowed(false);
+
+ bool skipped = false;
+ Input input;
+
+ pullbackMovie->start();
+
+ while (!_vm->shouldQuit() && !pullbackMovie->endOfVideo()) {
+ if (pullbackMovie->needsUpdate()) {
+ frame = pullbackMovie->decodeNextFrame();
+
+ if (frame) {
+ g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, 64, 112, frame->w, frame->h);
+ g_system->updateScreen();
+ }
+ }
+
+ InputDevice.getInput(input, kPullbackInterruptFilter);
+ if (input.anyInput() || _vm->saveRequested() || _vm->loadRequested()) {
+ skipped = true;
+ break;
+ }
+
+ g_system->delayMillis(10);
+ }
+
+ delete pullbackMovie;
+
+ if (_vm->shouldQuit())
+ return;
+
+ _vm->swapSaveAllowed(saveAllowed);
+ _vm->swapLoadAllowed(openAllowed);
+
+ ExtraTable::Entry entry;
+
+ if (!skipped) {
+ _vm->_gfx->doFadeOutSync(kThreeSeconds * kFifteenTicksPerSecond, kFifteenTicksPerSecond, false);
+ g_system->delayMillis(3 * 1000 / 2);
+ getExtraEntry(kCaldoria00WakeUp1, entry);
+ _navMovie.setTime(entry.movieStart);
+ _navMovie.redrawMovieWorld();
+ _navMovie.show();
+ _vm->refreshDisplay();
+ _vm->_gfx->doFadeInSync(kOneSecond * kFifteenTicksPerSecond, kFifteenTicksPerSecond, false);
+ } else {
+ getExtraEntry(kCaldoria00WakeUp1, entry);
+ _navMovie.setTime(entry.movieStart);
+ _navMovie.redrawMovieWorld();
+ _navMovie.show();
+ }
+
+ GameState.setCaldoriaSeenPullback(true);
+ }
+
+ Neighborhood::start();
+}
+
+void Caldoria::flushGameState() {
+ GameState.setCaldoriaFuseTimeLimit(_utilityFuse.getTimeRemaining());
+}
+
+class AIBombActiveCondition : public AICondition {
+public:
+ AIBombActiveCondition() {}
+
+ bool fireCondition();
+};
+
+// Return true if player is on 53 east and Sinclair is shot.
+bool AIBombActiveCondition::fireCondition() {
+ return GameState.getCurrentRoom() == kCaldoria53 && GameState.getCurrentDirection() == kEast &&
+ GameState.getCaldoriaSinclairShot();
+}
+
+void Caldoria::setUpAIRules() {
+ Neighborhood::setUpAIRules();
+
+ if (g_AIArea) {
+ if (GameState.allTimeZonesFinished()) {
+ AIPlayMessageAction *messageAction = new AIPlayMessageAction("Images/AI/Caldoria/X49NB1", false);
+ AILocationCondition *locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kCaldoria49, kNorth));
+ AIRule *rule = new AIRule(locCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Caldoria/X56EH1", false);
+ AIBombActiveCondition *activeCondition = new AIBombActiveCondition();
+ rule = new AIRule(activeCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+ } else {
+ AIPlayMessageAction *messageAction = new AIPlayMessageAction("Images/AI/Caldoria/XAB2", false);
+ AITimerCondition *timerCondition = new AITimerCondition(kLateWarning3TimeLimit, 1, true);
+ AILocationCondition *locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kCaldoria44, kEast));
+ AINotCondition *notCondition = new AINotCondition(locCondition);
+ AIAndCondition *andCondition = new AIAndCondition(timerCondition, notCondition);
+ AIRule *rule = new AIRule(andCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Caldoria/XAB1", false);
+ timerCondition = new AITimerCondition(kLateWarning2TimeLimit, 1, true);
+ locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kCaldoria44, kEast));
+ notCondition = new AINotCondition(locCondition);
+ andCondition = new AIAndCondition(timerCondition, notCondition);
+ rule = new AIRule(andCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Caldoria/XA44EB", false);
+ locCondition = new AILocationCondition(3);
+ locCondition->addLocation(MakeRoomView(kCaldoria01, kNorth));
+ locCondition->addLocation(MakeRoomView(kCaldoria01, kEast));
+ locCondition->addLocation(MakeRoomView(kCaldoria01, kSouth));
+ rule = new AIRule(locCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Caldoria/X42WH1", false);
+ AICondition *condition = makeLocationAndDoesntHaveItemCondition(kCaldoria44, kEast, kKeyCard);
+ rule = new AIRule(condition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ AIActivateRuleAction *ruleAction = new AIActivateRuleAction(rule);
+ locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kCaldoria42, kEast));
+ rule = new AIRule(locCondition, ruleAction);
+ g_AIArea->addAIRule(rule);
+ }
+ }
+}
+
+uint16 Caldoria::getDateResID() const {
+ return kDate2318ID;
+}
+
+TimeValue Caldoria::getViewTime(const RoomID room, const DirectionConstant direction) {
+ ExtraTable::Entry extra;
+ uint32 extraID = 0xffffffff;
+
+ switch (room) {
+ case kCaldoria00:
+ if (direction == kEast && _privateFlags.getFlag(kCaldoriaPrivate4DSystemOpenFlag))
+ extraID = k4DEnvironOpenView;
+ break;
+ case kCaldoriaDrawers:
+ if (direction == kNorth && _privateFlags.getFlag(kCaldoriaPrivateRightDrawerOpenFlag)) {
+ if (GameState.isTakenItemID(kKeyCard))
+ extraID = kRightDrawerOpenViewNoKeys;
+ else
+ extraID = kRightDrawerOpenViewWithKeys;
+ }
+ break;
+ case kCaldoria16:
+ if (direction == kSouth && GameState.getCaldoriaSeenSinclairInElevator())
+ extraID = kCaldoria16SouthViewWithElevator;
+ break;
+ case kCaldoriaReplicator:
+ if (GameState.getCaldoriaMadeOJ() && !(GameState.isTakenItemID(kOrangeJuiceGlassEmpty) || GameState.isTakenItemID(kOrangeJuiceGlassFull)))
+ extraID = kReplicatorNorthViewWithOJ;
+ break;
+ case kCaldoriaKiosk:
+ case kCaldoriaBinoculars:
+ return 0xffffffff;
+ case kCaldoria48:
+ if (direction == kNorth && GameState.getCaldoriaRoofDoorOpen())
+ extraID = kCa48NorthExplosion;
+ break;
+ }
+
+ if (extraID == 0xffffffff)
+ return Neighborhood::getViewTime(room, direction);
+
+ getExtraEntry(extraID, extra);
+ return extra.movieEnd - 1;
+}
+
+void Caldoria::startSpotOnceOnly(TimeValue startTime, TimeValue stopTime) {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kCaldoria13, kEast):
+ if (!_privateFlags.getFlag(kCaldoriaPrivateSeen13CarFlag) && _vm->getRandomBit() == 0) {
+ _privateFlags.setFlag(kCaldoriaPrivateSeen13CarFlag, true);
+ Neighborhood::startSpotOnceOnly(startTime, stopTime);
+ }
+ break;
+ case MakeRoomView(kCaldoria14, kEast):
+ if (!_privateFlags.getFlag(kCaldoriaPrivateSeen14CarFlag) && _vm->getRandomBit() == 0) {
+ _privateFlags.setFlag(kCaldoriaPrivateSeen14CarFlag, true);
+ Neighborhood::startSpotOnceOnly(startTime, stopTime);
+ }
+ break;
+ case MakeRoomView(kCaldoria18, kWest):
+ if (!_privateFlags.getFlag(kCaldoriaPrivateSeen18CarFlag) && _vm->getRandomBit() == 0) {
+ _privateFlags.setFlag(kCaldoriaPrivateSeen18CarFlag, true);
+ Neighborhood::startSpotOnceOnly(startTime, stopTime);
+ }
+ break;
+ case MakeRoomView(kCaldoria23, kSouth):
+ if (!_privateFlags.getFlag(kCaldoriaPrivateSeen23CarFlag) && _vm->getRandomBit() == 0) {
+ _privateFlags.setFlag(kCaldoriaPrivateSeen23CarFlag, true);
+ Neighborhood::startSpotOnceOnly(startTime, stopTime);
+ }
+ break;
+ case MakeRoomView(kCaldoria33, kSouth):
+ if (!_privateFlags.getFlag(kCaldoriaPrivateSeen33CarFlag) && _vm->getRandomBit() == 0) {
+ _privateFlags.setFlag(kCaldoriaPrivateSeen33CarFlag, true);
+ Neighborhood::startSpotOnceOnly(startTime, stopTime);
+ }
+ break;
+ case MakeRoomView(kCaldoria36, kNorth):
+ if (!_privateFlags.getFlag(kCaldoriaPrivateSeen36CarFlag) && _vm->getRandomBit() == 0) {
+ _privateFlags.setFlag(kCaldoriaPrivateSeen36CarFlag, true);
+ Neighborhood::startSpotOnceOnly(startTime, stopTime);
+ }
+ break;
+ case MakeRoomView(kCaldoria41, kNorth):
+ if (!_privateFlags.getFlag(kCaldoriaPrivateSeen41NorthCarFlag) && _vm->getRandomBit() == 0) {
+ _privateFlags.setFlag(kCaldoriaPrivateSeen41NorthCarFlag, true);
+ Neighborhood::startSpotOnceOnly(startTime, stopTime);
+ }
+ break;
+ case MakeRoomView(kCaldoria41, kEast):
+ if (!_privateFlags.getFlag(kCaldoriaPrivateSeen41EastCarFlag) && _vm->getRandomBit() == 0) {
+ _privateFlags.setFlag(kCaldoriaPrivateSeen41EastCarFlag, true);
+ Neighborhood::startSpotOnceOnly(startTime, stopTime);
+ }
+ break;
+ case MakeRoomView(kCaldoria41, kWest):
+ if (!_privateFlags.getFlag(kCaldoriaPrivateSeen41WestCarFlag) && _vm->getRandomBit() == 0) {
+ _privateFlags.setFlag(kCaldoriaPrivateSeen41WestCarFlag, true);
+ Neighborhood::startSpotOnceOnly(startTime, stopTime);
+ }
+ break;
+ default:
+ Neighborhood::startSpotOnceOnly(startTime, stopTime);
+ break;
+ }
+}
+
+void Caldoria::findSpotEntry(const RoomID room, const DirectionConstant direction, SpotFlags flags, SpotTable::Entry &entry) {
+ Neighborhood::findSpotEntry(room, direction, flags, entry);
+
+ switch (room) {
+ case kCaldoria00:
+ if (direction == kEast && (!GameState.getCaldoriaINNAnnouncing() || GameState.getCaldoriaSeenINN()))
+ entry.clear();
+ break;
+ case kCaldoriaVidPhone:
+ if (direction == kNorth && GameState.getCaldoriaSeenMessages())
+ entry.clear();
+ break;
+ case kCaldoria44:
+ if (direction == kEast && GameState.getLastRoom() != kCaldoria42)
+ entry.clear();
+ break;
+ }
+}
+
+void Caldoria::startExitMovie(const ExitTable::Entry &exitEntry) {
+ switch (GameState.getCurrentRoom()) {
+ case kCaldoria05:
+ case kCaldoria07:
+ if (GameState.getCurrentDirection() == kWest)
+ closeCroppedMovie();
+ // fall through
+ case kCaldoria11:
+ if (GameState.getCurrentDirection() == kEast)
+ closeCroppedMovie();
+ break;
+ case kCaldoria13:
+ case kCaldoria14:
+ if (GameState.getCurrentDirection() == kNorth)
+ closeCroppedMovie();
+ break;
+ }
+
+ Neighborhood::startExitMovie(exitEntry);
+}
+
+void Caldoria::startZoomMovie(const ZoomTable::Entry &zoomEntry) {
+ switch (GameState.getCurrentRoom()) {
+ case kCaldoria12:
+ if (GameState.getCurrentDirection() == kNorth)
+ closeCroppedMovie();
+ break;
+ }
+
+ Neighborhood::startZoomMovie(zoomEntry);
+}
+
+void Caldoria::startDoorOpenMovie(const TimeValue startTime, const TimeValue stopTime) {
+ if (GameState.getCurrentRoom() == kCaldoria27 || GameState.getCurrentRoom() == kCaldoria28 || GameState.getCurrentRoom() == kCaldoria45)
+ // Must be opening elevator door.
+ closeCroppedMovie();
+
+ if (GameState.getCurrentRoom() == kCaldoria44 && GameState.getLastRoom() != kCaldoria42)
+ startExtraSequence(kArriveAtCaldoriaFromTSA, kDoorOpenCompletedFlag, false);
+ else
+ Neighborhood::startDoorOpenMovie(startTime, stopTime);
+}
+
+void Caldoria::startTurnPush(const TurnDirection turnDirection, const TimeValue newViewTime, const DirectionConstant destDirection) {
+ switch (GameState.getCurrentRoom()) {
+ case kCaldoria05:
+ case kCaldoria07:
+ if (GameState.getCurrentDirection() == kWest)
+ closeCroppedMovie();
+ break;
+ case kCaldoria11:
+ if (GameState.getCurrentDirection() == kEast)
+ closeCroppedMovie();
+ break;
+ case kCaldoria12:
+ case kCaldoria13:
+ case kCaldoria14:
+ case kCaldoria27:
+ case kCaldoria28:
+ case kCaldoria45:
+ if (GameState.getCurrentDirection() == kNorth)
+ closeCroppedMovie();
+ break;
+ case kCaldoria48:
+ if (_croppedMovie.isSurfaceValid())
+ closeCroppedMovie();
+ break;
+ }
+
+ Neighborhood::startTurnPush(turnDirection, newViewTime, destDirection);
+}
+
+void Caldoria::bumpIntoWall() {
+ requestSpotSound(kCaldoriaUhghIn, kCaldoriaUhghOut, kFilterNoInput, 0);
+ Neighborhood::bumpIntoWall();
+}
+
+void Caldoria::closeDoorOffScreen(const RoomID room, const DirectionConstant direction) {
+ switch (room) {
+ case kCaldoria08:
+ if (direction == kNorth)
+ playSpotSoundSync(kCaldoriaShowerCloseIn, kCaldoriaShowerCloseOut);
+ else
+ playSpotSoundSync(kCaldoriaDoorCloseIn, kCaldoriaDoorCloseOut);
+ break;
+ case kCaldoria09:
+ playSpotSoundSync(kCaldoriaShowerCloseIn, kCaldoriaShowerCloseOut);
+ break;
+ case kCaldoria16:
+ case kCaldoria38:
+ case kCaldoria46:
+ case kCaldoria27:
+ case kCaldoria28:
+ case kCaldoria45:
+ playSpotSoundSync(kCaldoriaElevatorCloseIn, kCaldoriaElevatorCloseOut);
+ break;
+ case kCaldoria44:
+ case kCaldoria42:
+ if (GameState.getCurrentRoom() == kCaldoria42)
+ playSpotSoundSync(kCaldoriaGTDoorCloseIn, kCaldoriaGTDoorCloseOut);
+ break;
+ default:
+ playSpotSoundSync(kCaldoriaDoorCloseIn, kCaldoriaDoorCloseOut);
+ break;
+ }
+}
+
+int16 Caldoria::getStaticCompassAngle(const RoomID room, const DirectionConstant dir) {
+ int16 result = Neighborhood::getStaticCompassAngle(room, dir);
+
+ switch (room) {
+ case kCaldoriaVidPhone:
+ result += kVidPhoneAngle;
+ break;
+ case kCaldoriaReplicator:
+ result += kReplicatorAngle;
+ break;
+ case kCaldoriaDrawers:
+ result += kDrawersAngle;
+ break;
+ case kCaldoria53:
+ result += kCaldoria53Angle;
+ break;
+ case kCaldoria55:
+ result += kCaldoria55Angle;
+ break;
+ }
+
+ return result;
+}
+
+void Caldoria::getExitCompassMove(const ExitTable::Entry &exitEntry, FaderMoveSpec &compassMove) {
+ Neighborhood::getExitCompassMove(exitEntry, compassMove);
+
+ switch (MakeRoomView(exitEntry.room, exitEntry.direction)) {
+ case MakeRoomView(kCaldoria08, kNorth):
+ case MakeRoomView(kCaldoria09, kSouth):
+ compassMove.insertFaderKnot((exitEntry.movieStart + exitEntry.movieEnd) >> 1, compassMove.getNthKnotValue(0) + 30);
+ break;
+ case MakeRoomView(kCaldoria10, kEast):
+ compassMove.insertFaderKnot(exitEntry.movieStart + 4 * kCaldoriaFrameDuration, 90);
+ compassMove.insertFaderKnot(exitEntry.movieStart + 19 * kCaldoriaFrameDuration, -90);
+ break;
+ case MakeRoomView(kCaldoria42, kWest):
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), exitEntry.movieStart, -90, exitEntry.movieEnd, 90);
+ compassMove.insertFaderKnot(exitEntry.movieStart + 3 * kCaldoriaFrameDuration, -90);
+ compassMove.insertFaderKnot(exitEntry.movieStart + 33 * kCaldoriaFrameDuration, 90);
+ break;
+ case MakeRoomView(kCaldoria54, kEast):
+ if (getCurrentAlternate() != kAltCaldoriaSinclairDown) {
+ compassMove.insertFaderKnot(exitEntry.movieStart + 16 * kCaldoriaFrameDuration, 135);
+ compassMove.insertFaderKnot(exitEntry.movieEnd, 135);
+ }
+ break;
+ case MakeRoomView(kCaldoria55, kNorth):
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), exitEntry.movieStart, 315, exitEntry.movieEnd, 270);
+ break;
+ }
+}
+
+void Caldoria::getZoomCompassMove(const ZoomTable::Entry &zoomEntry, FaderMoveSpec &compassMove) {
+ Neighborhood::getZoomCompassMove(zoomEntry, compassMove);
+
+ switch (zoomEntry.hotspot) {
+ case kCaBathroomToiletSpotID:
+ compassMove.insertFaderKnot(zoomEntry.movieStart + 4 * kCaldoriaFrameDuration, 90);
+ compassMove.insertFaderKnot(zoomEntry.movieStart + 19 * kCaldoriaFrameDuration, -90);
+ compassMove.insertFaderKnot(zoomEntry.movieEnd, -90);
+ break;
+ }
+}
+
+void Caldoria::getExtraCompassMove(const ExtraTable::Entry &entry, FaderMoveSpec &compassMove) {
+ switch (entry.extra) {
+ case kCaldoria00WakeUp1:
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), entry.movieStart, 90, entry.movieEnd, 180);
+ compassMove.insertFaderKnot(entry.movieStart + 1000, 90);
+ compassMove.insertFaderKnot(entry.movieStart + 1640, 120);
+ compassMove.insertFaderKnot(entry.movieStart + 2240, 135);
+ compassMove.insertFaderKnot(entry.movieStart + 2640, 180);
+ break;
+ case kCaldoria00WakeUp2:
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), entry.movieStart, 180, entry.movieEnd, 90);
+ compassMove.insertFaderKnot(entry.movieStart + 560, 90);
+ break;
+ case kCaldoria56BombStage1:
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), entry.movieStart, 90, entry.movieEnd, 10);
+ compassMove.insertFaderKnot(entry.movieStart + 31 * kCaldoriaFrameDuration, 60);
+ compassMove.insertFaderKnot(entry.movieStart + 49 * kCaldoriaFrameDuration, 60);
+ compassMove.insertFaderKnot(entry.movieStart + 66 * kCaldoriaFrameDuration, 10);
+ break;
+ case kCaldoria56BombStage7:
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), entry.movieStart, 10, entry.movieEnd, 90);
+ compassMove.insertFaderKnot(entry.movieStart + 131 * kCaldoriaFrameDuration, 10);
+ compassMove.insertFaderKnot(entry.movieStart + 148 * kCaldoriaFrameDuration, 60);
+ compassMove.insertFaderKnot(entry.movieStart + 165 * kCaldoriaFrameDuration, 60);
+ compassMove.insertFaderKnot(entry.movieEnd - 5 * kCaldoriaFrameDuration, 90);
+ break;
+ default:
+ Neighborhood::getExtraCompassMove(entry, compassMove);
+ break;
+ }
+}
+
+void Caldoria::loadAmbientLoops() {
+ RoomID room = GameState.getCurrentRoom();
+
+ if (room == kCaldoria00 && GameState.getCaldoriaWokenUp())
+ loadLoopSound1("Sounds/Caldoria/Apartment Music.AIFF", 0x100 / 4);
+ else if (room >= kCaldoria01 && room <= kCaldoria14)
+ loadLoopSound1("Sounds/Caldoria/Apartment Music.AIFF", 0x100 / 4);
+ else if (room == kCaldoria27 || room == kCaldoria28 || room == kCaldoria45)
+ loadLoopSound1("Sounds/Caldoria/Elevator Loop.AIFF", 0x100 / 5);
+ else if (room == kCaldoria44)
+ loadLoopSound1("Sounds/Caldoria/TSA Hum Loop.AIFF");
+ else if (room >= kCaldoria15 && room <= kCaldoria48)
+ loadLoopSound1("Sounds/Caldoria/Industrial Nuage.aiff", 2 * 0x100 / 3);
+ else if (room >= kCaldoria49 && room <= kCaldoria56)
+ loadLoopSound1("Sounds/Caldoria/A50NLB00.22K.AIFF", 0x100 / 4);
+}
+
+void Caldoria::checkContinuePoint(const RoomID room, const DirectionConstant direction) {
+ switch (MakeRoomView(room, direction)) {
+ case MakeRoomView(kCaldoria06, kSouth):
+ case MakeRoomView(kCaldoria13, kNorth):
+ case MakeRoomView(kCaldoria16, kSouth):
+ case MakeRoomView(kCaldoria38, kEast):
+ case MakeRoomView(kCaldoria38, kWest):
+ case MakeRoomView(kCaldoria40, kNorth):
+ case MakeRoomView(kCaldoria44, kEast):
+ case MakeRoomView(kCaldoria48, kNorth):
+ case MakeRoomView(kCaldoria49, kNorth):
+ makeContinuePoint();
+ break;
+ }
+}
+
+void Caldoria::spotCompleted() {
+ Neighborhood::spotCompleted();
+ if (GameState.getCurrentRoom() == kCaldoriaBinoculars)
+ startExtraSequence(kBinocularsZoomInOnShip, kExtraCompletedFlag, kFilterNoInput);
+}
+
+void Caldoria::arriveAt(const RoomID room, const DirectionConstant direction) {
+ switch (room) {
+ case kCaldoria56:
+ if (!GameState.getCaldoriaGunAimed())
+ // Fall through...
+ case kCaldoria49:
+ case kCaldoria50:
+ case kCaldoria51:
+ case kCaldoria52:
+ case kCaldoria53:
+ case kCaldoria54:
+ case kCaldoria55:
+ if (GameState.getCaldoriaSinclairShot())
+ setCurrentAlternate(kAltCaldoriaSinclairDown);
+ break;
+ }
+
+ Neighborhood::arriveAt(room, direction);
+ Input dummy;
+
+ switch (room) {
+ case kCaldoria00:
+ arriveAtCaldoria00();
+ break;
+ case kCaldoria05:
+ if (direction == kWest && GameState.getCaldoriaINNAnnouncing())
+ loopCroppedMovie("Images/Caldoria/A05 Light Loop", kCaldoriaA05LightLoopLeft, kCaldoriaA05LightLoopTop);
+ break;
+ case kCaldoria07:
+ if (direction == kWest && GameState.getCaldoriaINNAnnouncing())
+ loopCroppedMovie("Images/Caldoria/A07 Light Loop", kCaldoriaA07LightLoopLeft, kCaldoriaA07LightLoopTop);
+ break;
+ case kCaldoria09:
+ _lastExtra = 0xffffffff;
+ break;
+ case kCaldoriaToilet:
+ GameState.setScoringReadPaper(true);
+ break;
+ case kCaldoriaReplicator:
+ setCurrentActivation(kActivateReplicatorReady);
+ requestSpotSound(kCaldoriaReplicatorIntroIn, kCaldoriaReplicatorIntroOut, kFilterNoInput, 0);
+ break;
+ case kCaldoria11:
+ setCurrentAlternate(kAltCaldoriaNormal);
+ if (direction == kEast && !GameState.getCaldoriaSeenMessages())
+ loopCroppedMovie("Images/Caldoria/A11 Message Machine Loop", kCaldoria11MessageLoopLeft, kCaldoria11MessageLoopTop);
+ break;
+ case kCaldoria12:
+ if (direction == kNorth && !GameState.getCaldoriaSeenMessages())
+ loopCroppedMovie("Images/Caldoria/A12 Message Machine Loop", kCaldoria12MessageLoopLeft, kCaldoria12MessageLoopTop);
+ break;
+ case kCaldoriaDrawers:
+ setCurrentActivation(kActivateDrawersClosed);
+ break;
+ case kCaldoria13:
+ GameState.setCaldoriaINNAnnouncing(true);
+ if (direction == kNorth && !GameState.getCaldoriaSeenMessages())
+ loopCroppedMovie("Images/Caldoria/A13 Message Machine Loop", kCaldoria13MessageLoopLeft, kCaldoria13MessageLoopTop);
+ break;
+ case kCaldoria14:
+ if (direction == kNorth && !GameState.getCaldoriaSeenMessages())
+ loopCroppedMovie("Images/Caldoria/A14 Message Machine Loop", kCaldoria14MessageLoopLeft, kCaldoria14MessageLoopTop);
+ break;
+ case kCaldoria08:
+ if (direction == kWest)
+ setCurrentActivation(kActivateMirrorReady);
+ // Fall through...
+ case kCaldoria15:
+ GameState.setCaldoriaINNAnnouncing(true);
+ break;
+ case kCaldoria27:
+ case kCaldoria28:
+ case kCaldoria45:
+ if (GameState.getCurrentDirection() == kNorth)
+ openDoor();
+ break;
+ case kCaldoriaBinoculars:
+ GameState.setScoringLookThroughTelescope(true);
+ break;
+ case kCaldoriaKiosk:
+ GameState.setScoringSawCaldoriaKiosk(true);
+ startExtraSequenceSync(kCaldoriaKioskVideo, kFilterAllInput);
+ downButton(dummy);
+ break;
+ case kCaldoria44:
+ arriveAtCaldoria44();
+ break;
+ case kCaldoria49:
+ arriveAtCaldoria49();
+ break;
+ case kCaldoria53:
+ if (direction == kEast && !GameState.getCaldoriaSinclairShot())
+ zoomToSinclair();
+ break;
+ case kCaldoria50:
+ if (direction == kNorth && !GameState.getCaldoriaSinclairShot())
+ setUpSinclairLoops();
+ break;
+ case kCaldoria54:
+ if (direction == kSouth && !GameState.getCaldoriaSinclairShot())
+ setUpSinclairLoops();
+ break;
+ case kCaldoria56:
+ arriveAtCaldoria56();
+ break;
+ case kCaldoriaDeathRoom:
+ arriveAtCaldoriaDeath();
+ break;
+ }
+
+ checkSinclairShootsOS();
+ setUpRoofTop();
+}
+
+void Caldoria::doAIRecalibration() {
+ GameState.setCaldoriaDidRecalibration(true);
+
+ if (!g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/Caldoria/XA01EB1", true, kRecalibrationInterruptFilter))
+ return;
+
+ g_interface->calibrateEnergyBar();
+ if (!g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/Caldoria/XA01EB4", true, kRecalibrationInterruptFilter))
+ return;
+
+ g_interface->raiseInventoryDrawerSync();
+ if (!g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/Caldoria/XA01EB6", true, kRecalibrationInterruptFilter)) {
+ g_interface->lowerInventoryDrawerSync();
+ return;
+ }
+
+ g_interface->lowerInventoryDrawerSync();
+ g_interface->raiseBiochipDrawerSync();
+
+ if (!g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/Caldoria/XA01EB5", true, kRecalibrationInterruptFilter)) {
+ g_interface->lowerBiochipDrawerSync();
+ return;
+ }
+
+ g_interface->lowerBiochipDrawerSync();
+
+ g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/Caldoria/XA01EB8", false, kRecalibrationInterruptFilter);
+}
+
+void Caldoria::arriveAtCaldoria00() {
+ if (GameState.getCurrentDirection() == kEast) {
+ if (GameState.getCaldoriaWokenUp()) {
+ if (!GameState.getCaldoriaDidRecalibration())
+ doAIRecalibration();
+ setCurrentActivation(kActivate4DClosed);
+ } else {
+ // Good morning, sleeping beauty
+ ExtraTable::Entry extra;
+ getExtraEntry(kCaldoria00WakeUp1, extra);
+
+ if (_navMovie.getTime() != extra.movieStart) {
+ _navMovie.setTime(extra.movieStart);
+ _navMovie.redrawMovieWorld();
+ }
+
+ startExtraSequenceSync(kCaldoria00WakeUp1, kFilterNoInput);
+ GameState.setCaldoriaWokenUp(true);
+ playCroppedMovieOnce("Images/Caldoria/VidPhone.movie", kCaldoriaVidPhoneLeft, kCaldoriaVidPhoneTop, kFilterAllInput);
+ startExtraSequence(kCaldoria00WakeUp2, kExtraCompletedFlag, kFilterNoInput);
+ }
+ }
+}
+
+bool Caldoria::wantsCursor() {
+ return GameState.getCaldoriaDidRecalibration();
+}
+
+void Caldoria::arriveAtCaldoria44() {
+ if (GameState.getLastNeighborhood() != kCaldoriaID) {
+ openDoor();
+ } else {
+ setCurrentActivation(kActivateReadyForCard);
+ loopExtraSequence(kCaldoriaTransporterArrowLoop, 0);
+ }
+}
+
+void Caldoria::arriveAtCaldoria49() {
+ if (GameState.getLastRoom() == kCaldoria48)
+ setCurrentAlternate(kAltCaldoriaNormal);
+
+ // Need to force the loop to play.
+ if (GameState.getCurrentDirection() == kNorth) {
+ GameState.setCaldoriaFuseTimeLimit(kSinclairShootsTimeLimit);
+ startExtraSequence(kCa49NorthVoiceAnalysis, kExtraCompletedFlag, kFilterNoInput);
+ }
+}
+
+void Caldoria::arriveAtCaldoria56() {
+ if (!GameState.getCaldoriaBombDisarmed()) {
+ _privateFlags.setFlag(kCaldoriaPrivateZoomingToBombFlag, true);
+
+ if (GameState.getCurrentDirection() == kNorth) {
+ turnRight();
+ } else if (GameState.getCurrentDirection() == kSouth) {
+ turnLeft();
+ } else if (GameState.getCurrentDirection() == kEast) {
+ _privateFlags.setFlag(kCaldoriaPrivateZoomingToBombFlag, false);
+ newInteraction(kCaldoriaBombInteractionID);
+ }
+ }
+}
+
+void Caldoria::arriveAtCaldoriaDeath() {
+ if (GameState.getLastRoom() == kCaldoria49) {
+ if (GameState.getCaldoriaSinclairShot()) {
+ die(kDeathNuclearExplosion);
+ } else {
+ playSpotSoundSync(kCaldoriaSinclairShootsOSIn, kCaldoriaSinclairShootsOSOut);
+ playSpotSoundSync(kCaldoriaScreamingAfterIn, kCaldoriaScreamingAfterOut);
+ die(kDeathSinclairShotDelegate);
+ }
+ } else {
+ die(kDeathShotBySinclair);
+ }
+}
+
+void Caldoria::setUpRoofTop() {
+ switch (GameState.getCurrentRoom()) {
+ case kCaldoria48:
+ if (GameState.getCurrentDirection() == kNorth) {
+ if (GameState.getCaldoriaRoofDoorOpen()) {
+ setCurrentAlternate(kAltCaldoriaRoofDoorBlown);
+ } else if (GameState.getCaldoriaDoorBombed()) {
+ // Long enough for AI hints...?
+ _utilityFuse.primeFuse(kCardBombCountDownTime);
+ _utilityFuse.setFunctor(new Common::Functor0Mem<void, Caldoria>(this, &Caldoria::doorBombTimerExpired));
+ _utilityFuse.lightFuse();
+
+ loopCroppedMovie("Images/Caldoria/A48 Bomb Loop", kCaldoria48CardBombLoopLeft, kCaldoria48CardBombLoopTop);
+ } else {
+ setCurrentActivation(kActivateRoofSlotEmpty);
+ }
+ }
+ break;
+ case kCaldoria56:
+ if (GameState.getCurrentDirection() == kEast && GameState.getCaldoriaGunAimed())
+ startExtraSequence(kCa53EastShootSinclair, kExtraCompletedFlag, false);
+ else
+ // Fall through...
+ case kCaldoria49:
+ case kCaldoria50:
+ case kCaldoria51:
+ case kCaldoria52:
+ case kCaldoria53:
+ case kCaldoria54:
+ case kCaldoria55:
+ if (!GameState.getCaldoriaSinclairShot()) {
+ if (GameState.getCaldoriaSawVoiceAnalysis() && !_utilityFuse.isFuseLit()) {
+ _utilityFuse.primeFuse(GameState.getCaldoriaFuseTimeLimit());
+ _utilityFuse.setFunctor(new Common::Functor0Mem<void, Caldoria>(this, &Caldoria::sinclairTimerExpired));
+ _utilityFuse.lightFuse();
+ }
+ } else {
+ setCurrentAlternate(kAltCaldoriaSinclairDown);
+ }
+ break;
+ }
+}
+
+void Caldoria::downButton(const Input &input) {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kCaldoria01, kEast):
+ GameState.setCaldoriaWokenUp(true);
+ startExtraSequence(kCaldoria00SitDown, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ default:
+ Neighborhood::downButton(input);
+ break;
+ }
+}
+
+void Caldoria::turnTo(const DirectionConstant direction) {
+ Neighborhood::turnTo(direction);
+
+ switch (GameState.getCurrentRoom()) {
+ case kCaldoria00:
+ if (direction == kEast)
+ setCurrentActivation(kActivate4DClosed);
+ break;
+ case kCaldoria01:
+ if (direction == kEast) {
+ GameState.setCaldoriaWokenUp(true);
+ startExtraSequence(kCaldoria00SitDown, kExtraCompletedFlag, kFilterNoInput);
+ }
+ break;
+ case kCaldoria05:
+ if (direction == kWest && GameState.getCaldoriaINNAnnouncing())
+ loopCroppedMovie("Images/Caldoria/A05 Light Loop", kCaldoriaA05LightLoopLeft, kCaldoriaA05LightLoopTop);
+ break;
+ case kCaldoria07:
+ if (direction == kWest && GameState.getCaldoriaINNAnnouncing())
+ loopCroppedMovie("Images/Caldoria/A07 Light Loop", kCaldoriaA07LightLoopLeft, kCaldoriaA07LightLoopTop);
+ break;
+ case kCaldoria08:
+ if (direction == kWest)
+ setCurrentActivation(kActivateMirrorReady);
+ break;
+ case kCaldoria09:
+ _lastExtra = 0xffffffff;
+ break;
+ case kCaldoria11:
+ if (direction == kEast && !GameState.getCaldoriaSeenMessages())
+ loopCroppedMovie("Images/Caldoria/A11 Message Machine Loop", kCaldoria11MessageLoopLeft, kCaldoria11MessageLoopTop);
+ break;
+ case kCaldoria12:
+ if (direction == kNorth && !GameState.getCaldoriaSeenMessages())
+ loopCroppedMovie("Images/Caldoria/A12 Message Machine Loop", kCaldoria12MessageLoopLeft, kCaldoria12MessageLoopTop);
+ break;
+ case kCaldoria13:
+ if (direction == kNorth && !GameState.getCaldoriaSeenMessages())
+ loopCroppedMovie("Images/Caldoria/A13 Message Machine Loop", kCaldoria13MessageLoopLeft, kCaldoria13MessageLoopTop);
+ break;
+ case kCaldoria14:
+ if (direction == kNorth && !GameState.getCaldoriaSeenMessages())
+ loopCroppedMovie("Images/Caldoria/A14 Message Machine Loop", kCaldoria14MessageLoopLeft, kCaldoria14MessageLoopTop);
+ break;
+ case kCaldoria27:
+ case kCaldoria28:
+ case kCaldoria45:
+ if (direction == kNorth)
+ openElevatorMovie();
+ else
+ closeCroppedMovie();
+ break;
+ case kCaldoria48:
+ if (direction == kNorth && !GameState.getCaldoriaDoorBombed())
+ setCurrentActivation(kActivateRoofSlotEmpty);
+ break;
+ case kCaldoria53:
+ if (GameState.getCurrentDirection() == kEast && !GameState.getCaldoriaSinclairShot())
+ zoomToSinclair();
+ break;
+ case kCaldoria50:
+ if (direction == kNorth && !GameState.getCaldoriaSinclairShot())
+ setUpSinclairLoops();
+ break;
+ case kCaldoria54:
+ if (direction == kSouth && !GameState.getCaldoriaSinclairShot())
+ setUpSinclairLoops();
+ break;
+ case kCaldoria56:
+ if (_privateFlags.getFlag(kCaldoriaPrivateZoomingToBombFlag)) {
+ _privateFlags.setFlag(kCaldoriaPrivateZoomingToBombFlag, false);
+ newInteraction(kCaldoriaBombInteractionID);
+ } else if (GameState.getCaldoriaBombDisarmed()) {
+ _vm->playEndMessage();
+ }
+ break;
+ }
+
+ checkSinclairShootsOS();
+}
+
+void Caldoria::zoomTo(const Hotspot *zoomOutSpot) {
+ // Need to set _zoomOutSpot here because we may come through
+ // this function another way, say by pressing the down arrow,
+ // that doesn't involve the ClickInHotSpot function.
+ _zoomOutSpot = zoomOutSpot;
+
+ if (zoomOutSpot->getObjectID() == kCaldoriaDrawersOutSpotID) {
+ if (_privateFlags.getFlag(kCaloriaPrivateLeftDrawerOpenFlag)) {
+ _privateFlags.setFlag(kCaloriaPrivateLeftDrawerOpenFlag, false);
+ startExtraSequence(kLeftDrawerClose, kExtraCompletedFlag, kFilterNoInput);
+ } else if (_privateFlags.getFlag(kCaldoriaPrivateRightDrawerOpenFlag)) {
+ _privateFlags.setFlag(kCaldoriaPrivateRightDrawerOpenFlag, false);
+ if (GameState.isTakenItemID(kKeyCard))
+ startExtraSequence(kRightDrawerCloseNoKeys, kExtraCompletedFlag, false);
+ else
+ startExtraSequence(kRightDrawerCloseWithKeys, kExtraCompletedFlag, false);
+ } else {
+ Neighborhood::zoomTo(zoomOutSpot);
+ }
+ } else {
+ Neighborhood::zoomTo(zoomOutSpot);
+ }
+}
+
+void Caldoria::setUpSinclairLoops() {
+ _navMovie.stop();
+ scheduleNavCallBack(kSinclairLoopDoneFlag);
+ _sinclairLoopCount = 0;
+ _numSinclairLoops = 2;
+ _navMovie.start();
+}
+
+void Caldoria::zoomToSinclair() {
+ _utilityFuse.stopFuse();
+ _privateFlags.setFlag(kCaldoriaPrivateReadyToShootFlag, true);
+ setCurrentActivation(kActivateZoomedOnSinclair);
+
+ ExtraTable::Entry entry;
+ getExtraEntry(kCa53EastZoomToSinclair, entry);
+ _sinclairInterrupt.scheduleCallBack(kTriggerTimeFwd, entry.movieStart + kSinclairInterruptionTime1, _navMovie.getScale());
+ startExtraSequence(kCa53EastZoomToSinclair, kExtraCompletedFlag, kFilterAllInput);
+}
+
+void Caldoria::receiveNotification(Notification *notification, const NotificationFlags flags) {
+ Neighborhood::receiveNotification(notification, flags);
+
+ if ((flags & kExtraCompletedFlag) != 0) {
+ InventoryItem *item;
+ _interruptionFilter = kFilterAllInput;
+
+ switch (_lastExtra) {
+ case kCaldoria00WakeUp2:
+ makeContinuePoint();
+ // Force ArriveAt to do its thing...
+ GameState.setCurrentRoom(kNoRoomID);
+ arriveAt(kCaldoria00, kEast);
+ break;
+ case k4DEnvironOpenToINN:
+ GameState.setCaldoriaSeenINN(true);
+ GameState.setScoringSawINN(true);
+ // Fall through to k4DEnvironOpen...
+ case k4DEnvironOpen:
+ _privateFlags.setFlag(kCaldoriaPrivate4DSystemOpenFlag, true);
+ setCurrentActivation(kActivate4DOpen);
+ newInteraction(kCaldoria4DInteractionID);
+ break;
+ case kCaldoriaShowerUp:
+ GameState.setScoringTookShower(true);
+ GameState.setCaldoriaDoneHygiene(true);
+ break;
+ case kLeftDrawerClose:
+ case kRightDrawerCloseNoKeys:
+ case kRightDrawerCloseWithKeys:
+ if (_zoomOutSpot && _zoomOutSpot->getObjectID() == kCaldoriaDrawersOutSpotID) {
+ Input input;
+ clickInHotspot(input, _zoomOutSpot);
+ }
+ break;
+ case kCreateOrangeJuice:
+ setCurrentActivation(kActivateOJOnThePad);
+ requestSpotSound(kCaldoriaReplicatorOJChoiceIn, kCaldoriaReplicatorOJChoiceOut, kFilterNoInput, 0);
+ break;
+ case kCaldoria00SitDown:
+ arriveAt(kCaldoria00, kEast);
+ break;
+ case kCaldoria16ElevatorUp:
+ startExtraSequence(kCaldoria16ElevatorDown, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kCaldoria16ElevatorDown:
+ GameState.setCaldoriaSeenSinclairInElevator(true);
+ _privateFlags.setFlag(kCaldoriaPrivateCanOpenElevatorDoorFlag, true);
+ openDoor();
+ break;
+ case kCaldoriaFourthToGround:
+ case kCaldoriaRoofToGround:
+ arriveAt(kCaldoria28, GameState.getCurrentDirection());
+ break;
+ case kCaldoriaFourthToRoof:
+ case kCaldoriaGroundToRoof:
+ arriveAt(kCaldoria45, GameState.getCurrentDirection());
+ break;
+ case kCaldoriaGroundToFourth:
+ case kCaldoriaRoofToFourth:
+ arriveAt(kCaldoria27, GameState.getCurrentDirection());
+ break;
+ case kCaGTCardSwipe:
+ item = (InventoryItem *)_vm->getAllItems().findItemByID(kKeyCard);
+ _vm->addItemToInventory(item);
+ setCurrentActivation(kActivateReadyToTransport);
+ break;
+ case kCaGTFryTheFly:
+ case kCaGTGoToTSA:
+ _vm->jumpToNewEnvironment(kFullTSAID, kTSA00, kNorth);
+ break;
+ case kCaGTGoToTokyo:
+ playDeathExtra(kCaGTArriveAtTokyo, kDeathUncreatedInCaldoria);
+ break;
+ case kCaGTGoToBeach:
+ playDeathExtra(kCaGTArriveAtBeach, kDeathUncreatedInCaldoria);
+ break;
+ case kCa48NorthExplosion:
+ // Current biochip must be the shield if we got here.
+ _vm->getCurrentBiochip()->setItemState(kShieldNormal);
+ break;
+ case kBinocularsZoomInOnShip:
+ setCurrentActivation(kActivateFocusedOnShip);
+ break;
+ case kCa49NorthVoiceAnalysis:
+ _utilityFuse.primeFuse(kSinclairShootsTimeLimit);
+ _utilityFuse.setFunctor(new Common::Functor0Mem<void, Caldoria>(this, &Caldoria::sinclairTimerExpired));
+ _utilityFuse.lightFuse();
+ GameState.setCaldoriaSawVoiceAnalysis(true);
+ break;
+ case kCa53EastZoomToSinclair:
+ if (GameState.getCaldoriaSinclairShot()) {
+ delete _gunSprite;
+ _gunSprite = 0;
+ startExtraSequence(kCa53EastShootSinclair, kExtraCompletedFlag, false);
+ } else {
+ playDeathExtra(kCa53EastDeath2, kDeathSinclairShotDelegate);
+ }
+ break;
+ case kCa53EastShootSinclair:
+ _vm->addItemToInventory((InventoryItem *)_vm->getAllItems().findItemByID(kStunGun));
+ startExtraSequence(kCa53EastZoomOutFromSinclair, kExtraCompletedFlag, false);
+ GameState.setScoringStunnedSinclair(true);
+ break;
+ case kCa53EastZoomOutFromSinclair:
+ setCurrentAlternate(kAltCaldoriaSinclairDown);
+ updateViewFrame();
+ makeContinuePoint();
+ break;
+ }
+ } else if ((flags & kSpotSoundCompletedFlag) != 0) {
+ switch (GameState.getCurrentRoom()) {
+ case kCaldoria20:
+ case kCaldoria21:
+ case kCaldoria26:
+ case kCaldoria29:
+ case kCaldoria34:
+ case kCaldoria35:
+ updateViewFrame();
+ break;
+ case kCaldoria27:
+ case kCaldoria28:
+ case kCaldoria45:
+ updateElevatorMovie();
+ break;
+ case kCaldoriaReplicator:
+ emptyOJGlass();
+ break;
+ }
+ } else if ((flags & kSinclairLoopDoneFlag) != 0) {
+ if (++_sinclairLoopCount == _numSinclairLoops) {
+ switch (GameState.getCurrentRoom()) {
+ case kCaldoria50:
+ playDeathExtra(kCa50SinclairShoots, kDeathShotBySinclair);
+ break;
+ case kCaldoria54:
+ playDeathExtra(kCa54SouthDeath, kDeathShotBySinclair);
+ break;
+ }
+ } else {
+ _navMovie.stop();
+ scheduleNavCallBack(kSinclairLoopDoneFlag);
+ _navMovie.start();
+ }
+ }
+
+ g_AIArea->checkMiddleArea();
+}
+
+InputBits Caldoria::getInputFilter() {
+ InputBits result = Neighborhood::getInputFilter();
+
+ switch (GameState.getCurrentRoom()) {
+ case kCaldoria00:
+ if (_privateFlags.getFlag(kCaldoriaPrivate4DSystemOpenFlag))
+ result &= ~kFilterAllDirections;
+ break;
+ case kCaldoriaBinoculars:
+ if (getCurrentActivation() == kActivateNotFocusedOnShip)
+ result &= ~(kFilterDownButton | kFilterDownAuto);
+ break;
+ case kCaldoria53:
+ if (_privateFlags.getFlag(kCaldoriaPrivateReadyToShootFlag) && !GameState.getCaldoriaSinclairShot())
+ result &= ~kFilterAllDirections;
+ break;
+ case kCaldoria48:
+ if (GameState.getCaldoriaDoorBombed())
+ result &= ~kFilterAllDirections;
+ }
+
+ return result;
+}
+
+void Caldoria::activateHotspots() {
+ Neighborhood::activateHotspots();
+
+ switch (GameState.getCurrentRoom()) {
+ case kCaldoriaDrawers:
+ if (getCurrentActivation() == kActivateRightOpen) {
+ if (GameState.isTakenItemID(kKeyCard)) {
+ _vm->getAllHotspots().activateOneHotspot(kCaldoriaRightDrawerNoKeysCloseSpotID);
+ _vm->getAllHotspots().deactivateOneHotspot(kCaldoriaRightDrawerWithKeysCloseSpotID);
+ } else {
+ _vm->getAllHotspots().activateOneHotspot(kCaldoriaRightDrawerWithKeysCloseSpotID);
+ _vm->getAllHotspots().deactivateOneHotspot(kCaldoriaRightDrawerNoKeysCloseSpotID);
+ }
+ }
+ case kCaldoriaReplicator:
+ if (GameState.getCaldoriaMadeOJ())
+ _vm->getAllHotspots().deactivateOneHotspot(kCaldoriaMakeOJSpotID);
+ break;
+ case kCaldoria27:
+ if (GameState.isCurrentDoorOpen()) {
+ _vm->getAllHotspots().deactivateOneHotspot(kCaldoriaFourthFloorElevator1);
+ _vm->getAllHotspots().deactivateOneHotspot(kCaldoriaFourthFloorElevator2);
+ _vm->getAllHotspots().deactivateOneHotspot(kCaldoriaFourthFloorElevator3);
+ _vm->getAllHotspots().deactivateOneHotspot(kCaldoriaFourthFloorElevator4);
+ _vm->getAllHotspots().deactivateOneHotspot(kCaldoriaFourthFloorElevator5);
+ }
+ break;
+ case kCaldoria28:
+ if (GameState.isCurrentDoorOpen()) {
+ _vm->getAllHotspots().deactivateOneHotspot(kCaldoriaGroundElevator1);
+ _vm->getAllHotspots().deactivateOneHotspot(kCaldoriaGroundElevator2);
+ _vm->getAllHotspots().deactivateOneHotspot(kCaldoriaGroundElevator3);
+ _vm->getAllHotspots().deactivateOneHotspot(kCaldoriaGroundElevator4);
+ _vm->getAllHotspots().deactivateOneHotspot(kCaldoriaGroundElevator5);
+ }
+ break;
+ case kCaldoria45:
+ if (GameState.isCurrentDoorOpen()) {
+ _vm->getAllHotspots().deactivateOneHotspot(kCaldoriaRoofElevator1);
+ _vm->getAllHotspots().deactivateOneHotspot(kCaldoriaRoofElevator2);
+ _vm->getAllHotspots().deactivateOneHotspot(kCaldoriaRoofElevator3);
+ _vm->getAllHotspots().deactivateOneHotspot(kCaldoriaRoofElevator4);
+ _vm->getAllHotspots().deactivateOneHotspot(kCaldoriaRoofElevator5);
+ }
+ break;
+ }
+}
+
+void Caldoria::clickInHotspot(const Input &input, const Hotspot *spot) {
+ switch (spot->getObjectID()) {
+ case kCa4DEnvironOpenSpotID:
+ if (!GameState.getCaldoriaINNAnnouncing() || GameState.getCaldoriaSeenINN()) {
+ startExtraSequence(k4DEnvironOpen, kExtraCompletedFlag, kFilterNoInput);
+ } else {
+ // This trick depends on the following sequences being in order in the
+ // world movie:
+ // k4DEnvironOpenToINN
+ // k4DINNInterruption
+ // k4DINNIntro
+ // k4DINNMarkJohnson
+ // k4DINNMeganLove
+ // k4DINNFadeOut
+ // k4DEnvironOpenFromINN
+ loadLoopSound1("");
+ loadLoopSound2("");
+ startExtraLongSequence(k4DEnvironOpenToINN, k4DEnvironOpenFromINN, kExtraCompletedFlag, kFilterNoInput);
+ }
+ break;
+ case kCa4DEnvironCloseSpotID:
+ ((Caldoria4DSystem *)_currentInteraction)->shutDown4DSystem();
+ break;
+ case kCaBathroomMirrorSpotID:
+ newInteraction(kCaldoriaMirrorInteractionID);
+ break;
+ case kCaShowerSpotID:
+ requestExtraSequence(kCaldoriaShowerTitle, 0, kFilterNoInput);
+ requestExtraSequence(kCaldoriaShowerButton, 0, kFilterNoInput);
+ requestExtraSequence(kCaldoriaShowerDown, 0, kFilterNoInput);
+ requestExtraSequence(kCaldoriaShowerUp, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kCaldoriaLeftDrawerOpenSpotID:
+ _privateFlags.setFlag(kCaloriaPrivateLeftDrawerOpenFlag, true);
+ setCurrentActivation(kActivateLeftOpen);
+ startExtraSequence(kLeftDrawerOpen, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kCaldoriaLeftDrawerCloseSpotID:
+ _privateFlags.setFlag(kCaloriaPrivateLeftDrawerOpenFlag, false);
+ setCurrentActivation(kActivateDrawersClosed);
+ startExtraSequence(kLeftDrawerClose, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kCaldoriaRightDrawerOpenSpotID:
+ _privateFlags.setFlag(kCaldoriaPrivateRightDrawerOpenFlag, true);
+ setCurrentActivation(kActivateRightOpen);
+ if (GameState.isTakenItemID(kKeyCard))
+ startExtraSequence(kRightDrawerOpenNoKeys, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraSequence(kRightDrawerOpenWithKeys, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kCaldoriaRightDrawerWithKeysCloseSpotID:
+ _privateFlags.setFlag(kCaldoriaPrivateRightDrawerOpenFlag, false);
+ setCurrentActivation(kActivateDrawersClosed);
+ startExtraSequence(kRightDrawerCloseWithKeys, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kCaldoriaRightDrawerNoKeysCloseSpotID:
+ _privateFlags.setFlag(kCaldoriaPrivateRightDrawerOpenFlag, false);
+ setCurrentActivation(kActivateDrawersClosed);
+ startExtraSequence(kRightDrawerCloseNoKeys, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kCaldoriaMakeStickyBunsSpotID:
+ requestSpotSound(kCaldoriaReplicatorWrongChoiceIn, kCaldoriaReplicatorWrongChoiceOut, kFilterNoInput, 0);
+ break;
+ case kCaldoriaMakeOJSpotID:
+ GameState.setCaldoriaMadeOJ(true);
+ startExtraSequence(kCreateOrangeJuice, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kCaBedroomVidPhoneActivationSpotID:
+ newInteraction(kCaldoriaMessagesInteractionID);
+ break;
+ case kCaldoriaFourthFloorElevatorSpotID:
+ if (!GameState.getCaldoriaSeenSinclairInElevator()) {
+ startExtraSequence(kCaldoria16ElevatorUp, kExtraCompletedFlag, kFilterNoInput);
+ } else {
+ _privateFlags.setFlag(kCaldoriaPrivateCanOpenElevatorDoorFlag, true);
+ openDoor();
+ }
+ break;
+ case kCaldoriaGroundElevatorSpotID:
+ _privateFlags.setFlag(kCaldoriaPrivateCanOpenElevatorDoorFlag, true);
+ openDoor();
+ break;
+ case kCaldoriaRoofElevatorSpotID:
+ _privateFlags.setFlag(kCaldoriaPrivateCanOpenElevatorDoorFlag, true);
+ openDoor();
+ break;
+ case kCaldoriaFourthFloorElevator1:
+ case kCaldoriaFourthFloorElevator2:
+ case kCaldoriaFourthFloorElevator3:
+ case kCaldoriaFourthFloorElevator4:
+ case kCaldoriaFourthFloorElevator5:
+ // Assumes that elevator hot spots are consecutive.
+ takeElevator(4, spot->getObjectID() - kCaldoriaFourthFloorElevator1 + 1);
+ break;
+ case kCaldoriaGroundElevator1:
+ case kCaldoriaGroundElevator2:
+ case kCaldoriaGroundElevator3:
+ case kCaldoriaGroundElevator4:
+ case kCaldoriaGroundElevator5:
+ // Assumes that elevator hot spots are consecutive.
+ takeElevator(1, spot->getObjectID() - kCaldoriaGroundElevator1 + 1);
+ break;
+ case kCaldoriaRoofElevator1:
+ case kCaldoriaRoofElevator2:
+ case kCaldoriaRoofElevator3:
+ case kCaldoriaRoofElevator4:
+ case kCaldoriaRoofElevator5:
+ // Assumes that elevator hot spots are consecutive.
+ takeElevator(5, spot->getObjectID() - kCaldoriaRoofElevator1 + 1);
+ break;
+ case kCaldoriaGTTokyoSpotID:
+ startExtraSequence(kCaGTGoToTokyo, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kCaldoriaGTTSASpotID:
+ GameState.setScoringGoToTSA(true);
+ startExtraLongSequence(kCaGTFryTheFly, kCaGTGoToTSA, kExtraCompletedFlag, false);
+ break;
+ case kCaldoriaGTBeachSpotID:
+ startExtraSequence(kCaGTGoToBeach, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kCaldoriaGTOtherSpotID:
+ showExtraView(kCaGTOtherChoice);
+ playSpotSoundSync(kCaldoriaNoOtherDestinationIn, kCaldoriaNoOtherDestinationOut);
+ showExtraView(kCaGTCardSwipe);
+ break;
+ case kCaldoriaZoomInOnShipSpotID:
+ startExtraSequence(kBinocularsZoomInOnShip, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kCaldoriaRoofDoorSpotID:
+ startExtraSequence(kCa48NorthRooftopClosed, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kCaldoria20DoorbellSpotID:
+ case kCaldoria21DoorbellSpotID:
+ case kCaldoria26DoorbellSpotID:
+ case kCaldoria29DoorbellSpotID:
+ case kCaldoria34DoorbellSpotID:
+ case kCaldoria35DoorbellSpotID:
+ clickOnDoorbell(spot->getObjectID());
+ break;
+ default:
+ Neighborhood::clickInHotspot(input, spot);
+ break;
+ }
+}
+
+void Caldoria::clickOnDoorbell(const HotSpotID doorBellSpotID) {
+ uint32 extra;
+ ExtraTable::Entry entry;
+
+ switch (doorBellSpotID) {
+ case kCaldoria20DoorbellSpotID:
+ extra = kCaldoria20Doorbell;
+ break;
+ case kCaldoria21DoorbellSpotID:
+ extra = kCaldoria21Doorbell;
+ break;
+ case kCaldoria26DoorbellSpotID:
+ extra = kCaldoria26Doorbell;
+ break;
+ case kCaldoria29DoorbellSpotID:
+ extra = kCaldoria29Doorbell;
+ break;
+ case kCaldoria34DoorbellSpotID:
+ extra = kCaldoria34Doorbell;
+ break;
+ case kCaldoria35DoorbellSpotID:
+ extra = kCaldoria35Doorbell;
+ break;
+ default:
+ error("Invalid doorbell hotspot");
+ }
+
+ getExtraEntry(extra, entry);
+ showViewFrame(entry.movieStart);
+ requestSpotSound(kCaldoriaNobodyHomeIn, kCaldoriaNobodyHomeOut, kFilterNoInput, kSpotSoundCompletedFlag);
+}
+
+CanOpenDoorReason Caldoria::canOpenDoor(DoorTable::Entry &entry) {
+ switch (GameState.getCurrentRoom()) {
+ case kCaldoria16:
+ case kCaldoria38:
+ case kCaldoria46:
+ if (GameState.getCurrentDirection() == kSouth && !_privateFlags.getFlag(kCaldoriaPrivateCanOpenElevatorDoorFlag))
+ return kCantOpenLocked;
+ break;
+ }
+
+ return Neighborhood::canOpenDoor(entry);
+}
+
+void Caldoria::doorOpened() {
+ Neighborhood::doorOpened();
+ _privateFlags.setFlag(kCaldoriaPrivateCanOpenElevatorDoorFlag, false);
+}
+
+GameInteraction *Caldoria::makeInteraction(const InteractionID interactionID) {
+ switch (interactionID) {
+ case kCaldoria4DInteractionID:
+ return new Caldoria4DSystem(this);
+ case kCaldoriaBombInteractionID:
+ return new CaldoriaBomb(this, _vm);
+ case kCaldoriaMessagesInteractionID:
+ return new CaldoriaMessages(this, kCaldoriaMessagesNotificationID, _vm);
+ case kCaldoriaMirrorInteractionID:
+ return new CaldoriaMirror(this);
+ }
+
+ return 0;
+}
+
+void Caldoria::newInteraction(const InteractionID interactionID) {
+ Neighborhood::newInteraction(interactionID);
+
+ if (!_currentInteraction) {
+ if (_privateFlags.getFlag(kCaldoriaPrivate4DSystemOpenFlag)) {
+ _privateFlags.setFlag(kCaldoriaPrivate4DSystemOpenFlag, false);
+ setCurrentActivation(kActivate4DClosed);
+ startExtraSequence(k4DEnvironClose, kExtraCompletedFlag, kFilterNoInput);
+ } else if (GameState.getCaldoriaBombDisarmed()) {
+ turnLeft();
+ }
+ }
+}
+
+// Only called when trying to pick up an item and the player can't (because
+// the inventory is too full or because the player lets go of the item before
+// dropping it into the inventory).
+Hotspot *Caldoria::getItemScreenSpot(Item *item, DisplayElement *element) {
+ HotSpotID destSpotID = kNoHotSpotID;
+
+ switch (item->getObjectID()) {
+ case kKeyCard:
+ destSpotID = kCaldoriaKeyCardSpotID;
+ break;
+ case kOrangeJuiceGlassEmpty:
+ case kOrangeJuiceGlassFull:
+ destSpotID = kCaldoriaOrangeJuiceSpotID;
+ break;
+ }
+
+ if (destSpotID == kNoHotSpotID)
+ return Neighborhood::getItemScreenSpot(item, element);
+
+ return _vm->getAllHotspots().findHotspotByID(destSpotID);
+}
+
+void Caldoria::pickedUpItem(Item *item) {
+ switch (item->getObjectID()) {
+ case kKeyCard:
+ GameState.setScoringGotKeyCard(true);
+ break;
+ case kOrangeJuiceGlassFull:
+ setCurrentActivation(kActivateReplicatorReady);
+ requestSpotSound(kCaldoriaDrinkOJIn, kCaldoriaDrinkOJOut, kFilterNoInput, kSpotSoundCompletedFlag);
+ break;
+ case kStunGun:
+ GameState.setCaldoriaGunAimed(false);
+ break;
+ }
+}
+
+void Caldoria::dropItemIntoRoom(Item *item, Hotspot *dropSpot) {
+ switch (item->getObjectID()) {
+ case kKeyCard:
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ if (dropSpot->getObjectID() == kCaldoriaGTCardDropSpotID)
+ startExtraSequence(kCaGTCardSwipe, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kOrangeJuiceGlassEmpty:
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ if (dropSpot->getObjectID() == kCaldoriaOrangeJuiceDropSpotID) {
+ GameState.setCaldoriaMadeOJ(false);
+ startExtraSequence(kDisposeOrangeJuice, kExtraCompletedFlag, kFilterNoInput);
+ }
+ break;
+ case kCardBomb:
+ GameState.setCaldoriaDoorBombed(true);
+ setCurrentActivation(kActivateHotSpotAlways);
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ // Long enough for AI hints...?
+ _utilityFuse.primeFuse(kCardBombCountDownTime);
+ _utilityFuse.setFunctor(new Common::Functor0Mem<void, Caldoria>(this, &Caldoria::doorBombTimerExpired));
+ _utilityFuse.lightFuse();
+ GameState.setCaldoriaFuseTimeLimit(kCardBombCountDownTime);
+ loopCroppedMovie("Images/Caldoria/A48 Bomb Loop", kCaldoria48CardBombLoopLeft, kCaldoria48CardBombLoopTop);
+ GameState.setScoringUsedCardBomb(true);
+ break;
+ case kStunGun:
+ GameState.setCaldoriaGunAimed(true);
+ GameState.setCaldoriaSinclairShot(true);
+ _gunSprite = item->getDragSprite(0);
+ _gunSprite->setCurrentFrameIndex(1);
+ _gunSprite->setDisplayOrder(kDragSpriteOrder);
+ _gunSprite->moveElementTo(kCaldoriaGunSpriteLeft, kCaldoriaGunSpriteTop);
+ _gunSprite->startDisplaying();
+ _gunSprite->show();
+ break;
+ default:
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ break;
+ }
+}
+
+void Caldoria::takeElevator(uint startFloor, uint endFloor) {
+ _croppedMovie.stop();
+ _croppedMovie.setSegment(0, _croppedMovie.getDuration());
+
+ switch (startFloor) {
+ case 1:
+ switch (endFloor) {
+ case 1:
+ // Do nothing.
+ break;
+ case 2:
+ _croppedMovie.setTime(k1To2Time);
+ requestSpotSound(kCaldoriaNoOtherDestinationIn, kCaldoriaNoOtherDestinationOut, kFilterNoInput, kSpotSoundCompletedFlag);
+ break;
+ case 3:
+ _croppedMovie.setTime(k1To3Time);
+ requestSpotSound(kCaldoriaNoOtherDestinationIn, kCaldoriaNoOtherDestinationOut, kFilterNoInput, kSpotSoundCompletedFlag);
+ break;
+ case 4:
+ _croppedMovie.setSegment(k1To4Start, k1To4Stop);
+ _croppedMovie.setTime(k1To4Start);
+ startExtraSequence(kCaldoriaGroundToFourth, kExtraCompletedFlag, false);
+ _croppedMovie.start();
+ break;
+ case 5:
+ _croppedMovie.setSegment(k1To5Start, k1To5Stop);
+ _croppedMovie.setTime(k1To5Start);
+ startExtraSequence(kCaldoriaGroundToRoof, kExtraCompletedFlag, false);
+ _croppedMovie.start();
+ break;
+ }
+ break;
+ case 4:
+ switch (endFloor) {
+ case 1:
+ _croppedMovie.setSegment(k4To1Start, k4To1Stop);
+ _croppedMovie.setTime(k4To1Start);
+ startExtraSequence(kCaldoriaFourthToGround, kExtraCompletedFlag, false);
+ _croppedMovie.start();
+ break;
+ case 2:
+ _croppedMovie.setTime(k4To2Time);
+ requestSpotSound(kCaldoriaNoOtherDestinationIn, kCaldoriaNoOtherDestinationOut, kFilterNoInput, kSpotSoundCompletedFlag);
+ break;
+ case 3:
+ _croppedMovie.setTime(k4To3Time);
+ requestSpotSound(kCaldoriaNoOtherDestinationIn, kCaldoriaNoOtherDestinationOut, kFilterNoInput, kSpotSoundCompletedFlag);
+ break;
+ case 4:
+ // Do nothing.
+ break;
+ case 5:
+ _croppedMovie.setSegment(k4To5Start, k4To5Stop);
+ _croppedMovie.setTime(k4To5Start);
+ startExtraSequence(kCaldoriaFourthToRoof, kExtraCompletedFlag, false);
+ _croppedMovie.start();
+ break;
+ }
+ break;
+ case 5:
+ switch (endFloor) {
+ case 1:
+ _croppedMovie.setSegment(k5To1Start, k5To1Stop);
+ _croppedMovie.setTime(k5To1Start);
+ startExtraSequence(kCaldoriaRoofToGround, kExtraCompletedFlag, false);
+ _croppedMovie.start();
+ break;
+ case 2:
+ _croppedMovie.setTime(k5To2Time);
+ requestSpotSound(kCaldoriaNoOtherDestinationIn, kCaldoriaNoOtherDestinationOut, kFilterNoInput, kSpotSoundCompletedFlag);
+ break;
+ case 3:
+ _croppedMovie.setTime(k5To3Time);
+ requestSpotSound(kCaldoriaNoOtherDestinationIn, kCaldoriaNoOtherDestinationOut, kFilterNoInput, kSpotSoundCompletedFlag);
+ break;
+ case 4:
+ _croppedMovie.setSegment(k5To4Start, k5To4Stop);
+ _croppedMovie.setTime(k5To4Start);
+ startExtraSequence(kCaldoriaRoofToFourth, kExtraCompletedFlag, false);
+ _croppedMovie.start();
+ break;
+ case 5:
+ // Do nothing.
+ break;
+ }
+ break;
+ };
+}
+
+void Caldoria::updateElevatorMovie() {
+ TimeValue time = 0xffffffff;
+
+ if (GameState.getCurrentDirection() == kNorth) {
+ switch (GameState.getCurrentRoom()) {
+ case kCaldoria27:
+ time = k4FloorTime;
+ break;
+ case kCaldoria28:
+ time = k1FloorTime;
+ break;
+ case kCaldoria45:
+ time = k5FloorTime;
+ break;
+ }
+ }
+
+ _croppedMovie.stop();
+
+ if (time == 0xffffffff) {
+ _croppedMovie.hide();
+ } else {
+ _croppedMovie.stop();
+ _croppedMovie.setSegment(0, _croppedMovie.getDuration());
+ _croppedMovie.setTime(time);
+ _croppedMovie.redrawMovieWorld();
+ _croppedMovie.show();
+
+ // *** Why do I need this?
+ // clone2727: "don't ask me!"
+ _navMovie.redrawMovieWorld();
+ }
+}
+
+void Caldoria::openElevatorMovie() {
+ if (!_croppedMovie.isSurfaceValid())
+ openCroppedMovie("Images/Caldoria/Caldoria Elevator.movie", kCaldoriaElevatorLeft, kCaldoriaElevatorTop);
+
+ updateElevatorMovie();
+}
+
+void Caldoria::emptyOJGlass() {
+ GameState.setTakenItemID(kOrangeJuiceGlassFull, false);
+ GameState.setTakenItemID(kOrangeJuiceGlassEmpty, true);
+ _vm->removeItemFromInventory((InventoryItem *)_vm->getAllItems().findItemByID(kOrangeJuiceGlassFull));
+ _vm->addItemToInventory((InventoryItem *)_vm->getAllItems().findItemByID(kOrangeJuiceGlassEmpty));
+}
+
+void Caldoria::doorBombTimerExpired() {
+ closeCroppedMovie();
+
+ if (GameState.getShieldOn()) {
+ _vm->getCurrentBiochip()->setItemState(kShieldCardBomb);
+ setCurrentAlternate(kAltCaldoriaRoofDoorBlown);
+ startExtraSequence(kCa48NorthExplosion, kExtraCompletedFlag, kFilterNoInput);
+ GameState.setScoringShieldedCardBomb(true);
+ GameState.setCaldoriaDoorBombed(false);
+ GameState.setCaldoriaRoofDoorOpen(true);
+ } else {
+ playDeathExtra(kCa48NorthExplosionDeath, kDeathCardBomb);
+ }
+}
+
+void Caldoria::sinclairTimerExpired() {
+ _privateFlags.setFlag(kCaldoriaPrivateSinclairTimerExpiredFlag, true);
+ checkSinclairShootsOS();
+}
+
+void Caldoria::checkSinclairShootsOS() {
+ if (_privateFlags.getFlag(kCaldoriaPrivateSinclairTimerExpiredFlag))
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kCaldoria49, kNorth):
+ case MakeRoomView(kCaldoria49, kSouth):
+ case MakeRoomView(kCaldoria49, kEast):
+ case MakeRoomView(kCaldoria49, kWest):
+ case MakeRoomView(kCaldoria50, kSouth):
+ case MakeRoomView(kCaldoria50, kEast):
+ case MakeRoomView(kCaldoria50, kWest):
+ case MakeRoomView(kCaldoria51, kNorth):
+ case MakeRoomView(kCaldoria51, kSouth):
+ case MakeRoomView(kCaldoria51, kWest):
+ case MakeRoomView(kCaldoria52, kNorth):
+ case MakeRoomView(kCaldoria52, kSouth):
+ case MakeRoomView(kCaldoria52, kWest):
+ case MakeRoomView(kCaldoria53, kNorth):
+ case MakeRoomView(kCaldoria53, kSouth):
+ case MakeRoomView(kCaldoria53, kWest):
+ case MakeRoomView(kCaldoria54, kNorth):
+ case MakeRoomView(kCaldoria54, kEast):
+ case MakeRoomView(kCaldoria54, kWest):
+ playSpotSoundSync(kCaldoriaSinclairShootsOSIn, kCaldoriaSinclairShootsOSOut);
+ playSpotSoundSync(kCaldoriaScreamingAfterIn, kCaldoriaScreamingAfterOut);
+ die(kDeathSinclairShotDelegate);
+ break;
+ }
+}
+
+void Caldoria::checkInterruptSinclair() {
+ if (GameState.getCaldoriaSinclairShot()) {
+ _navMovie.stop();
+ _neighborhoodNotification.setNotificationFlags(kExtraCompletedFlag, kExtraCompletedFlag);
+ g_AIArea->unlockAI();
+ } else {
+ uint32 currentTime = _navMovie.getTime();
+
+ ExtraTable::Entry entry;
+ getExtraEntry(kCa53EastZoomToSinclair, entry);
+
+ if (currentTime < entry.movieStart + kSinclairInterruptionTime2)
+ _sinclairInterrupt.scheduleCallBack(kTriggerTimeFwd, entry.movieStart + kSinclairInterruptionTime2,
+ _navMovie.getScale());
+ else if (currentTime < entry.movieStart + kSinclairInterruptionTime3)
+ _sinclairInterrupt.scheduleCallBack(kTriggerTimeFwd, entry.movieStart + kSinclairInterruptionTime3,
+ _navMovie.getScale());
+ else if (currentTime < entry.movieStart + kSinclairInterruptionTime4)
+ _sinclairInterrupt.scheduleCallBack(kTriggerTimeFwd, entry.movieStart + kSinclairInterruptionTime4,
+ _navMovie.getScale());
+ }
+}
+
+Common::String Caldoria::getBriefingMovie() {
+ Common::String movieName = Neighborhood::getBriefingMovie();
+
+ if (movieName.empty()) {
+ if (GameState.allTimeZonesFinished())
+ return "Images/AI/Caldoria/XA02";
+
+ return "Images/AI/Caldoria/XA01";
+ }
+
+ return movieName;
+}
+
+Common::String Caldoria::getEnvScanMovie() {
+ Common::String movieName = Neighborhood::getEnvScanMovie();
+
+ if (movieName.empty()) {
+ RoomID room = GameState.getCurrentRoom();
+
+ if (room >= kCaldoria00 && room <= kCaldoria14) {
+ // Inside apartment.
+ if (GameState.getCaldoriaDoneHygiene())
+ return "Images/AI/Caldoria/XAE2";
+
+ return "Images/AI/Caldoria/XAE1";
+ } else if (room >= kCaldoria15 && room <= kCaldoria48) {
+ // Wandering the halls...
+ return "Images/AI/Caldoria/XAE3";
+ } else {
+ // Must be the roof.
+ return "Images/AI/Caldoria/XAEH2";
+ }
+ }
+
+ return movieName;
+}
+
+uint Caldoria::getNumHints() {
+ uint numHints = Neighborhood::getNumHints();
+
+ if (numHints == 0) {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kCaldoria44, kEast):
+ if (!GameState.isTakenItemID(kKeyCard) && GameState.getOpenDoorRoom() == kNoRoomID)
+ numHints = 1;
+ break;
+ case MakeRoomView(kCaldoria48, kNorth):
+ if (!GameState.getCaldoriaRoofDoorOpen()) {
+ if (_croppedMovie.isRunning()) // Bomb must be looping.
+ numHints = 3;
+ else if (GameState.isTakenItemID(kCardBomb))
+ numHints = 1;
+ }
+ break;
+ case MakeRoomView(kCaldoria49, kEast):
+ case MakeRoomView(kCaldoria54, kEast):
+ numHints = 1;
+ break;
+ case MakeRoomView(kCaldoria49, kNorth):
+ numHints = 1;
+ break;
+ }
+ }
+
+ return numHints;
+}
+
+Common::String Caldoria::getHintMovie(uint hintNum) {
+ Common::String movieName = Neighborhood::getHintMovie(hintNum);
+
+ if (movieName.empty()) {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kCaldoria44, kEast):
+ return "Images/AI/Caldoria/X42WH2";
+ case MakeRoomView(kCaldoria48, kNorth):
+ if (_croppedMovie.isRunning()) { // Bomb must be looping.
+ if (hintNum == 1)
+ return "Images/AI/Caldoria/X48ND1";
+ else if (hintNum == 2)
+ return "Images/AI/Caldoria/X48ND2";
+ else if (GameState.isTakenItemID(kShieldBiochip))
+ return "Images/AI/Caldoria/X48ND3";
+
+ // *** Doesn't work yet, need global movies.
+ break;
+ }
+
+ return "Images/AI/Globals/XGLOB1A";
+ case MakeRoomView(kCaldoria49, kEast):
+ case MakeRoomView(kCaldoria54, kEast):
+ return "Images/AI/Caldoria/X49E";
+ case MakeRoomView(kCaldoria49, kNorth):
+ return "Images/AI/Caldoria/X49NB2";
+ }
+ }
+
+ return movieName;
+}
+
+void Caldoria::updateCursor(const Common::Point where, const Hotspot *cursorSpot) {
+ if (cursorSpot) {
+ switch (cursorSpot->getObjectID()) {
+ case kCa4DEnvironCloseSpotID:
+ _vm->_cursor->setCurrentFrameIndex(2);
+ return;
+ case kCaldoriaKioskSpotID:
+ _vm->_cursor->setCurrentFrameIndex(3);
+ return;
+ }
+ }
+
+ Neighborhood::updateCursor(where, cursorSpot);
+}
+
+Common::String Caldoria::getNavMovieName() {
+ return "Images/Caldoria/Caldoria.movie";
+}
+
+Common::String Caldoria::getSoundSpotsName() {
+ return "Sounds/Caldoria/Caldoria Spots";
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/caldoria/caldoria.h b/engines/pegasus/neighborhood/caldoria/caldoria.h
new file mode 100644
index 0000000000..3d6a155170
--- /dev/null
+++ b/engines/pegasus/neighborhood/caldoria/caldoria.h
@@ -0,0 +1,523 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_CALDORIA_CALDORIA_H
+#define PEGASUS_NEIGHBORHOOD_CALDORIA_CALDORIA_H
+
+#include "pegasus/neighborhood/neighborhood.h"
+
+namespace Pegasus {
+
+static const TimeScale kCaldoriaMovieScale = 600;
+static const TimeScale kCaldoriaFramesPerSecond = 15;
+static const TimeScale kCaldoriaFrameDuration = 40;
+
+// Alternate IDs.
+
+static const AlternateID kAltCaldoriaNormal = 0;
+static const AlternateID kAltCaldoriaRoofDoorBlown = 2;
+static const AlternateID kAltCaldoriaSinclairDown = 3;
+
+// Room IDs.
+
+static const RoomID kCaldoria00 = 1;
+static const RoomID kCaldoria01 = 2;
+static const RoomID kCaldoria02 = 3;
+static const RoomID kCaldoria03 = 4;
+static const RoomID kCaldoria04 = 5;
+static const RoomID kCaldoria05 = 6;
+static const RoomID kCaldoria06 = 7;
+static const RoomID kCaldoria07 = 8;
+static const RoomID kCaldoria08 = 9;
+static const RoomID kCaldoria09 = 10;
+static const RoomID kCaldoria10 = 11;
+static const RoomID kCaldoriaToilet = 12;
+static const RoomID kCaldoria11 = 13;
+static const RoomID kCaldoria12 = 14;
+static const RoomID kCaldoriaVidPhone = 15;
+static const RoomID kCaldoriaReplicator = 16;
+static const RoomID kCaldoriaDrawers = 17;
+static const RoomID kCaldoria13 = 18;
+static const RoomID kCaldoria14 = 19;
+static const RoomID kCaldoria15 = 20;
+static const RoomID kCaldoria16 = 21;
+static const RoomID kCaldoria17 = 22;
+static const RoomID kCaldoria18 = 23;
+static const RoomID kCaldoria19 = 24;
+static const RoomID kCaldoria20 = 25;
+static const RoomID kCaldoria21 = 26;
+static const RoomID kCaldoria22 = 27;
+static const RoomID kCaldoria23 = 28;
+static const RoomID kCaldoria24 = 29;
+static const RoomID kCaldoria25 = 30;
+static const RoomID kCaldoria26 = 31;
+static const RoomID kCaldoria27 = 32;
+static const RoomID kCaldoria28 = 33;
+static const RoomID kCaldoria29 = 34;
+static const RoomID kCaldoria30 = 35;
+static const RoomID kCaldoria31 = 36;
+static const RoomID kCaldoria32 = 37;
+static const RoomID kCaldoria33 = 38;
+static const RoomID kCaldoria34 = 39;
+static const RoomID kCaldoria35 = 40;
+static const RoomID kCaldoria36 = 41;
+static const RoomID kCaldoria37 = 42;
+static const RoomID kCaldoria38 = 43;
+static const RoomID kCaldoria39 = 44;
+static const RoomID kCaldoria40 = 45;
+static const RoomID kCaldoria41 = 46;
+static const RoomID kCaldoriaBinoculars = 47;
+static const RoomID kCaldoria42 = 48;
+static const RoomID kCaldoriaKiosk = 49;
+static const RoomID kCaldoria44 = 50;
+static const RoomID kCaldoria45 = 51;
+static const RoomID kCaldoria46 = 52;
+static const RoomID kCaldoria47 = 53;
+static const RoomID kCaldoria48 = 54;
+static const RoomID kCaldoria49 = 55;
+static const RoomID kCaldoria50 = 56;
+static const RoomID kCaldoria51 = 57;
+static const RoomID kCaldoria52 = 58;
+static const RoomID kCaldoria53 = 59;
+static const RoomID kCaldoria54 = 60;
+static const RoomID kCaldoria55 = 61;
+static const RoomID kCaldoria56 = 62;
+static const RoomID kCaldoriaDeathRoom = 0;
+
+// Hot Spot Activation IDs.
+
+static const HotSpotActivationID kActivate4DClosed = 1;
+static const HotSpotActivationID kActivate4DOpen = 2;
+static const HotSpotActivationID kActivateMirrorReady = 3;
+static const HotSpotActivationID kActivateStylistReady = 4;
+static const HotSpotActivationID kActivateReplicatorReady = 5;
+static const HotSpotActivationID kActivateOJOnThePad = 6;
+static const HotSpotActivationID kActivateDrawersClosed = 7;
+static const HotSpotActivationID kActivateRightOpen = 8;
+static const HotSpotActivationID kActivateLeftOpen = 9;
+static const HotSpotActivationID kActivateFocusedOnShip = 10;
+static const HotSpotActivationID kActivateNotFocusedOnShip = 11;
+static const HotSpotActivationID kActivateReadyForCard = 12;
+static const HotSpotActivationID kActivateReadyToTransport = 13;
+static const HotSpotActivationID kActivateRoofSlotEmpty = 14;
+static const HotSpotActivationID kActivateZoomedOnSinclair = 15;
+
+// Hot Spot IDs.
+
+static const HotSpotID kCa4DEnvironOpenSpotID = 5000;
+static const HotSpotID kCa4DEnvironCloseSpotID = 5001;
+static const HotSpotID kCa4DVisualSpotID = 5002;
+static const HotSpotID kCa4DAudioSpotID = 5003;
+static const HotSpotID kCa4DChoice1SpotID = 5004;
+static const HotSpotID kCa4DChoice2SpotID = 5005;
+static const HotSpotID kCa4DChoice3SpotID = 5006;
+static const HotSpotID kCa4DChoice4SpotID = 5007;
+static const HotSpotID kCaBathroomMirrorSpotID = 5008;
+static const HotSpotID kCaHairStyle1SpotID = 5009;
+static const HotSpotID kCaHairStyle2SpotID = 5010;
+static const HotSpotID kCaHairStyle3SpotID = 5011;
+static const HotSpotID kCaShowerSpotID = 5012;
+static const HotSpotID kCaBathroomToiletSpotID = 5013;
+static const HotSpotID kCaldoriaVidPhoneSpotID = 5014;
+static const HotSpotID kCaldoriaReplicatorSpotID = 5015;
+static const HotSpotID kCaldoriaDrawersSpotID = 5016;
+static const HotSpotID kCaldoriaVidPhoneOutSpotID = 5017;
+static const HotSpotID kCaBedroomVidPhoneActivationSpotID = 5018;
+static const HotSpotID kCaldoriaReplicatorOutSpotID = 5019;
+static const HotSpotID kCaldoriaMakeOJSpotID = 5020;
+static const HotSpotID kCaldoriaMakeStickyBunsSpotID = 5021;
+static const HotSpotID kCaldoriaOrangeJuiceSpotID = 5022;
+static const HotSpotID kCaldoriaOrangeJuiceDropSpotID = 5023;
+static const HotSpotID kCaldoriaDrawersOutSpotID = 5024;
+static const HotSpotID kCaldoriaLeftDrawerOpenSpotID = 5025;
+static const HotSpotID kCaldoriaRightDrawerOpenSpotID = 5026;
+static const HotSpotID kCaldoriaKeyCardSpotID = 5027;
+static const HotSpotID kCaldoriaLeftDrawerCloseSpotID = 5028;
+static const HotSpotID kCaldoriaRightDrawerWithKeysCloseSpotID = 5029;
+static const HotSpotID kCaldoriaRightDrawerNoKeysCloseSpotID = 5030;
+static const HotSpotID kCaldoriaFourthFloorElevatorSpotID = 5031;
+static const HotSpotID kCaldoria20DoorbellSpotID = 5032;
+static const HotSpotID kCaldoria21DoorbellSpotID = 5033;
+static const HotSpotID kCaldoria26DoorbellSpotID = 5034;
+static const HotSpotID kCaldoriaFourthFloorElevator1 = 5035;
+static const HotSpotID kCaldoriaFourthFloorElevator2 = 5036;
+static const HotSpotID kCaldoriaFourthFloorElevator3 = 5037;
+static const HotSpotID kCaldoriaFourthFloorElevator4 = 5038;
+static const HotSpotID kCaldoriaFourthFloorElevator5 = 5039;
+static const HotSpotID kCaldoriaGroundElevator1 = 5040;
+static const HotSpotID kCaldoriaGroundElevator2 = 5041;
+static const HotSpotID kCaldoriaGroundElevator3 = 5042;
+static const HotSpotID kCaldoriaGroundElevator4 = 5043;
+static const HotSpotID kCaldoriaGroundElevator5 = 5044;
+static const HotSpotID kCaldoria29DoorbellSpotID = 5045;
+static const HotSpotID kCaldoria34DoorbellSpotID = 5046;
+static const HotSpotID kCaldoria35DoorbellSpotID = 5047;
+static const HotSpotID kCaldoriaGroundElevatorSpotID = 5048;
+static const HotSpotID kCaldoriaBinocularZoomInSpotID = 5049;
+static const HotSpotID kCaldoriaBinocularsOutSpotID = 5050;
+static const HotSpotID kCaldoriaZoomInOnShipSpotID = 5051;
+static const HotSpotID kCaldoriaKioskSpotID = 5052;
+static const HotSpotID kCaldoriaKioskOutSpotID = 5053;
+static const HotSpotID kCaldoriaKioskInfoSpotID = 5054;
+static const HotSpotID kCaldoriaGTCardDropSpotID = 5055;
+static const HotSpotID kCaldoriaGTTokyoSpotID = 5056;
+static const HotSpotID kCaldoriaGTTSASpotID = 5057;
+static const HotSpotID kCaldoriaGTBeachSpotID = 5058;
+static const HotSpotID kCaldoriaGTOtherSpotID = 5059;
+static const HotSpotID kCaldoriaRoofElevator1 = 5060;
+static const HotSpotID kCaldoriaRoofElevator2 = 5061;
+static const HotSpotID kCaldoriaRoofElevator3 = 5062;
+static const HotSpotID kCaldoriaRoofElevator4 = 5063;
+static const HotSpotID kCaldoriaRoofElevator5 = 5064;
+static const HotSpotID kCaldoriaRoofElevatorSpotID = 5065;
+static const HotSpotID kCaldoriaRoofDoorSpotID = 5066;
+static const HotSpotID kCaldoriaRoofCardDropSpotID = 5067;
+static const HotSpotID kCaldoria53EastSinclairTargetSpotID = 5068;
+
+// Extra sequence IDs.
+
+static const ExtraID kCaldoriaWakeUpView1 = 0;
+static const ExtraID kCaldoria00WakeUp1 = 1;
+static const ExtraID kCaldoria00WakeUp2 = 2;
+static const ExtraID kCaldoria00SitDown = 3;
+static const ExtraID k4DEnvironOpenToINN = 4;
+static const ExtraID k4DINNInterruption = 5;
+static const ExtraID k4DINNIntro = 6;
+static const ExtraID k4DINNMarkJohnson = 7;
+static const ExtraID k4DINNMeganLove = 8;
+static const ExtraID k4DINNFadeOut = 9;
+static const ExtraID k4DEnvironOpenFromINN = 10;
+static const ExtraID k4DEnvironOpen = 11;
+static const ExtraID k4DEnvironOpenView = 12;
+static const ExtraID k4DEnvironClose = 13;
+static const ExtraID k4DIslandLoop = 14;
+static const ExtraID k4DDesertLoop = 15;
+static const ExtraID k4DMountainLoop = 16;
+static const ExtraID k4DIsland1ToIsland0 = 17;
+static const ExtraID k4DIsland2ToIsland0 = 18;
+static const ExtraID k4DIsland0ToDesert0 = 19;
+static const ExtraID k4DIsland1ToDesert0 = 20;
+static const ExtraID k4DIsland2ToDesert0 = 21;
+static const ExtraID k4DIsland0ToMountain0 = 22;
+static const ExtraID k4DIsland1ToMountain0 = 23;
+static const ExtraID k4DIsland2ToMountain0 = 24;
+static const ExtraID k4DDesert0ToIsland0 = 25;
+static const ExtraID k4DDesert1ToIsland0 = 26;
+static const ExtraID k4DDesert2ToIsland0 = 27;
+static const ExtraID k4DDesert0ToMountain0 = 28;
+static const ExtraID k4DDesert1ToMountain0 = 29;
+static const ExtraID k4DDesert2ToMountain0 = 30;
+static const ExtraID k4DMountain0ToIsland0 = 31;
+static const ExtraID k4DMountain1ToIsland0 = 32;
+static const ExtraID k4DMountain2ToIsland0 = 33;
+static const ExtraID k4DMountain0ToDesert0 = 34;
+static const ExtraID k4DMountain1ToDesert0 = 35;
+static const ExtraID k4DMountain2ToDesert0 = 36;
+static const ExtraID kCaBathroomGreeting = 37;
+static const ExtraID kCaBathroomBodyFat = 38;
+static const ExtraID kCaBathroomStylistIntro = 39;
+static const ExtraID kCaBathroomRetrothrash = 40;
+static const ExtraID kCaBathroomRetrothrashReturn = 41;
+static const ExtraID kCaBathroomGeoWave = 42;
+static const ExtraID kCaBathroomGeoWaveReturn = 43;
+static const ExtraID kCaBathroomAgencyStandard = 44;
+static const ExtraID kCaldoriaShowerTitle = 45;
+static const ExtraID kCaldoriaShowerButton = 46;
+static const ExtraID kCaldoriaShowerDown = 47;
+static const ExtraID kCaldoriaShowerUp = 48;
+static const ExtraID kCaBedroomVidPhone = 49;
+static const ExtraID kCaBedroomMessage1 = 50;
+static const ExtraID kCaBedroomMessage2 = 51;
+static const ExtraID kCreateOrangeJuice = 52;
+static const ExtraID kDisposeOrangeJuice = 53;
+static const ExtraID kReplicatorNorthViewWithOJ = 54;
+static const ExtraID kLeftDrawerOpen = 55;
+static const ExtraID kLeftDrawerClose = 56;
+static const ExtraID kRightDrawerOpenWithKeys = 57;
+static const ExtraID kRightDrawerCloseWithKeys = 58;
+static const ExtraID kRightDrawerOpenNoKeys = 59;
+static const ExtraID kRightDrawerCloseNoKeys = 60;
+static const ExtraID kRightDrawerOpenViewWithKeys = 61;
+static const ExtraID kRightDrawerOpenViewNoKeys = 62;
+static const ExtraID kCaldoria16ElevatorUp = 63;
+static const ExtraID kCaldoria16ElevatorDown = 64;
+static const ExtraID kCaldoria16SouthViewWithElevator = 65;
+static const ExtraID kCaldoria20Doorbell = 66;
+static const ExtraID kCaldoria21Doorbell = 67;
+static const ExtraID kCaldoria26Doorbell = 68;
+static const ExtraID kCaldoriaFourthToGround = 69;
+static const ExtraID kCaldoriaRoofToFourth = 70;
+static const ExtraID kCaldoriaRoofToGround = 71;
+static const ExtraID kCaldoriaGroundToFourth = 72;
+static const ExtraID kCaldoriaGroundToRoof = 73;
+static const ExtraID kCaldoriaFourthToRoof = 74;
+static const ExtraID kCaldoria29Doorbell = 75;
+static const ExtraID kCaldoria34Doorbell = 76;
+static const ExtraID kCaldoria35Doorbell = 77;
+static const ExtraID kBinocularsZoomInOnShip = 78;
+static const ExtraID kCaldoriaKioskVideo = 79;
+static const ExtraID kCaldoriaTransporterArrowLoop = 80;
+static const ExtraID kArriveAtCaldoriaFromTSA = 81;
+static const ExtraID kCaGTOtherChoice = 82;
+static const ExtraID kCaGTCardSwipe = 83;
+static const ExtraID kCaGTSelectTSA = 84;
+static const ExtraID kCaGTFryTheFly = 85;
+static const ExtraID kCaGTGoToTSA = 86;
+static const ExtraID kCaGTSelectBeach = 87;
+static const ExtraID kCaGTGoToBeach = 88;
+static const ExtraID kCaGTArriveAtBeach = 89;
+static const ExtraID kCaGTSelectTokyo = 90;
+static const ExtraID kCaGTGoToTokyo = 91;
+static const ExtraID kCaGTArriveAtTokyo = 92;
+static const ExtraID kCa48NorthRooftopClosed = 93;
+static const ExtraID kCa48NorthExplosion = 94;
+static const ExtraID kCa48NorthExplosionDeath = 95;
+static const ExtraID kCa49NorthVoiceAnalysis = 96;
+static const ExtraID kCa50SinclairShoots = 97;
+static const ExtraID kCa53EastZoomToSinclair = 98;
+static const ExtraID kCa53EastDeath2 = 99;
+static const ExtraID kCa53EastShootSinclair = 100;
+static const ExtraID kCa53EastZoomOutFromSinclair = 101;
+static const ExtraID kCa54SouthDeath = 102;
+static const ExtraID kCaldoria56BombStage1 = 103;
+static const ExtraID kCaldoria56BombStage2 = 104;
+static const ExtraID kCaldoria56BombStage3 = 105;
+static const ExtraID kCaldoria56BombStage4 = 106;
+static const ExtraID kCaldoria56BombStage5 = 107;
+static const ExtraID kCaldoria56BombStage6 = 108;
+static const ExtraID kCaldoria56BombStage7 = 109;
+static const ExtraID kCaldoria56BombExplodes = 110;
+
+// Caldoria interactions.
+
+static const InteractionID kCaldoria4DInteractionID = 0;
+static const InteractionID kCaldoriaBombInteractionID = 1;
+static const InteractionID kCaldoriaMessagesInteractionID = 2;
+static const InteractionID kCaldoriaMirrorInteractionID = 3;
+
+// Caldoria:
+
+static const DisplayOrder kVidPhoneOrder = kMonitorLayer;
+static const DisplayOrder k4DSpritesOrder = kMonitorLayer;
+static const DisplayOrder kCaldoriaMessagesOrder = kMonitorLayer;
+static const DisplayOrder kCaldoriaElevatorOrder = kMonitorLayer;
+static const DisplayOrder kCaldoriaA05LightLoopOrder = kMonitorLayer;
+static const DisplayOrder kCaldoriaA07LightLoopOrder = kMonitorLayer;
+static const DisplayOrder kCaldoriaBombGridOrder = kMonitorLayer;
+static const DisplayOrder kCaldoriaBombTimerOrder = kCaldoriaBombGridOrder + 1;
+
+/////////////////////////////////////////////
+//
+// Caldoria
+
+static const CoordType kCaldoriaVidPhoneLeft = kNavAreaLeft + 105;
+static const CoordType kCaldoriaVidPhoneTop = kNavAreaTop + 28;
+
+static const CoordType kCaldoria4DSpritesLeft = kNavAreaLeft + 10;
+static const CoordType kCaldoria4DSpritesTop = kNavAreaTop + 142;
+
+static const CoordType kCaldoriaMessageLeft = kNavAreaLeft + 202;
+static const CoordType kCaldoriaMessageTop = kNavAreaTop + 26;
+
+static const CoordType kCaldoriaElevatorLeft = kNavAreaLeft + 407;
+static const CoordType kCaldoriaElevatorTop = kNavAreaTop + 138;
+
+static const CoordType kCaldoriaA05LightLoopLeft = kNavAreaLeft + 213;
+static const CoordType kCaldoriaA05LightLoopTop = kNavAreaTop + 215;
+
+static const CoordType kCaldoriaA07LightLoopLeft = kNavAreaLeft + 414;
+static const CoordType kCaldoriaA07LightLoopTop = kNavAreaTop + 215;
+
+static const CoordType kCaldoriaGunSpriteLeft = kNavAreaLeft + 276;
+static const CoordType kCaldoriaGunSpriteTop = kNavAreaTop + 115;
+
+static const CoordType kCaldoria11MessageLoopLeft = kNavAreaLeft + 135;
+static const CoordType kCaldoria11MessageLoopTop = kNavAreaTop + 214;
+
+static const CoordType kCaldoria12MessageLoopLeft = kNavAreaLeft + 209;
+static const CoordType kCaldoria12MessageLoopTop = kNavAreaTop + 170;
+
+static const CoordType kCaldoria13MessageLoopLeft = kNavAreaLeft + 480;
+static const CoordType kCaldoria13MessageLoopTop = kNavAreaTop + 191;
+
+static const CoordType kCaldoria14MessageLoopLeft = kNavAreaLeft + 248;
+static const CoordType kCaldoria14MessageLoopTop = kNavAreaTop + 191;
+
+static const CoordType kCaldoria48CardBombLoopLeft = kNavAreaLeft + 337;
+static const CoordType kCaldoria48CardBombLoopTop = kNavAreaTop + 205;
+
+static const CoordType kCaldoriaBombGridLeft = kNavAreaLeft + 290;
+static const CoordType kCaldoriaBombGridTop = kNavAreaTop + 58;
+
+static const CoordType kCaldoriaBombTimerLeft = kNavAreaLeft + 58;
+static const CoordType kCaldoriaBombTimerTop = kNavAreaTop + 204;
+
+// Caldoria display IDs.
+
+static const DisplayElementID kCaldoriaVidPhoneID = kNeighborhoodDisplayID;
+static const DisplayElementID kCaldoria4DSpritesID = kCaldoriaVidPhoneID + 1;
+static const DisplayElementID kCaldoriaMessagesID = kCaldoria4DSpritesID + 1;
+static const DisplayElementID kCaldoriaUtilityID = kCaldoriaMessagesID + 1;
+static const DisplayElementID kCaldoriaBombGridID = kCaldoriaUtilityID + 1;
+static const DisplayElementID kCaldoriaBombTimerID = kCaldoriaBombGridID + 1;
+
+static const TimeValue kCaldoria4DBlankChoiceIn = 29730;
+static const TimeValue kCaldoria4DBlankChoiceOut = 33910;
+
+class Caldoria;
+
+class SinclairCallBack : public TimeBaseCallBack {
+public:
+ SinclairCallBack(Caldoria *);
+ ~SinclairCallBack() {}
+
+protected:
+ virtual void callBack();
+
+ Caldoria *_caldoria;
+};
+
+class Caldoria : public Neighborhood {
+friend class SinclairCallBack;
+
+public:
+ Caldoria(InputHandler *, PegasusEngine *);
+ virtual ~Caldoria();
+
+ virtual uint16 getDateResID() const;
+
+ void pickedUpItem(Item *);
+
+ virtual GameInteraction *makeInteraction(const InteractionID);
+
+ virtual Common::String getBriefingMovie();
+ virtual Common::String getEnvScanMovie();
+ virtual uint getNumHints();
+ virtual Common::String getHintMovie(uint);
+ void loadAmbientLoops();
+ bool wantsCursor();
+ void flushGameState();
+
+ void checkContinuePoint(const RoomID, const DirectionConstant);
+
+protected:
+ enum {
+ kCaldoriaPrivate4DSystemOpenFlag,
+ kCaloriaPrivateLeftDrawerOpenFlag,
+ kCaldoriaPrivateRightDrawerOpenFlag,
+ kCaldoriaPrivateReadyToShootFlag,
+ kCaldoriaPrivateZoomingToBombFlag,
+ kCaldoriaPrivateCanOpenElevatorDoorFlag,
+ kCaldoriaPrivateSinclairTimerExpiredFlag,
+ kCaldoriaPrivateSeen13CarFlag,
+ kCaldoriaPrivateSeen14CarFlag,
+ kCaldoriaPrivateSeen18CarFlag,
+ kCaldoriaPrivateSeen23CarFlag,
+ kCaldoriaPrivateSeen33CarFlag,
+ kCaldoriaPrivateSeen36CarFlag,
+ kCaldoriaPrivateSeen41NorthCarFlag,
+ kCaldoriaPrivateSeen41EastCarFlag,
+ kCaldoriaPrivateSeen41WestCarFlag,
+ kNumCaldoriaPrivateFlags
+ };
+
+ void init();
+ void start();
+
+ void setUpRoofTop();
+
+ void setUpAIRules();
+ void doAIRecalibration();
+ TimeValue getViewTime(const RoomID, const DirectionConstant);
+ void findSpotEntry(const RoomID, const DirectionConstant, SpotFlags, SpotTable::Entry &);
+ void startSpotOnceOnly(TimeValue, TimeValue);
+ void startExitMovie(const ExitTable::Entry &);
+ void startZoomMovie(const ZoomTable::Entry &);
+ void startDoorOpenMovie(const TimeValue, const TimeValue);
+ void startTurnPush(const TurnDirection, const TimeValue, const DirectionConstant);
+ void bumpIntoWall();
+ int16 getStaticCompassAngle(const RoomID, const DirectionConstant);
+ void getExitCompassMove(const ExitTable::Entry &, FaderMoveSpec &);
+ void getZoomCompassMove(const ZoomTable::Entry &, FaderMoveSpec &);
+ void getExtraCompassMove(const ExtraTable::Entry &, FaderMoveSpec &);
+ void spotCompleted();
+ void arriveAt(const RoomID, const DirectionConstant);
+ void arriveAtCaldoria00();
+ void arriveAtCaldoriaToilet();
+ void arriveAtCaldoria44();
+ void arriveAtCaldoria49();
+ void arriveAtCaldoria56();
+ void arriveAtCaldoriaDeath();
+ void turnTo(const DirectionConstant);
+ void zoomTo(const Hotspot *);
+ void downButton(const Input &);
+ void receiveNotification(Notification *, const NotificationFlags);
+ InputBits getInputFilter();
+ void activateHotspots();
+ void clickInHotspot(const Input &, const Hotspot *);
+ void newInteraction(const InteractionID);
+
+ void clickOnDoorbell(const HotSpotID);
+
+ Hotspot *getItemScreenSpot(Item *, DisplayElement *);
+ void dropItemIntoRoom(Item *, Hotspot *);
+ void takeElevator(uint, uint);
+ void updateElevatorMovie();
+ void openElevatorMovie();
+ void emptyOJGlass();
+ void closeDoorOffScreen(const RoomID, const DirectionConstant);
+ void doorBombTimerExpired();
+ void sinclairTimerExpired();
+ void checkSinclairShootsOS();
+ void setUpSinclairLoops();
+ void zoomToSinclair();
+ void playEndMessage();
+ void checkInterruptSinclair();
+
+ CanOpenDoorReason canOpenDoor(DoorTable::Entry &);
+ void doorOpened();
+
+ void updateCursor(const Common::Point, const Hotspot *);
+
+ FlagsArray<uint16, kNumCaldoriaPrivateFlags> _privateFlags;
+
+ const Hotspot *_zoomOutSpot;
+
+ FuseFunction _utilityFuse;
+
+ long _sinclairLoopCount;
+ long _numSinclairLoops;
+
+ Sprite *_gunSprite;
+
+ SinclairCallBack _sinclairInterrupt;
+
+ Common::String getSoundSpotsName();
+ Common::String getNavMovieName();
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/caldoria/caldoria4dsystem.cpp b/engines/pegasus/neighborhood/caldoria/caldoria4dsystem.cpp
new file mode 100644
index 0000000000..0494753661
--- /dev/null
+++ b/engines/pegasus/neighborhood/caldoria/caldoria4dsystem.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/pegasus.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/neighborhood/caldoria/caldoria.h"
+#include "pegasus/neighborhood/caldoria/caldoria4dsystem.h"
+
+namespace Pegasus {
+
+static const TimeValue kSwitchableSlop = 3 * kCaldoriaFrameDuration;
+// Two seconds - some slop
+static const TimeValue kSwitchableDuration = kCaldoriaMovieScale * 2 - kSwitchableSlop;
+// Twelve frames + some slop
+static const TimeValue kNonswitchableDuration = kCaldoriaFrameDuration * 12 + kSwitchableSlop;
+
+static const TimeValue kSwitchable1Start = 0;
+static const TimeValue kSwitchable1Stop = kSwitchable1Start + kSwitchableDuration;
+
+static const TimeValue kSwitchable2Start = kSwitchable1Stop + kNonswitchableDuration;
+static const TimeValue kSwitchable2Stop = kSwitchable2Start + kSwitchableDuration;
+
+static const TimeValue kSwitchable3Start = kSwitchable2Stop + kNonswitchableDuration;
+static const TimeValue kSwitchable3Stop = kSwitchable3Start + kSwitchableDuration;
+
+static const NotificationFlags kVidPhoneDoneFlag = 1;
+
+static const TimeValue kRockMusicLoopIn = 0;
+static const TimeValue kRockMusicLoopOut = 2088;
+
+static const TimeValue kOrchestralMusicLoopIn = 2088;
+static const TimeValue kOrchestralMusicLoopOut = 4985;
+
+static const TimeValue kRhythmsMusicLoopIn = 4985;
+static const TimeValue kRhythmsMusicLoopOut = 6824;
+
+static const TimeValue kAcousticMusicLoopIn = 6824;
+static const TimeValue kAcousticMusicLoopOut = 9387;
+
+enum {
+ k4DVideoMenu,
+ k4DAudioMenu,
+ k4DShuttingDown,
+
+ // These constants are the exact frame numbers of the sprite movie.
+ k4DRockChoice = 0,
+ k4DOrchestralChoice,
+ k4DRhythmsChoice,
+ k4DAcousticChoice,
+ k4DIslandChoice,
+ k4DDesertChoice,
+ k4DMountainChoice,
+
+ k4DFirstVideoChoice = k4DIslandChoice
+};
+
+static const ExtraID s_transitionExtras0[3][3] = {
+ { 0xffffffff, k4DIsland0ToDesert0, k4DIsland0ToMountain0 },
+ { k4DDesert0ToIsland0, 0xffffffff, k4DDesert0ToMountain0 },
+ { k4DMountain0ToIsland0, k4DMountain0ToDesert0, 0xffffffff }
+};
+
+static const ExtraID s_transitionExtras1[3][3] = {
+ { 0xffffffff, k4DIsland1ToDesert0, k4DIsland1ToMountain0 },
+ { k4DDesert1ToIsland0, 0xffffffff, k4DDesert1ToMountain0 },
+ { k4DMountain1ToIsland0, k4DMountain1ToDesert0, 0xffffffff }
+};
+
+static const ExtraID s_transitionExtras2[3][3] = {
+ { 0xffffffff, k4DIsland2ToDesert0, k4DIsland2ToMountain0 },
+ { k4DDesert2ToIsland0, 0xffffffff, k4DDesert2ToMountain0 },
+ { k4DMountain2ToIsland0, k4DMountain2ToDesert0, 0xffffffff }
+};
+
+static const ExtraID s_shutDownExtras[3][3] = {
+ { 0xffffffff, k4DIsland1ToIsland0, k4DIsland2ToIsland0 },
+ { k4DDesert0ToIsland0, k4DDesert1ToIsland0, k4DDesert2ToIsland0 },
+ { k4DMountain0ToIsland0, k4DMountain1ToIsland0, k4DMountain2ToIsland0 }
+};
+
+Caldoria4DSystem::Caldoria4DSystem(Neighborhood *owner) : GameInteraction(kCaldoria4DInteractionID, owner),
+ _4DSpritesMovie(kCaldoria4DSpritesID) {
+ g_AIArea->lockAIOut();
+}
+
+Caldoria4DSystem::~Caldoria4DSystem() {
+ g_AIArea->unlockAI();
+}
+
+void Caldoria4DSystem::openInteraction() {
+ _whichMenu = k4DVideoMenu;
+ _videoChoice = k4DIslandChoice;
+ _audioChoice = k4DRockChoice;
+ _clickedHotspotID = kNoHotSpotID;
+
+ _4DSpritesMovie.initFromMovieFile("Images/Caldoria/4D Sprites", true);
+ _4DSpritesMovie.moveElementTo(kCaldoria4DSpritesLeft, kCaldoria4DSpritesTop);
+ _4DSpritesMovie.setDisplayOrder(k4DSpritesOrder);
+ _4DSpritesMovie.startDisplaying();
+ _4DSpritesMovie.show();
+
+ _4DSpritesScale = _4DSpritesMovie.getScale();
+
+ _neighborhoodNotification = _owner->getNeighborhoodNotification();
+ _neighborhoodNotification->notifyMe(this, kExtraCompletedFlag, kExtraCompletedFlag);
+
+ startIdling();
+}
+
+void Caldoria4DSystem::loopExtra(const ExtraID extraID) {
+ ExtraTable::Entry extraEntry;
+
+ _owner->getExtraEntry(extraID, extraEntry);
+ _loopStart = extraEntry.movieStart;
+ _owner->loopExtraSequence(extraID);
+}
+
+void Caldoria4DSystem::useIdleTime() {
+ if (_whichMenu == k4DShuttingDown) {
+ TimeValue movieTime = _owner->getNavMovie()->getTime() - _loopStart;
+ ExtraID extraID;
+
+ if (movieTime < kSwitchable1Stop)
+ extraID = s_shutDownExtras[_videoChoice - k4DFirstVideoChoice][0];
+ else if (movieTime >= kSwitchable2Start && movieTime < kSwitchable2Stop)
+ extraID = s_shutDownExtras[_videoChoice - k4DFirstVideoChoice][1];
+ else if (movieTime >= kSwitchable3Start && movieTime < kSwitchable3Stop)
+ extraID = s_shutDownExtras[_videoChoice - k4DFirstVideoChoice][2];
+ else
+ extraID = 0xffffffff;
+
+ if (extraID != 0xffffffff) {
+ setSpritesMovie();
+ _loopStart = 0;
+ _owner->startExtraSequence(extraID, kExtraCompletedFlag, kFilterNoInput);
+ }
+ } else if (_clickedHotspotID != kNoHotSpotID) {
+ TimeValue movieTime = _owner->getNavMovie()->getTime() - _loopStart;
+ ExtraID extraID;
+
+ if (movieTime < kSwitchable1Stop) {
+ extraID = s_transitionExtras0[_videoChoice - k4DFirstVideoChoice][_clickedHotspotID - kCa4DChoice1SpotID];
+ _clickedHotspotID = kNoHotSpotID;
+ } else if (movieTime >= kSwitchable2Start && movieTime < kSwitchable2Stop) {
+ extraID = s_transitionExtras1[_videoChoice - k4DFirstVideoChoice][_clickedHotspotID - kCa4DChoice1SpotID];
+ _clickedHotspotID = kNoHotSpotID;
+ } else if (movieTime >= kSwitchable3Start && movieTime < kSwitchable3Stop) {
+ extraID = s_transitionExtras2[_videoChoice - k4DFirstVideoChoice][_clickedHotspotID - kCa4DChoice1SpotID];
+ _clickedHotspotID = kNoHotSpotID;
+ } else
+ extraID = 0xffffffff;
+
+ if (extraID != 0xffffffff) {
+ switch (extraID) {
+ case k4DDesert0ToIsland0:
+ case k4DMountain0ToIsland0:
+ case k4DDesert1ToIsland0:
+ case k4DMountain1ToIsland0:
+ case k4DDesert2ToIsland0:
+ case k4DMountain2ToIsland0:
+ _videoChoice = k4DIslandChoice;
+ break;
+ case k4DIsland0ToDesert0:
+ case k4DMountain0ToDesert0:
+ case k4DIsland1ToDesert0:
+ case k4DMountain1ToDesert0:
+ case k4DIsland2ToDesert0:
+ case k4DMountain2ToDesert0:
+ _videoChoice = k4DDesertChoice;
+ break;
+ case k4DDesert0ToMountain0:
+ case k4DIsland0ToMountain0:
+ case k4DIsland1ToMountain0:
+ case k4DDesert1ToMountain0:
+ case k4DIsland2ToMountain0:
+ case k4DDesert2ToMountain0:
+ _videoChoice = k4DMountainChoice;
+ break;
+ }
+
+ setSpritesMovie();
+ _loopStart = 0;
+ _owner->startExtraSequence(extraID, kExtraCompletedFlag, kFilterNoInput);
+ }
+ }
+}
+
+void Caldoria4DSystem::initInteraction() {
+ setSpritesMovie();
+
+ _owner->loadLoopSound1("Sounds/Caldoria/Rock.aiff");
+ loopExtra(k4DIslandLoop);
+}
+
+void Caldoria4DSystem::closeInteraction() {
+ stopIdling();
+ _neighborhoodNotification->cancelNotification(this);
+ _4DSpritesMovie.releaseMovie();
+ _owner->loadAmbientLoops();
+}
+
+void Caldoria4DSystem::setSpritesMovie() {
+ if (_whichMenu == k4DShuttingDown)
+ _4DSpritesMovie.setTime(_4DSpritesScale * k4DIslandChoice);
+ else if (_whichMenu == k4DVideoMenu)
+ _4DSpritesMovie.setTime(_4DSpritesScale * _videoChoice);
+ else if (_whichMenu == k4DAudioMenu)
+ _4DSpritesMovie.setTime(_4DSpritesScale * _audioChoice);
+
+ _4DSpritesMovie.redrawMovieWorld();
+}
+
+void Caldoria4DSystem::handleInput(const Input &input, const Hotspot *cursorSpot) {
+ if (input.downButtonAnyDown())
+ return;
+ if (input.anyDirectionInput())
+ shutDown4DSystem();
+ else
+ GameInteraction::handleInput(input, cursorSpot);
+}
+
+void Caldoria4DSystem::activateHotspots() {
+ GameInteraction::activateHotspots();
+ if (_whichMenu == k4DAudioMenu)
+ g_allHotspots.activateOneHotspot(kCa4DChoice4SpotID);
+}
+
+void Caldoria4DSystem::clickInHotspot(const Input &input, const Hotspot *spot) {
+ switch (spot->getObjectID()) {
+ case kCa4DVisualSpotID:
+ if (_whichMenu == k4DAudioMenu) {
+ _whichMenu = k4DVideoMenu;
+ setSpritesMovie();
+ }
+ break;
+ case kCa4DAudioSpotID:
+ if (_whichMenu == k4DVideoMenu) {
+ _whichMenu = k4DAudioMenu;
+ setSpritesMovie();
+ }
+ break;
+ case kCa4DChoice1SpotID:
+ if (_whichMenu == k4DVideoMenu)
+ makeIslandChoice();
+ else if (_whichMenu == k4DAudioMenu)
+ makeRockChoice();
+ break;
+ case kCa4DChoice2SpotID:
+ if (_whichMenu == k4DVideoMenu)
+ makeDesertChoice();
+ else if (_whichMenu == k4DAudioMenu)
+ makeOrchestralChoice();
+ break;
+ case kCa4DChoice3SpotID:
+ if (_whichMenu == k4DVideoMenu)
+ makeMountainChoice();
+ else if (_whichMenu == k4DAudioMenu)
+ makeRhythmsChoice();
+ break;
+ case kCa4DChoice4SpotID:
+ if (_whichMenu == k4DAudioMenu)
+ makeAcousticChoice();
+ else
+ _owner->playSpotSoundSync(kCaldoria4DBlankChoiceIn, kCaldoria4DBlankChoiceOut);
+ break;
+ default:
+ GameInteraction::clickInHotspot(input, spot);
+ }
+}
+
+void Caldoria4DSystem::receiveNotification(Notification *, const NotificationFlags) {
+ if (_whichMenu == k4DShuttingDown) {
+ _owner->requestDeleteCurrentInteraction();
+ } else {
+ uint32 extraID;
+
+ switch (_videoChoice) {
+ case k4DIslandChoice:
+ extraID = k4DIslandLoop;
+ break;
+ case k4DDesertChoice:
+ extraID = k4DDesertLoop;
+ break;
+ case k4DMountainChoice:
+ extraID = k4DMountainLoop;
+ break;
+ default:
+ extraID = 0xffffffff;
+ break;
+ }
+
+ if (extraID != 0xffffffff)
+ loopExtra(extraID);
+ }
+}
+
+void Caldoria4DSystem::makeIslandChoice() {
+ if (_videoChoice != k4DIslandChoice && _clickedHotspotID == kNoHotSpotID)
+ _clickedHotspotID = kCa4DChoice1SpotID;
+}
+
+void Caldoria4DSystem::makeDesertChoice() {
+ if (_videoChoice != k4DDesertChoice && _clickedHotspotID == kNoHotSpotID)
+ _clickedHotspotID = kCa4DChoice2SpotID;
+}
+
+void Caldoria4DSystem::makeMountainChoice() {
+ if (_videoChoice != k4DMountainChoice && _clickedHotspotID == kNoHotSpotID)
+ _clickedHotspotID = kCa4DChoice3SpotID;
+}
+
+void Caldoria4DSystem::makeRockChoice() {
+ if (_audioChoice != k4DRockChoice) {
+ _audioChoice = k4DRockChoice;
+ setSpritesMovie();
+ _owner->loadLoopSound1("Sounds/Caldoria/Rock.aiff");
+ }
+}
+
+void Caldoria4DSystem::makeOrchestralChoice() {
+ if (_audioChoice != k4DOrchestralChoice) {
+ _audioChoice = k4DOrchestralChoice;
+ setSpritesMovie();
+ _owner->loadLoopSound1("Sounds/Caldoria/Orchestral.aiff");
+ }
+}
+
+void Caldoria4DSystem::makeRhythmsChoice() {
+ if (_audioChoice != k4DRhythmsChoice) {
+ _audioChoice = k4DRhythmsChoice;
+ setSpritesMovie();
+ _owner->loadLoopSound1("Sounds/Caldoria/Rhythms.aiff");
+ }
+}
+
+void Caldoria4DSystem::makeAcousticChoice() {
+ if (_audioChoice != k4DAcousticChoice) {
+ _audioChoice = k4DAcousticChoice;
+ setSpritesMovie();
+ _owner->loadLoopSound1("Sounds/Caldoria/Acoustic.aiff");
+ }
+}
+
+void Caldoria4DSystem::shutDown4DSystem() {
+ _whichMenu = k4DShuttingDown;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/caldoria/caldoria4dsystem.h b/engines/pegasus/neighborhood/caldoria/caldoria4dsystem.h
new file mode 100644
index 0000000000..1c5fa44b90
--- /dev/null
+++ b/engines/pegasus/neighborhood/caldoria/caldoria4dsystem.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_CALDORIA_CALDORIA4DSYSTEM_H
+#define PEGASUS_NEIGHBORHOOD_CALDORIA_CALDORIA4DSYSTEM_H
+
+#include "pegasus/interaction.h"
+#include "pegasus/movie.h"
+#include "pegasus/notification.h"
+#include "pegasus/timers.h"
+
+namespace Pegasus {
+
+class Neighborhood;
+
+class Caldoria4DSystem : public GameInteraction, private Idler, public NotificationReceiver {
+public:
+ Caldoria4DSystem(Neighborhood *);
+ virtual ~Caldoria4DSystem();
+
+ void shutDown4DSystem();
+
+protected:
+ void openInteraction();
+ void initInteraction();
+ void closeInteraction();
+
+ void handleInput(const Input &, const Hotspot *);
+ void activateHotspots();
+ void clickInHotspot(const Input &, const Hotspot *);
+ void receiveNotification(Notification *, const NotificationFlags);
+ void setSpritesMovie();
+ void makeIslandChoice();
+ void makeRockChoice();
+ void makeMountainChoice();
+ void makeOrchestralChoice();
+ void makeDesertChoice();
+ void makeRhythmsChoice();
+ void makeAcousticChoice();
+
+ void useIdleTime();
+ void loopExtra(const ExtraID);
+
+ Movie _4DSpritesMovie;
+ TimeScale _4DSpritesScale;
+ uint _whichMenu;
+ uint _videoChoice;
+ uint _audioChoice;
+ Notification *_neighborhoodNotification;
+ TimeValue _loopStart;
+ HotSpotID _clickedHotspotID;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/caldoria/caldoriabomb.cpp b/engines/pegasus/neighborhood/caldoria/caldoriabomb.cpp
new file mode 100644
index 0000000000..abf34d3863
--- /dev/null
+++ b/engines/pegasus/neighborhood/caldoria/caldoriabomb.cpp
@@ -0,0 +1,1442 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/neighborhood/caldoria/caldoria.h"
+#include "pegasus/neighborhood/caldoria/caldoriabomb.h"
+
+namespace Pegasus {
+
+// Bomb game PICTs:
+
+static const uint16 kYellowBombPICTBaseID = 700;
+static const uint16 kRedBombPICTBaseID = 709;
+static const uint16 kTimerLeftPICTID = 718;
+static const uint16 kTimerRightPICTID = 719;
+
+static const uint32 kFlashOnTime = 20;
+static const uint32 kFlashOffTime = 10;
+
+static const uint32 kOnTime1 = kFlashOnTime;
+static const uint32 kOffTime1 = kOnTime1 + kFlashOffTime;
+static const uint32 kOnTime2 = kOffTime1 + kFlashOnTime;
+static const uint32 kOffTime2 = kOnTime2 + kFlashOffTime;
+static const uint32 kOnTime3 = kOffTime2 + kFlashOnTime;
+static const uint32 kOffTime3 = kOnTime3 + kFlashOffTime;
+static const uint32 kOnTime4 = kOffTime3 + kFlashOnTime;
+
+static const HotSpotID kVertextHotSpotBaseID = 10000;
+
+static const CoordType kVertextHotSpotWidth = 24;
+static const CoordType kVertextHotSpotHeight = 24;
+
+static const NotificationFlags kBombTimerExpiredFlag = 1;
+
+static const VertexType kBombLevelOne[] = {
+ 0, 1, 0, 1, 0, // hot vertices first.
+ 1, 1, 0, 1, 1,
+ 1, 1, 0, 1, 0,
+ 1, 1, 0, 1, 1,
+ 0, 1, 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, 0,
+
+ 9, // 9 edges in this level
+
+ kEdgeOneFourth,
+ 3,
+ 1, 2, 3,
+ 0, 0,
+
+ kEdgeOneFourth,
+ 5,
+ 5, 6, 7, 8, 9,
+ 0, 0, 0, 0,
+
+ kEdgeOneFourth,
+ 4,
+ 10, 11, 12, 13,
+ 0, 0, 0,
+
+ kEdgeOneFourth,
+ 5,
+ 15, 16, 17, 18, 19,
+ 0, 0, 0, 0,
+
+ kEdgeOneFourth,
+ 3,
+ 21, 22, 23,
+ 0, 0,
+
+ kEdgeOneHalf,
+ 3,
+ 5, 10, 15,
+ 0, 0,
+
+ kEdgeOneHalf,
+ 5,
+ 1, 6, 11, 16, 21,
+ 0, 0, 0, 0,
+
+ kEdgeOneHalf,
+ 5,
+ 3, 8, 13, 18, 23,
+ 0, 0, 0, 0,
+
+ kEdgeOneHalf,
+ 3,
+ 9, 14, 19,
+ 0, 0
+};
+
+static const VertexType kBombLevelTwo[] = {
+ 0, 1, 0, 1, 0,
+ 1, 1, 1, 0, 1,
+ 0, 0, 0, 1, 0,
+ 1, 1, 1, 0, 1,
+ 0, 1, 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, 0,
+
+ 15,
+
+ kEdgeOneEighth,
+ 2,
+ 5, 1,
+ 0,
+
+ kEdgeOneEighth,
+ 3,
+ 17, 13, 9,
+ 0, 0,
+
+ kEdgeOneEighth,
+ 2,
+ 23, 19,
+ 0,
+
+ kEdgeThreeEighths,
+ 2,
+ 3, 9,
+ 0,
+
+ kEdgeThreeEighths,
+ 3,
+ 7, 13, 19,
+ 0, 0,
+
+ kEdgeThreeEighths,
+ 2,
+ 15, 21,
+ 0,
+
+ kEdgeOneFourth,
+ 3,
+ 1, 2, 3,
+ 0, 0,
+
+ kEdgeOneFourth,
+ 4,
+ 6, 7, 8, 9,
+ 0, 0, 0,
+
+ kEdgeOneFourth,
+ 4,
+ 16, 17, 18, 19,
+ 0, 0, 0,
+
+ kEdgeOneFourth,
+ 3,
+ 21, 22, 23,
+ 0, 0,
+
+ kEdgeOneHalf,
+ 3,
+ 5, 10, 15,
+ 0, 0,
+
+ kEdgeOneHalf,
+ 2,
+ 1, 6,
+ 0,
+
+ kEdgeOneHalf,
+ 3,
+ 7, 12, 17,
+ 0, 0,
+
+ kEdgeOneHalf,
+ 3,
+ 9, 14, 19,
+ 0, 0,
+
+ kEdgeOneHalf,
+ 2,
+ 16, 21,
+ 0
+};
+
+static const VertexType kBombLevelThree[] = {
+ 0, 1, 0, 1, 0,
+ 1, 1, 1, 1, 1,
+ 0, 1, 1, 0, 0,
+ 1, 1, 1, 1, 1,
+ 0, 1, 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, 0,
+
+ 22,
+
+ kEdgeThreeSixteenths,
+ 3,
+ 15, 12, 9,
+ 0, 0,
+
+ kEdgeFiveSixteenths,
+ 3,
+ 5, 12, 19,
+ 0, 0,
+
+ kEdgeOneEighth,
+ 2,
+ 5, 1,
+ 0,
+
+ kEdgeOneEighth,
+ 2,
+ 7, 3,
+ 0,
+
+ kEdgeOneEighth,
+ 2,
+ 15, 11,
+ 0,
+
+ kEdgeOneEighth,
+ 2,
+ 21, 17,
+ 0,
+
+ kEdgeOneEighth,
+ 2,
+ 23, 19,
+ 0,
+
+ kEdgeThreeEighths,
+ 2,
+ 1, 7,
+ 0,
+
+ kEdgeThreeEighths,
+ 2,
+ 3, 9,
+ 0,
+
+ kEdgeThreeEighths,
+ 2,
+ 5, 11,
+ 0,
+
+ kEdgeThreeEighths,
+ 2,
+ 15, 21,
+ 0,
+
+ kEdgeThreeEighths,
+ 2,
+ 17, 23,
+ 0,
+
+ kEdgeOneFourth,
+ 3,
+ 1, 2, 3,
+ 0, 0,
+
+ kEdgeOneFourth,
+ 2,
+ 5, 6,
+ 0,
+
+ kEdgeOneFourth,
+ 2,
+ 8, 9,
+ 0,
+
+ kEdgeOneFourth,
+ 2,
+ 15, 16,
+ 0,
+
+ kEdgeOneFourth,
+ 2,
+ 18, 19,
+ 0,
+
+ kEdgeOneFourth,
+ 3,
+ 21, 22, 23,
+ 0, 0,
+
+ kEdgeOneHalf,
+ 2,
+ 1, 6,
+ 0,
+
+ kEdgeOneHalf,
+ 2,
+ 3, 8,
+ 0,
+
+ kEdgeOneHalf,
+ 2,
+ 16, 21,
+ 0,
+
+ kEdgeOneHalf,
+ 2,
+ 18, 23,
+ 0
+};
+
+static const VertexType kBombLevelFour[] = {
+ 1, 1, 1, 1, 0,
+ 1, 1, 0, 1, 1,
+ 1, 0, 1, 0, 1,
+ 1, 1, 0, 1, 1,
+ 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, 0,
+
+ 19,
+
+ kEdgeOneEighth,
+ 2,
+ 5, 1,
+ 0,
+
+ kEdgeOneEighth,
+ 3,
+ 10, 6, 2,
+ 0, 0,
+
+ kEdgeOneEighth,
+ 3,
+ 16, 12, 8,
+ 0, 0,
+
+ kEdgeOneEighth,
+ 3,
+ 22, 18, 14,
+ 0, 0,
+
+ kEdgeOneEighth,
+ 2,
+ 23, 19,
+ 0,
+
+ kEdgeThreeEighths,
+ 3,
+ 2, 8, 14,
+ 0, 0,
+
+ kEdgeThreeEighths,
+ 3,
+ 10, 16, 22,
+ 0, 0,
+
+ kEdgeOneFourth,
+ 4,
+ 0, 1, 2, 3,
+ 0, 0, 0,
+
+ kEdgeOneFourth,
+ 2,
+ 5, 6,
+ 0,
+
+ kEdgeOneFourth,
+ 2,
+ 8, 9,
+ 0,
+
+ kEdgeOneFourth,
+ 2,
+ 15, 16,
+ 0,
+
+ kEdgeOneFourth,
+ 2,
+ 18, 19,
+ 0,
+
+ kEdgeOneFourth,
+ 4,
+ 21, 22, 23, 24,
+ 0, 0, 0,
+
+ kEdgeOneHalf,
+ 4,
+ 0, 5, 10, 15,
+ 0, 0, 0,
+
+ kEdgeOneHalf,
+ 2,
+ 1, 6,
+ 0,
+
+ kEdgeOneHalf,
+ 2,
+ 3, 8,
+ 0,
+
+ kEdgeOneHalf,
+ 4,
+ 9, 14, 19, 24,
+ 0, 0, 0,
+
+ kEdgeOneHalf,
+ 2,
+ 16, 21,
+ 0,
+
+ kEdgeOneHalf,
+ 2,
+ 18, 23,
+ 0
+};
+
+static const VertexType kBombLevelFive[] = {
+ 0, 1, 0, 1, 0,
+ 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 0,
+ 1, 1, 1, 1, 1,
+ 0, 1, 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, 0,
+
+ 19,
+
+ kEdgeOneEighth,
+ 2,
+ 5, 1,
+ 0,
+
+ kEdgeOneEighth,
+ 2,
+ 7, 3,
+ 0,
+
+ kEdgeOneEighth,
+ 2,
+ 13, 9,
+ 0,
+
+ kEdgeOneEighth,
+ 2,
+ 15, 11,
+ 0,
+
+ kEdgeOneEighth,
+ 2,
+ 21, 17,
+ 0,
+
+ kEdgeOneEighth,
+ 2,
+ 23, 19,
+ 0,
+
+ kEdgeThreeEighths,
+ 2,
+ 1, 7,
+ 0,
+
+ kEdgeThreeEighths,
+ 4,
+ 5, 11, 17, 23,
+ 0, 0, 0,
+
+ kEdgeThreeEighths,
+ 3,
+ 6, 12, 18,
+ 0, 0,
+
+ kEdgeThreeEighths,
+ 2,
+ 13, 19,
+ 0,
+
+ kEdgeThreeEighths,
+ 2,
+ 15, 21,
+ 0,
+
+ kEdgeOneFourth,
+ 5,
+ 5, 6, 7, 8, 9,
+ 0, 0, 0, 0,
+
+ kEdgeOneFourth,
+ 3,
+ 15, 16, 17,
+ 0, 0,
+
+ kEdgeOneFourth,
+ 2,
+ 18, 19,
+ 0,
+
+ kEdgeOneFourth,
+ 3,
+ 21, 22, 23,
+ 0, 0,
+
+ kEdgeOneHalf,
+ 3,
+ 5, 10, 15,
+ 0, 0,
+
+ kEdgeOneHalf,
+ 2,
+ 1, 6,
+ 0,
+
+ kEdgeOneHalf,
+ 3,
+ 11, 16, 21,
+ 0, 0,
+
+ kEdgeOneHalf,
+ 5,
+ 3, 8, 13, 18, 23,
+ 0, 0, 0, 0
+};
+
+static const VertexType kBombLevelSix[] = {
+ 0, 1, 1, 1, 0,
+ 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 1,
+ 1, 1, 1, 1, 1,
+ 0, 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, 0, 0,
+
+ 25,
+
+ kEdgeOneSixteenth,
+ 2,
+ 10, 1,
+ 0,
+
+ kEdgeOneSixteenth,
+ 2,
+ 23, 14,
+ 0,
+
+ kEdgeSevenSixteenths,
+ 2,
+ 3, 14,
+ 0,
+
+ kEdgeSevenSixteenths,
+ 2,
+ 10, 21,
+ 0,
+
+ kEdgeOneEighth,
+ 2,
+ 5, 1,
+ 0,
+
+ kEdgeOneEighth,
+ 3,
+ 10, 6, 2,
+ 0, 0,
+
+ kEdgeOneEighth,
+ 2,
+ 7, 3,
+ 0,
+
+ kEdgeOneEighth,
+ 2,
+ 21, 17,
+ 0,
+
+ kEdgeOneEighth,
+ 3,
+ 22, 18, 14,
+ 0, 0,
+
+ kEdgeOneEighth,
+ 2,
+ 23, 19,
+ 0,
+
+ kEdgeThreeEighths,
+ 2,
+ 1, 7,
+ 0,
+
+ kEdgeThreeEighths,
+ 3,
+ 2, 8, 14,
+ 0, 0,
+
+ kEdgeThreeEighths,
+ 2,
+ 3, 9,
+ 0,
+
+ kEdgeThreeEighths,
+ 3,
+ 10, 16, 22,
+ 0, 0,
+
+ kEdgeThreeEighths,
+ 2,
+ 15, 21,
+ 0,
+
+ kEdgeThreeEighths,
+ 2,
+ 17, 23,
+ 0,
+
+ kEdgeOneFourth,
+ 3,
+ 1, 2, 3,
+ 0, 0,
+
+ kEdgeOneFourth,
+ 3,
+ 6, 7, 8,
+ 0, 0,
+
+ kEdgeOneFourth,
+ 3,
+ 16, 17, 18,
+ 0, 0,
+
+ kEdgeOneFourth,
+ 3,
+ 21, 22, 23,
+ 0, 0,
+
+ kEdgeOneHalf,
+ 3,
+ 5, 10, 15,
+ 0, 0,
+
+ kEdgeOneHalf,
+ 3,
+ 6, 11, 16,
+ 0, 0,
+
+ kEdgeOneHalf,
+ 5,
+ 2, 7, 12, 17, 22,
+ 0, 0, 0, 0,
+
+ kEdgeOneHalf,
+ 3,
+ 8, 13, 18,
+ 0, 0,
+
+ kEdgeOneHalf,
+ 3,
+ 9, 14, 19,
+ 0, 0
+};
+
+static const CoordType kBombGridWidth = 140;
+static const CoordType kBombGridHeight = 140;
+
+static const CoordType kDotOriginX = 0;
+static const CoordType kDotOriginY = 0;
+
+static const CoordType kVertOriginX = 2;
+static const CoordType kVertOriginY = 6;
+
+static const CoordType kHorizOriginX = 6;
+static const CoordType kHorizOriginY = 2;
+
+static const CoordType kDiagOriginX = 6;
+static const CoordType kDiagOriginY = 6;
+
+static const int g_originsX[] = {
+ kDiagOriginX,
+ kDiagOriginX,
+ kDiagOriginX,
+ kHorizOriginX,
+ kDiagOriginX,
+ kDiagOriginX,
+ kDiagOriginX,
+ kVertOriginX
+};
+
+static const int g_originsY[] = {
+ kDiagOriginY - 64,
+ kDiagOriginY - 32,
+ kDiagOriginY - 32,
+ kHorizOriginY,
+ kDiagOriginY,
+ kDiagOriginY,
+ kDiagOriginY,
+ kVertOriginY
+};
+
+struct HotVerticesList {
+ int numHotVerts;
+ VertexType hotVerts[25];
+};
+
+CoordType vertToX(VertexType vertex) {
+ return (vertex % 5) * 32;
+}
+
+CoordType vertToY(VertexType vertex) {
+ return (vertex / 5) * 32;
+}
+
+// This function returns the number of edges in the bomb edge list.
+VertexType getNumEdges(BombEdgeList edges) {
+ return edges[50];
+}
+
+// These four functions return pointers into the given edge list.
+
+// getFirstEdge and getNextEdge can be used to iterate across all edges
+// in an edge list. These functions can be used to walk all the edges
+// in a bomb edge list for drawing.
+VertexType *getFirstEdge(BombEdgeList edges) {
+ return &edges[51];
+}
+
+VertexType *getNextEdge(VertexType *anEdge) {
+ return anEdge + *(anEdge + 1) * 2 + 1;
+}
+
+// getVertices returns a pointer to all of the vertices that should are
+// hot. These vertices indicate all the vertices that should be drawn in
+// the game.
+VertexType *getVertices(BombEdgeList edges) {
+ return &edges[0];
+}
+
+// getUsedVertices returns a pointer to the "used" vertices area: the
+// area that keeps track of which vertices have been set by the
+// setVertexUsed used function.
+VertexType *getUsedVertices(BombEdgeList edges) {
+ return &edges[25];
+}
+
+// Useful for saving. Saving the state of the bomb game is as simple as writing
+// out the edge list.
+int getEdgeListSize(BombEdgeList edges) {
+ VertexType numEdges = getNumEdges(edges);
+ VertexType *anEdge = getFirstEdge(edges);
+
+ while (numEdges--)
+ anEdge = getNextEdge(anEdge);
+
+ return anEdge - edges + 4;
+}
+
+// Returns true if the given vertex lies on the given edge.
+bool vertexOnEdge(VertexType *anEdge, VertexType whichVertex) {
+ VertexType numVerts = *++anEdge;
+
+ while (numVerts--)
+ if (*++anEdge == whichVertex)
+ return true;
+
+ return false;
+}
+
+// Given an edge list and a from vertex, this function constructs a list
+// of all vertices that may be clicked on.
+// if fromVertex == -1, all vertices are eligible.
+// otherwise, only vertices on a line from fromVertex are eligible.
+void makeHotVertexList(BombEdgeList edges, VertexType fromVertex, HotVerticesList &hotVertices) {
+ hotVertices.numHotVerts = 0;
+
+ if (fromVertex == -1) {
+ for (VertexType i = 0; i < 25; i++)
+ if (edges[i])
+ hotVertices.hotVerts[hotVertices.numHotVerts++] = i;
+ } else {
+ VertexType numEdges = getNumEdges(edges);
+ VertexType *anEdge = getFirstEdge(edges);
+ hotVertices.hotVerts[hotVertices.numHotVerts++] = fromVertex;
+
+ while (numEdges--) {
+ if (vertexOnEdge(anEdge, fromVertex)) {
+ VertexType *p = anEdge + 1;
+ VertexType numVerts = *p;
+
+ while (numVerts--)
+ if (*++p != fromVertex)
+ hotVertices.hotVerts[hotVertices.numHotVerts++] = *p;
+ }
+
+ anEdge = getNextEdge(anEdge);
+ }
+ }
+}
+
+// Set all edges in the edge list to the value passed in "edgeVal".
+// For drawing purposes, 0 can mean don't draw, and 1 and higher can
+// represent different colors.
+void setAllEdgesUsed(BombEdgeList edges, VertexType used) {
+ VertexType numEdges = getNumEdges(edges);
+ VertexType *anEdge = getFirstEdge(edges);
+
+ while (numEdges--) {
+ VertexType *p1 = anEdge + 1;
+ VertexType numVerts = *p1;
+ p1 += numVerts + 1;
+
+ while (--numVerts)
+ *p1++ = used;
+
+ anEdge = getNextEdge(anEdge);
+ }
+
+ VertexType *p1 = edges;
+ VertexType *p2 = getUsedVertices(edges);
+
+ for (VertexType i = 0; i < 25; i++, p1++, p2++)
+ if (*p1)
+ *p2 = used;
+}
+
+// Same as setAllEdgesUsed, but only affects edges that are already set
+// to a non-zero value.
+void setAllUsedEdgesUsed(BombEdgeList edges, VertexType used) {
+ VertexType numEdges = getNumEdges(edges);
+ VertexType *anEdge = getFirstEdge(edges);
+
+ while (numEdges--) {
+ VertexType *p = anEdge + 1;
+ VertexType numVerts = *p;
+ p += numVerts + 1;
+
+ while (--numVerts) {
+ if (*p)
+ *p = used;
+ ++p;
+ }
+
+ anEdge = getNextEdge(anEdge);
+ }
+
+ VertexType *p = getUsedVertices(edges);
+ for (VertexType i = 0; i < 25; i++, p++)
+ if (*p)
+ *p = used;
+}
+
+// Replace all edges with value "value" with the new value "used".
+void replaceUsedEdges(BombEdgeList edges, VertexType value, VertexType used) {
+ VertexType numEdges = getNumEdges(edges);
+ VertexType *anEdge = getFirstEdge(edges);
+
+ while (numEdges--) {
+ VertexType *p = anEdge + 1;
+ VertexType numVerts = *p;
+ p += numVerts + 1;
+
+ while (--numVerts) {
+ if (*p == value)
+ *p = used;
+
+ p++;
+ }
+
+ anEdge = getNextEdge(anEdge);
+ }
+
+ VertexType *p = getUsedVertices(edges);
+ for (VertexType i = 0; i < 25; i++, p++)
+ if (*p == value)
+ *p = used;
+}
+
+// Set a vertex's value to "used".
+void setVertexUsed(BombEdgeList edges, VertexType whichVertex, VertexType value) {
+ *(getUsedVertices(edges) + whichVertex) = value;
+}
+
+// Mark an edge in the given list between the two vertices as "used". This marks
+// all inbetween vertices as well, even if the vertex is not marked as a "hot"
+// vertex in the hot vertex section. Returns true if doing this operation
+// crosses an already marked edge.
+bool setEdgeUsed(BombEdgeList edges, VertexType fromVertex, VertexType toVertex) {
+ VertexType numEdges = getNumEdges(edges);
+ VertexType *anEdge = getFirstEdge(edges);
+ bool crossed = false;
+
+ while (numEdges--) {
+ VertexType *p = anEdge;
+ VertexType numVerts = *++p;
+ VertexType *fromPtr = 0;
+ VertexType *toPtr = 0;
+ VertexType i = numVerts;
+ p++;
+
+ while (i--) {
+ if (*p == fromVertex)
+ fromPtr = p;
+ else if (*p == toVertex)
+ toPtr = p;
+
+ if (fromPtr && toPtr) {
+ // Found the edge...
+ if (fromPtr > toPtr) {
+ p = fromPtr;
+ fromPtr = toPtr;
+ toPtr = p;
+ }
+
+ p = fromPtr + numVerts;
+
+ for (i = toPtr - fromPtr; i > 0; i--, p++) {
+ ++(*p);
+
+ if (*p == 2)
+ crossed = true;
+ }
+
+ VertexType *verts = getVertices(edges);
+ VertexType *usedVerts = getUsedVertices(edges);
+ *(usedVerts + *fromPtr) = 1;
+
+ for (p = fromPtr + 1; p != toPtr; p++)
+ if (*(verts + *p))
+ *(usedVerts + *p) = 1;
+
+ *(usedVerts + *toPtr) = 1;
+ return crossed;
+ }
+
+ p++;
+ }
+
+ anEdge = getNextEdge(anEdge);
+ }
+
+ return false;
+}
+
+// Return true if all edges are used. Can be used to determine when the bomb
+// game is over.
+bool allEdgesUsed(BombEdgeList edges) {
+ VertexType numEdges = getNumEdges(edges);
+ VertexType *anEdge = getFirstEdge(edges);
+
+ while (numEdges--) {
+ VertexType *p = anEdge + 1;
+ VertexType numVerts = *p;
+ p += numVerts + 1;
+
+ while (--numVerts) {
+ if (!*p)
+ return false;
+
+ ++p;
+ }
+
+ anEdge = getNextEdge(anEdge);
+ }
+
+ return true;
+}
+
+BombGrid::BombGrid(const DisplayElementID id) : Picture(id) {
+ Common::Rect bounds(0, 0, kBombGridWidth, kBombGridHeight);
+
+ allocateSurface(bounds);
+ setBounds(bounds);
+ _surface->fillRect(bounds, g_system->getScreenFormat().RGBToColor(0xff, 0xff, 0xff));
+
+ _transparent = true;
+
+ _yellowDot.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kYellowBombPICTBaseID, true);
+ _yellowOneSixteenth.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kYellowBombPICTBaseID + 1, true);
+ _yellowOneEighth.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kYellowBombPICTBaseID + 2, true);
+ _yellowThreeSixteenths.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kYellowBombPICTBaseID + 3, true);
+ _yellowOneFourth.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kYellowBombPICTBaseID + 4, true);
+ _yellowFiveSixteenths.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kYellowBombPICTBaseID + 5, true);
+ _yellowThreeEighths.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kYellowBombPICTBaseID + 6, true);
+ _yellowSevenSixteenths.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kYellowBombPICTBaseID + 7, true);
+ _yellowOneHalf.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kYellowBombPICTBaseID + 8, true);
+
+ _redDot.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kRedBombPICTBaseID, true);
+ _redOneSixteenth.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kRedBombPICTBaseID + 1, true);
+ _redOneEighth.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kRedBombPICTBaseID + 2, true);
+ _redThreeSixteenths.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kRedBombPICTBaseID + 3, true);
+ _redOneFourth.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kRedBombPICTBaseID + 4, true);
+ _redFiveSixteenths.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kRedBombPICTBaseID + 5, true);
+ _redThreeEighths.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kRedBombPICTBaseID + 6, true);
+ _redSevenSixteenths.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kRedBombPICTBaseID + 7, true);
+ _redOneHalf.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kRedBombPICTBaseID + 8, true);
+}
+
+void BombGrid::drawEdges(BombEdgeList edges) {
+ GraphicsManager *gfx = ((PegasusEngine *)g_engine)->_gfx;
+ gfx->setCurSurface(_surface);
+
+ _surface->fillRect(Common::Rect(0, 0, kBombGridWidth, kBombGridHeight), g_system->getScreenFormat().RGBToColor(0xff, 0xff, 0xff));
+
+ Frame *yellowStuff = &_yellowDot;
+ Frame *redStuff = &_redDot;
+ VertexType numEdges = getNumEdges(edges);
+ VertexType *anEdge = getFirstEdge(edges);
+ VertexType i, *p;
+
+ Common::Rect bounds;
+ getSurfaceBounds(bounds);
+
+ while (numEdges--) {
+ p = anEdge;
+ VertexType edgeDirection = *p++;
+ VertexType numVerts = *p++;
+ VertexType numSegs = numVerts - 1;
+
+ for (i = 0; i < numSegs; i++, p++) {
+ if (*(p + numVerts) > 0 && *(p + numVerts) < 4) {
+ Frame *drawStuff;
+
+ if (*(p + numVerts) == 2)
+ drawStuff = redStuff;
+ else
+ drawStuff = yellowStuff;
+
+ int x = vertToX(*p) + g_originsX[edgeDirection];
+ int y = vertToY(*p) + g_originsY[edgeDirection];
+
+ Common::Rect r1;
+ drawStuff[edgeDirection + 1].getSurfaceBounds(r1);
+ Common::Rect r2 = r1;
+ r2.moveTo(x, y);
+ drawStuff[edgeDirection + 1].drawImage(r1, r2);
+ }
+ }
+
+ anEdge = getNextEdge(anEdge);
+ }
+
+ for (i = 0, p = getUsedVertices(edges); i < 25; i++, p++) {
+ if (*p > 0 && *p < 4) {
+ Frame *drawStuff;
+
+ if (*p == 2)
+ drawStuff = redStuff;
+ else
+ drawStuff = yellowStuff;
+
+ int x = vertToX(i) + kDotOriginX;
+ int y = vertToY(i) + kDotOriginY;
+
+ Common::Rect r1;
+ drawStuff->getSurfaceBounds(r1);
+ Common::Rect r2 = r1;
+ r2.moveTo(x, y);
+ drawStuff->drawImage(r1, r2);
+ }
+ }
+
+ triggerRedraw();
+ gfx->setCurSurface(gfx->getWorkArea());
+}
+
+BombTimer::BombTimer(const DisplayElementID id) : IdlerAnimation(id) {
+ _middle = -1;
+ _leftImage.getImageFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kTimerLeftPICTID);
+ _rightImage.getImageFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kTimerRightPICTID);
+
+ Common::Rect r;
+ _leftImage.getSurfaceBounds(r);
+ setBounds(r);
+}
+
+void BombTimer::draw(const Common::Rect &updateRect) {
+ Common::Rect bounds;
+ getBounds(bounds);
+
+ Common::Rect r1 = bounds;
+ r1.right = _middle;
+ r1 = r1.findIntersectingRect(updateRect);
+
+ if (!r1.isEmpty()) {
+ Common::Rect r2 = r1;
+ r2.moveTo(r1.left - bounds.left, r1.top - bounds.top);
+ _leftImage.copyToCurrentPort(r2, r1);
+ }
+
+ r1 = bounds;
+ r1.left = _middle;
+ r1 = r1.findIntersectingRect(updateRect);
+
+ if (!r1.isEmpty()) {
+ Common::Rect r2 = r1;
+ r2.moveTo(r1.left - bounds.left, r1.top - bounds.top);
+ _rightImage.copyToCurrentPort(r2, r1);
+ }
+}
+
+void BombTimer::timeChanged(const TimeValue newTime) {
+ Common::Rect bounds;
+ getBounds(bounds);
+
+ int newMiddle = bounds.right - bounds.width() * newTime / getDuration();
+ if (newMiddle != _middle) {
+ _middle = newMiddle;
+ triggerRedraw();
+ }
+}
+
+#define CREATE_BOMB_LEVEL(num, data) \
+ _bombLevel[num] = new VertexType[sizeof(data)]; \
+ memcpy(_bombLevel[num], data, sizeof(data))
+
+CaldoriaBomb::CaldoriaBomb(Neighborhood *owner, NotificationManager *manager) :
+ GameInteraction(kCaldoriaBombInteractionID, owner), _grid(kCaldoriaBombGridID),
+ _timer(kCaldoriaBombTimerID), _timerNotification(kCaldoriaBombTimerNotificationID, manager) {
+ CREATE_BOMB_LEVEL(0, kBombLevelOne);
+ CREATE_BOMB_LEVEL(1, kBombLevelTwo);
+ CREATE_BOMB_LEVEL(2, kBombLevelThree);
+ CREATE_BOMB_LEVEL(3, kBombLevelFour);
+ CREATE_BOMB_LEVEL(4, kBombLevelFive);
+ CREATE_BOMB_LEVEL(5, kBombLevelSix);
+ _currentLevel = 0;
+}
+
+#undef CREATE_BOMB_LEVEL
+
+CaldoriaBomb::~CaldoriaBomb() {
+ for (int i = 0; i < 6; i++)
+ delete[] _bombLevel[i];
+}
+
+void CaldoriaBomb::openInteraction() {
+ _grid.moveElementTo(kCaldoriaBombGridLeft, kCaldoriaBombGridTop);
+ _grid.setDisplayOrder(kCaldoriaBombGridOrder);
+ _grid.startDisplaying();
+
+ _timer.moveElementTo(kCaldoriaBombTimerLeft, kCaldoriaBombTimerTop);
+ _timer.setDisplayOrder(kCaldoriaBombTimerOrder);
+ _timer.startDisplaying();
+ _timer.setSegment(0, kTenMinutesPerFifteenTicks, kFifteenTicksPerSecond);
+ _timer.setTime(0);
+
+ _timerNotification.notifyMe(this, kBombTimerExpiredFlag, kBombTimerExpiredFlag);
+ _timerCallBack.setNotification(&_timerNotification);
+ _timerCallBack.initCallBack(&_timer, kCallBackAtExtremes);
+ _timerCallBack.setCallBackFlag(kBombTimerExpiredFlag);
+
+ Common::Rect r(0, 0, kVertextHotSpotWidth, kVertextHotSpotHeight);
+
+ for (VertexType i = 0; i < 25; i++) {
+ _vertexHotspot[i] = new Hotspot(i + kVertextHotSpotBaseID);
+ r.moveTo(vertToX(i) + kCaldoriaBombGridLeft - kVertextHotSpotWidth / 2 + 6,
+ vertToY(i) + kCaldoriaBombGridTop - kVertextHotSpotHeight / 2 + 6);
+ _vertexHotspot[i]->setArea(r);
+ _vertexHotspot[i]->setHotspotFlags(kNeighborhoodSpotFlag | kClickSpotFlag);
+ g_allHotspots.push_back(_vertexHotspot[i]);
+ }
+
+ _neighborhoodNotification = _owner->getNeighborhoodNotification();
+ _neighborhoodNotification->notifyMe(this, kExtraCompletedFlag, kExtraCompletedFlag);
+}
+
+void CaldoriaBomb::initInteraction() {
+ _owner->loadLoopSound1("");
+ _owner->startExtraSequence(kCaldoria56BombStage1, kExtraCompletedFlag, kFilterNoInput);
+}
+
+void CaldoriaBomb::closeInteraction() {
+ _timer.stop();
+ _timer.hide();
+ _timer.stopDisplaying();
+ _grid.hide();
+ _grid.stopDisplaying();
+
+ // The original did not do this, but we need it here
+ // Not sure why the original worked without this; probably
+ // related to the way the List code worked in CodeWarrior.
+ // If this is not here, the notifications will later attempt
+ // to remove itself from this receiver causing a very nasty
+ // crash.
+ _timerNotification.cancelNotification(this);
+ _neighborhoodNotification->cancelNotification(this);
+}
+
+void CaldoriaBomb::startBombAmbient(Common::String ambient) {
+ _owner->loadLoopSound1(ambient);
+}
+
+void CaldoriaBomb::receiveNotification(Notification *notification, const NotificationFlags) {
+ if (notification == _neighborhoodNotification) {
+ switch (_owner->getLastExtra()) {
+ case kCaldoria56BombStage1:
+ _grid.show();
+ _timer.show();
+ _timerCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ _timer.start();
+ _currentLevel = 0;
+ _lastVertex = -1;
+ startBombAmbient("Sounds/Caldoria/BmbLoop1.22K.AIFF");
+ break;
+ case kCaldoria56BombStage2:
+ case kCaldoria56BombStage3:
+ case kCaldoria56BombStage4:
+ case kCaldoria56BombStage5:
+ case kCaldoria56BombStage6:
+ _grid.show();
+ _currentLevel++;
+ _grid.drawEdges(_bombLevel[_currentLevel]);
+ _lastVertex = -1;
+ startBombAmbient(Common::String::format("Sounds/Caldoria/BmbLoop%d.22K.AIFF", _owner->getLastExtra() - kCaldoria56BombStage1 + 1));
+ break;
+ case kCaldoria56BombStage7:
+ _owner->requestDeleteCurrentInteraction();
+ GameState.setCaldoriaBombDisarmed(true);
+ GameState.setScoringDisarmedNuke(true);
+ _owner->loadAmbientLoops();
+ break;
+ }
+ } else if (notification == &_timerNotification) {
+ _grid.hide();
+ _timer.stop();
+ _timer.hide();
+ _owner->loadLoopSound1("");
+ _owner->playDeathExtra(kCaldoria56BombExplodes, kDeathNuclearExplosion);
+ }
+}
+
+void CaldoriaBomb::activateHotspots() {
+ GameInteraction::activateHotspots();
+
+ if (_currentLevel != -1 && _lastVertex >= -1) {
+ HotVerticesList hotVertices;
+ makeHotVertexList(_bombLevel[_currentLevel], _lastVertex, hotVertices);
+
+ for (VertexType i = 0; i < hotVertices.numHotVerts; i++)
+ g_allHotspots.activateOneHotspot(hotVertices.hotVerts[i] + kVertextHotSpotBaseID);
+ }
+}
+
+void CaldoriaBomb::clickInHotspot(const Input &input, const Hotspot *hotspot) {
+ int clickedVertex = (int)hotspot->getObjectID() - (int)kVertextHotSpotBaseID;
+
+ if (clickedVertex >= 0 && clickedVertex < 25) {
+ if (_lastVertex != -1 && setEdgeUsed(_bombLevel[_currentLevel], _lastVertex, clickedVertex)) {
+ clickedVertex = -2;
+ _flashTime = tickCount();
+ } else if (allEdgesUsed(_bombLevel[_currentLevel])) {
+ setVertexUsed(_bombLevel[_currentLevel], clickedVertex, 1);
+ clickedVertex = -20;
+ _flashTime = tickCount();
+ } else {
+ setVertexUsed(_bombLevel[_currentLevel], clickedVertex, 2);
+ }
+
+ _grid.drawEdges(_bombLevel[_currentLevel]);
+ _lastVertex = clickedVertex;
+ } else {
+ GameInteraction::clickInHotspot(input, hotspot);
+ }
+}
+
+InputBits CaldoriaBomb::getInputFilter() {
+ // Disallow arrow buttons.
+ return GameInteraction::getInputFilter() & kFilterAllButtons;
+}
+
+void CaldoriaBomb::handleInput(const Input &input, const Hotspot *hotspot) {
+ GameInteraction::handleInput(input, hotspot);
+
+ switch (_lastVertex) {
+ case -2: // Flash back to yellow.
+ if (tickCount() > _flashTime + kOnTime1) {
+ replaceUsedEdges(_bombLevel[_currentLevel], 2, 3);
+ _grid.drawEdges(_bombLevel[_currentLevel]);
+ _lastVertex = -3;
+ }
+ break;
+ case -3: // Flash back to red.
+ if (tickCount() > _flashTime + kOffTime1) {
+ replaceUsedEdges(_bombLevel[_currentLevel], 3, 2);
+ _grid.drawEdges(_bombLevel[_currentLevel]);
+ _lastVertex = -4;
+ }
+ break;
+ case -4: // Flash all to yellow.
+ if (tickCount() > _flashTime + kOnTime2) {
+ setAllUsedEdgesUsed(_bombLevel[_currentLevel], 1);
+ _grid.drawEdges(_bombLevel[_currentLevel]);
+ _lastVertex = -5;
+ }
+ break;
+ case -5: // Flash all to red.
+ if (tickCount() > _flashTime + kOffTime2) {
+ setAllUsedEdgesUsed(_bombLevel[_currentLevel], 2);
+ _grid.drawEdges(_bombLevel[_currentLevel]);
+ _lastVertex = -6;
+ }
+ break;
+ case -6: // Flash all to yellow.
+ if (tickCount() > _flashTime + kOnTime3) {
+ setAllUsedEdgesUsed(_bombLevel[_currentLevel], 1);
+ _grid.drawEdges(_bombLevel[_currentLevel]);
+ _lastVertex = -7;
+ }
+ break;
+ case -7: // Flash all to red.
+ if (tickCount() > _flashTime + kOffTime3) {
+ setAllUsedEdgesUsed(_bombLevel[_currentLevel], 2);
+ _grid.drawEdges(_bombLevel[_currentLevel]);
+ _lastVertex = -8;
+ }
+ break;
+ case -8: // Restore to normal.
+ if (tickCount() > _flashTime + kOnTime4) {
+ setAllEdgesUsed(_bombLevel[_currentLevel], 0);
+ _grid.drawEdges(_bombLevel[_currentLevel]);
+ _lastVertex = -1;
+ }
+ break;
+
+ // Flash grid after success.
+ case -20: // Flash off.
+ if (tickCount() > _flashTime + kOnTime1) {
+ setAllEdgesUsed(_bombLevel[_currentLevel], 4);
+ _grid.drawEdges(_bombLevel[_currentLevel]);
+ _lastVertex = -21;
+ }
+ break;
+ case -21: // Flash on.
+ if (tickCount() > _flashTime + kOffTime1) {
+ setAllEdgesUsed(_bombLevel[_currentLevel], 1);
+ _grid.drawEdges(_bombLevel[_currentLevel]);
+ _lastVertex = -22;
+ }
+ break;
+ case -22: // Flash off.
+ if (tickCount() > _flashTime + kOnTime2) {
+ setAllEdgesUsed(_bombLevel[_currentLevel], 4);
+ _grid.drawEdges(_bombLevel[_currentLevel]);
+ _lastVertex = -23;
+ }
+ break;
+ case -23: // Flash on.
+ if (tickCount() > _flashTime + kOffTime2) {
+ setAllEdgesUsed(_bombLevel[_currentLevel], 1);
+ _grid.drawEdges(_bombLevel[_currentLevel]);
+ _lastVertex = -24;
+ }
+ break;
+ case -24:
+ if (tickCount() > _flashTime + kOnTime3) {
+ _grid.hide();
+ _lastVertex = -1;
+ _owner->loadLoopSound1("");
+
+ switch (_currentLevel) {
+ case 0:
+ _owner->startExtraSequence(kCaldoria56BombStage2, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case 1:
+ _owner->startExtraSequence(kCaldoria56BombStage3, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case 2:
+ _owner->startExtraSequence(kCaldoria56BombStage4, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case 3:
+ _owner->startExtraSequence(kCaldoria56BombStage5, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case 4:
+ _owner->startExtraSequence(kCaldoria56BombStage6, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case 5:
+ _timer.stop();
+ _grid.hide();
+ _timer.hide();
+ _owner->startExtraSequence(kCaldoria56BombStage7, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ }
+ }
+ break;
+ }
+}
+
+long CaldoriaBomb::getNumHints() {
+ return 2;
+}
+
+Common::String CaldoriaBomb::getHintMovie(uint hintNum) {
+ return (hintNum == 1) ? "Images/AI/Caldoria/X56EH2" : "Images/AI/Caldoria/X56EH3";
+}
+
+bool CaldoriaBomb::canSolve() {
+ return true;
+}
+
+void CaldoriaBomb::doSolve() {
+ _timer.stop();
+ _grid.hide();
+ _timer.hide();
+ _owner->loadLoopSound1("");
+ _owner->startExtraSequence(kCaldoria56BombStage7, kExtraCompletedFlag, kFilterNoInput);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/caldoria/caldoriabomb.h b/engines/pegasus/neighborhood/caldoria/caldoriabomb.h
new file mode 100644
index 0000000000..5bb39b4122
--- /dev/null
+++ b/engines/pegasus/neighborhood/caldoria/caldoriabomb.h
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_CALDORIA_CALDORIABOMB_H
+#define PEGASUS_NEIGHBORHOOD_CALDORIA_CALDORIABOMB_H
+
+#include "pegasus/interaction.h"
+#include "pegasus/notification.h"
+#include "pegasus/surface.h"
+
+namespace Pegasus {
+
+/*
+ Edge list is arranged as follows:
+
+ all values in the edge list are bytes.
+
+ all vertices are numbers between 0 and 24. x coordinate of vertex is vertex % 5,
+ and y coordinate is vertex / 5.
+
+ an edge is
+ a direction code
+ a number of vertices in the edge
+ an array of vertices -- all vertices along the edge, whether or not they're
+ clickable.
+ an array of bools (bytes) indicating that a portion of the edge is
+ traversed (and should be drawn). the number of bools is one less than
+ the number of vertices.
+
+ an edge list is
+ an array of 25 bools indicating which vertex is clickable.
+ an array of 25 bools indicating which vertex is used (drawn).
+ a number of edges
+ an array of edges.
+
+ a hot vertex list is
+ a number of vertices
+ an array of 25 vertices
+
+*/
+
+typedef int8 VertexType;
+typedef VertexType *BombEdgeList;
+
+static const VertexType kEdgeOneSixteenth = 0;
+static const VertexType kEdgeOneEighth = 1;
+static const VertexType kEdgeThreeSixteenths = 2;
+static const VertexType kEdgeOneFourth = 3;
+static const VertexType kEdgeFiveSixteenths = 4;
+static const VertexType kEdgeThreeEighths = 5;
+static const VertexType kEdgeSevenSixteenths = 6;
+static const VertexType kEdgeOneHalf = 7;
+
+class BombTimer : public IdlerAnimation {
+public:
+ BombTimer(const DisplayElementID);
+ virtual ~BombTimer() {}
+
+ void draw(const Common::Rect &);
+
+protected:
+ void timeChanged(const TimeValue);
+
+ int _middle;
+ Surface _leftImage, _rightImage;
+};
+
+class BombGrid : public Picture {
+public:
+ BombGrid(const DisplayElementID);
+ virtual ~BombGrid() {}
+
+ void drawEdges(BombEdgeList);
+
+protected:
+ Frame _yellowDot;
+ Frame _yellowOneSixteenth;
+ Frame _yellowOneEighth;
+ Frame _yellowThreeSixteenths;
+ Frame _yellowOneFourth;
+ Frame _yellowFiveSixteenths;
+ Frame _yellowThreeEighths;
+ Frame _yellowSevenSixteenths;
+ Frame _yellowOneHalf;
+ Frame _redDot;
+ Frame _redOneSixteenth;
+ Frame _redOneEighth;
+ Frame _redThreeSixteenths;
+ Frame _redOneFourth;
+ Frame _redFiveSixteenths;
+ Frame _redThreeEighths;
+ Frame _redSevenSixteenths;
+ Frame _redOneHalf;
+};
+
+class Hotspot;
+
+class CaldoriaBomb : public GameInteraction, public NotificationReceiver {
+public:
+ CaldoriaBomb(Neighborhood *, NotificationManager *);
+ virtual ~CaldoriaBomb();
+
+ long getNumHints();
+ Common::String getHintMovie(uint);
+ void doSolve();
+ bool canSolve();
+
+protected:
+ void openInteraction();
+ void initInteraction();
+ void closeInteraction();
+ void receiveNotification(Notification *, const NotificationFlags);
+ void activateHotspots();
+ void clickInHotspot(const Input &, const Hotspot *);
+ void handleInput(const Input &, const Hotspot *);
+ InputBits getInputFilter();
+ void startBombAmbient(Common::String);
+
+ Notification *_neighborhoodNotification;
+ BombGrid _grid;
+ BombTimer _timer;
+ BombEdgeList _bombLevel[6];
+ int _currentLevel, _flashTime;
+ Hotspot *_vertexHotspot[25];
+ VertexType _lastVertex;
+ Notification _timerNotification;
+ NotificationCallBack _timerCallBack;
+
+ TimeValue _readTime;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/caldoria/caldoriamessages.cpp b/engines/pegasus/neighborhood/caldoria/caldoriamessages.cpp
new file mode 100644
index 0000000000..a3ce97d438
--- /dev/null
+++ b/engines/pegasus/neighborhood/caldoria/caldoriamessages.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/gamestate.h"
+#include "pegasus/neighborhood/neighborhood.h"
+#include "pegasus/neighborhood/caldoria/caldoria.h"
+#include "pegasus/neighborhood/caldoria/caldoriamessages.h"
+
+namespace Pegasus {
+
+static const NotificationFlags kMessageDoneFlag = 1;
+
+CaldoriaMessages::CaldoriaMessages(Neighborhood *owner, const NotificationID id, NotificationManager *manager) :
+ GameInteraction(kCaldoriaMessagesInteractionID, owner), Notification(id, manager), _messageMovie(kCaldoriaMessagesID) {
+}
+
+void CaldoriaMessages::openInteraction() {
+ _neighborhoodNotification = GameInteraction::_owner->getNeighborhoodNotification();
+ _neighborhoodNotification->notifyMe(this, kExtraCompletedFlag, kExtraCompletedFlag);
+ _messageCallBack.setNotification(this);
+ notifyMe(this, kMessageDoneFlag, kMessageDoneFlag);
+ _messageCallBack.setCallBackFlag(kMessageDoneFlag);
+ _messageNumber = 1;
+}
+
+void CaldoriaMessages::initInteraction() {
+ GameInteraction::_owner->startExtraSequence(kCaBedroomVidPhone, kExtraCompletedFlag, kFilterNoInput);
+}
+
+void CaldoriaMessages::closeInteraction() {
+ cancelNotification(this);
+ _neighborhoodNotification->cancelNotification(this);
+}
+
+void CaldoriaMessages::receiveNotification(Notification *notification, const NotificationFlags) {
+ if (notification == _neighborhoodNotification) {
+ switch (GameInteraction::_owner->getLastExtra()) {
+ case kCaBedroomVidPhone:
+ GameInteraction::_owner->showExtraView(kCaBedroomMessage1);
+ break;
+ case kCaBedroomMessage1:
+ play1Message(1);
+ break;
+ case kCaBedroomMessage2:
+ play1Message(2);
+ break;
+ }
+ } else {
+ _messageCallBack.releaseCallBack();
+ _messageMovie.releaseMovie();
+
+ uint32 extraID = (_messageNumber == 1) ? kCaBedroomMessage1 : kCaBedroomMessage2;
+ GameInteraction::_owner->showExtraView(extraID);
+ allowInput(true);
+ }
+}
+
+void CaldoriaMessages::clickInHotspot(const Input &input, const Hotspot *spot) {
+ uint32 extraID;
+
+ switch (spot->getObjectID()) {
+ case kCaBedroomVidPhoneActivationSpotID:
+ extraID = (_messageNumber == 1) ? kCaBedroomMessage1 : kCaBedroomMessage2;
+ GameInteraction::_owner->startExtraSequence(extraID, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ default:
+ GameInteraction::clickInHotspot(input, spot);
+ break;
+ }
+}
+
+void CaldoriaMessages::play1Message(uint messageNumber) {
+ if (messageNumber == 1) {
+ _messageMovie.initFromMovieFile("Images/Caldoria/A12NVA.movie");
+ _messageNumber = 2;
+ } else {
+ _messageMovie.initFromMovieFile("Images/Caldoria/A12NVB.movie");
+ _messageNumber = 1;
+ GameState.setCaldoriaSeenMessages(true);
+ }
+
+ _messageMovie.moveElementTo(kCaldoriaMessageLeft, kCaldoriaMessageTop);
+ _messageMovie.setDisplayOrder(kCaldoriaMessagesOrder);
+ _messageMovie.startDisplaying();
+ _messageCallBack.initCallBack(&_messageMovie, kCallBackAtExtremes);
+ _messageCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ allowInput(false);
+ _messageMovie.show();
+ _messageMovie.redrawMovieWorld();
+ _messageMovie.start();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/caldoria/caldoriamessages.h b/engines/pegasus/neighborhood/caldoria/caldoriamessages.h
new file mode 100644
index 0000000000..955fe10ce9
--- /dev/null
+++ b/engines/pegasus/neighborhood/caldoria/caldoriamessages.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_CALDORIA_CALDORIAMESSAGES_H
+#define PEGASUS_NEIGHBORHOOD_CALDORIA_CALDORIAMESSAGES_H
+
+#include "pegasus/input.h"
+#include "pegasus/interaction.h"
+#include "pegasus/movie.h"
+#include "pegasus/notification.h"
+#include "pegasus/timers.h"
+
+namespace Pegasus {
+
+class Neighborhood;
+
+class CaldoriaMessages : public GameInteraction, public Notification, public NotificationReceiver {
+public:
+ CaldoriaMessages(Neighborhood *, const NotificationID, NotificationManager *);
+ virtual ~CaldoriaMessages() {}
+
+protected:
+ void openInteraction();
+ void initInteraction();
+ void closeInteraction();
+ void receiveNotification(Notification *, const NotificationFlags);
+ void clickInHotspot(const Input &, const Hotspot *);
+ void play1Message(uint);
+
+ Movie _messageMovie;
+ NotificationCallBack _messageCallBack;
+ Notification *_neighborhoodNotification;
+ uint _messageNumber;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/caldoria/caldoriamirror.cpp b/engines/pegasus/neighborhood/caldoria/caldoriamirror.cpp
new file mode 100644
index 0000000000..ff4d1811d0
--- /dev/null
+++ b/engines/pegasus/neighborhood/caldoria/caldoriamirror.cpp
@@ -0,0 +1,135 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/neighborhood/neighborhood.h"
+#include "pegasus/neighborhood/caldoria/caldoria.h"
+#include "pegasus/neighborhood/caldoria/caldoriamirror.h"
+
+namespace Pegasus {
+
+CaldoriaMirror::CaldoriaMirror(Neighborhood *owner) : GameInteraction(kCaldoriaMirrorInteractionID, owner) {
+}
+
+void CaldoriaMirror::openInteraction() {
+ _neighborhoodNotification = _owner->getNeighborhoodNotification();
+ _neighborhoodNotification->notifyMe(this, kExtraCompletedFlag, kExtraCompletedFlag);
+}
+
+void CaldoriaMirror::initInteraction() {
+ _owner->setCurrentActivation(kActivateMirrorReady);
+ _owner->startExtraSequence(kCaBathroomGreeting, kExtraCompletedFlag, kFilterNoInput);
+}
+
+void CaldoriaMirror::closeInteraction() {
+ _neighborhoodNotification->cancelNotification(this);
+}
+
+void CaldoriaMirror::handleInput(const Input &input, const Hotspot *cursorSpot) {
+ if (_owner->getLastExtra() == (uint32)kCaBathroomAgencyStandard || !input.anyDirectionInput())
+ GameInteraction::handleInput(input, cursorSpot);
+}
+
+void CaldoriaMirror::activateHotspots() {
+ GameInteraction::activateHotspots();
+
+ switch (_owner->getLastExtra()) {
+ case kCaBathroomGreeting:
+ case kCaBathroomBodyFat:
+ case kCaBathroomRetrothrash:
+ case kCaBathroomGeoWave:
+ g_allHotspots.activateOneHotspot(kCaBathroomMirrorSpotID);
+ g_allHotspots.deactivateOneHotspot(kCaHairStyle1SpotID);
+ g_allHotspots.deactivateOneHotspot(kCaHairStyle2SpotID);
+ g_allHotspots.deactivateOneHotspot(kCaHairStyle3SpotID);
+ break;
+ case kCaBathroomStylistIntro:
+ case kCaBathroomRetrothrashReturn:
+ case kCaBathroomGeoWaveReturn:
+ g_allHotspots.activateOneHotspot(kCaHairStyle1SpotID);
+ g_allHotspots.activateOneHotspot(kCaHairStyle2SpotID);
+ g_allHotspots.activateOneHotspot(kCaHairStyle3SpotID);
+ g_allHotspots.deactivateOneHotspot(kCaBathroomMirrorSpotID);
+ break;
+ }
+}
+
+void CaldoriaMirror::clickInHotspot(const Input &input, const Hotspot *spot) {
+ switch (spot->getObjectID()) {
+ case kCaBathroomMirrorSpotID:
+ switch (_owner->getLastExtra()) {
+ case kCaBathroomGreeting:
+ _owner->startExtraSequence(kCaBathroomBodyFat, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kCaBathroomBodyFat:
+ _owner->startExtraSequence(kCaBathroomStylistIntro, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kCaBathroomRetrothrash:
+ _owner->startExtraSequence(kCaBathroomRetrothrashReturn, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kCaBathroomGeoWave:
+ _owner->startExtraSequence(kCaBathroomGeoWaveReturn, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ }
+ break;
+ case kCaHairStyle1SpotID:
+ _owner->startExtraSequence(kCaBathroomRetrothrash, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kCaHairStyle2SpotID:
+ _owner->startExtraSequence(kCaBathroomAgencyStandard, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kCaHairStyle3SpotID:
+ _owner->startExtraSequence(kCaBathroomGeoWave, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ default:
+ GameInteraction::clickInHotspot(input, spot);
+ break;
+ }
+}
+
+void CaldoriaMirror::receiveNotification(Notification *, const NotificationFlags) {
+ switch (_owner->getLastExtra()) {
+ case kCaBathroomRetrothrash:
+ case kCaBathroomGeoWave:
+ _owner->setCurrentActivation(kActivateMirrorReady);
+ break;
+ case kCaBathroomStylistIntro:
+ case kCaBathroomRetrothrashReturn:
+ case kCaBathroomGeoWaveReturn:
+ _owner->setCurrentActivation(kActivateStylistReady);
+ break;
+ case kCaBathroomAgencyStandard:
+ _owner->setCurrentActivation(kActivateHotSpotAlways);
+ _owner->requestDeleteCurrentInteraction();
+ GameState.setScoringFixedHair(true);
+ GameState.setCaldoriaDoneHygiene(true);
+ break;
+ }
+
+ allowInput(true);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/caldoria/caldoriamirror.h b/engines/pegasus/neighborhood/caldoria/caldoriamirror.h
new file mode 100644
index 0000000000..1ca47ec774
--- /dev/null
+++ b/engines/pegasus/neighborhood/caldoria/caldoriamirror.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_CALDORIA_CALDORIAMIRROR_H
+#define PEGASUS_NEIGHBORHOOD_CALDORIA_CALDORIAMIRROR_H
+
+#include "pegasus/interaction.h"
+#include "pegasus/notification.h"
+
+namespace Pegasus {
+
+class CaldoriaMirror : public GameInteraction, public NotificationReceiver {
+public:
+ CaldoriaMirror(Neighborhood *);
+ virtual ~CaldoriaMirror() {}
+
+protected:
+ void openInteraction();
+ void initInteraction();
+ void closeInteraction();
+
+ void handleInput(const Input &, const Hotspot *);
+ void activateHotspots();
+ void clickInHotspot(const Input &, const Hotspot *);
+ void receiveNotification(Notification *, const NotificationFlags);
+
+ Notification *_neighborhoodNotification;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/door.cpp b/engines/pegasus/neighborhood/door.cpp
new file mode 100644
index 0000000000..f7ec7559fc
--- /dev/null
+++ b/engines/pegasus/neighborhood/door.cpp
@@ -0,0 +1,64 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/textconsole.h"
+
+#include "pegasus/neighborhood/door.h"
+
+namespace Pegasus {
+
+void DoorTable::loadFromStream(Common::SeekableReadStream *stream) {
+ uint32 count = stream->readUint32BE();
+ _entries.resize(count);
+
+ for (uint32 i = 0; i < count; i++) {
+ _entries[i].room = stream->readUint16BE();
+ _entries[i].direction = stream->readByte();
+ _entries[i].altCode = stream->readByte();
+ _entries[i].movieStart = stream->readUint32BE();
+ _entries[i].movieEnd = stream->readUint32BE();
+ _entries[i].flags = stream->readByte();
+ stream->readByte(); // alignment
+ debug(0, "Door[%d]: %d %d %d %d %d %d", i, _entries[i].room, _entries[i].direction,
+ _entries[i].altCode, _entries[i].movieStart, _entries[i].movieEnd,
+ _entries[i].flags);
+ }
+}
+
+void DoorTable::clear() {
+ _entries.clear();
+}
+
+DoorTable::Entry DoorTable::findEntry(RoomID room, DirectionConstant direction, AlternateID altCode) {
+ for (uint32 i = 0; i < _entries.size(); i++)
+ if (_entries[i].room == room && _entries[i].direction == direction && _entries[i].altCode == altCode)
+ return _entries[i];
+
+ return Entry();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/door.h b/engines/pegasus/neighborhood/door.h
new file mode 100644
index 0000000000..8ea757559a
--- /dev/null
+++ b/engines/pegasus/neighborhood/door.h
@@ -0,0 +1,90 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_DOOR_H
+#define PEGASUS_NEIGHBORHOOD_DOOR_H
+
+#include "common/array.h"
+#include "common/endian.h"
+
+#include "pegasus/constants.h"
+
+namespace Common {
+ class SeekableReadStream;
+}
+
+namespace Pegasus {
+
+typedef byte DoorFlags;
+
+enum {
+ kDoorPresentBit, // Bit set if there is a door here.
+ kDoorLockedBit // Bit set if door is locked, clear if unlocked.
+};
+
+static const DoorFlags kNoDoorFlags = 0;
+static const DoorFlags kDoorPresentMask = 1 << kDoorPresentBit;
+static const DoorFlags kDoorLockedMask = 1 << kDoorLockedBit;
+
+class DoorTable {
+public:
+ DoorTable() {}
+ ~DoorTable() {}
+
+ static uint32 getResTag() { return MKTAG('D', 'o', 'o', 'r'); }
+
+ void loadFromStream(Common::SeekableReadStream *stream);
+ void clear();
+
+ struct Entry {
+ Entry() { clear(); }
+ bool isEmpty() { return movieStart == 0xffffffff; }
+ void clear() {
+ room = kNoRoomID;
+ direction = kNoDirection;
+ altCode = kNoAlternateID;
+ movieStart = 0xffffffff;
+ movieEnd = 0xffffffff;
+ flags = kNoDoorFlags;
+ }
+
+ RoomID room;
+ DirectionConstant direction;
+ AlternateID altCode;
+ TimeValue movieStart;
+ TimeValue movieEnd;
+ DoorFlags flags;
+ };
+
+ Entry findEntry(RoomID room, DirectionConstant direction, AlternateID altCode);
+
+private:
+ Common::Array<Entry> _entries;
+};
+
+} // End of namespace Pegasus
+
+#endif
+
diff --git a/engines/pegasus/neighborhood/exit.cpp b/engines/pegasus/neighborhood/exit.cpp
new file mode 100644
index 0000000000..f0dfff12d3
--- /dev/null
+++ b/engines/pegasus/neighborhood/exit.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/textconsole.h"
+
+#include "pegasus/neighborhood/exit.h"
+
+namespace Pegasus {
+
+void ExitTable::loadFromStream(Common::SeekableReadStream *stream) {
+ uint32 count = stream->readUint32BE();
+ _entries.resize(count);
+
+ for (uint32 i = 0; i < count; i++) {
+ _entries[i].room = stream->readUint16BE();
+ _entries[i].direction = stream->readByte();
+ _entries[i].altCode = stream->readByte();
+ _entries[i].movieStart = stream->readUint32BE();
+ _entries[i].movieEnd = stream->readUint32BE();
+ _entries[i].exitEnd = stream->readUint32BE();
+ _entries[i].exitLoop = stream->readUint32BE();
+ _entries[i].exitRoom = stream->readUint16BE();
+ _entries[i].exitDirection = stream->readByte();
+ stream->readByte(); // alignment
+
+ _entries[i].originalEnd = _entries[i].exitEnd;
+
+ debug(0, "Exit[%d]: %d %d %d %d %d %d %d %d %d", i, _entries[i].room, _entries[i].direction,
+ _entries[i].altCode, _entries[i].movieStart, _entries[i].movieEnd, _entries[i].exitEnd,
+ _entries[i].exitLoop, _entries[i].exitRoom, _entries[i].exitDirection);
+ }
+}
+
+void ExitTable::clear() {
+ _entries.clear();
+}
+
+ExitTable::Entry ExitTable::findEntry(RoomID room, DirectionConstant direction, AlternateID altCode) {
+ for (uint32 i = 0; i < _entries.size(); i++)
+ if (_entries[i].room == room && _entries[i].direction == direction && _entries[i].altCode == altCode)
+ return _entries[i];
+
+ return Entry();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/exit.h b/engines/pegasus/neighborhood/exit.h
new file mode 100644
index 0000000000..17150892f9
--- /dev/null
+++ b/engines/pegasus/neighborhood/exit.h
@@ -0,0 +1,93 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_EXIT_H
+#define PEGASUS_NEIGHBORHOOD_EXIT_H
+
+#include "common/array.h"
+#include "common/endian.h"
+
+#include "pegasus/constants.h"
+
+namespace Common {
+ class SeekableReadStream;
+}
+
+namespace Pegasus {
+
+class ExitTable {
+public:
+ ExitTable() {}
+ ~ExitTable() {}
+
+ static uint32 getResTag() { return MKTAG('E', 'x', 'i', 't'); }
+
+ void loadFromStream(Common::SeekableReadStream *stream);
+ void clear();
+
+ struct Entry {
+ Entry() { clear(); }
+ bool isEmpty() { return movieStart == 0xffffffff; }
+ void clear() {
+ room = kNoRoomID;
+ direction = kNoDirection;
+ altCode = kNoAlternateID;
+ movieStart = 0xffffffff;
+ movieEnd = 0xffffffff;
+ exitEnd = 0xffffffff;
+ originalEnd = 0xffffffff;
+ exitLoop = 0xffffffff;
+ exitRoom = kNoRoomID;
+ exitDirection = kNoDirection;
+ }
+
+ RoomID room;
+ DirectionConstant direction;
+ AlternateID altCode;
+ TimeValue movieStart;
+ TimeValue movieEnd;
+ // exitEnd is the end of the optimized run of walks.
+ TimeValue exitEnd;
+ TimeValue originalEnd;
+ // exitLoop is the loop start time of the optimized run of walks if the run
+ // loops back on itself (so far, only in TSA).
+ TimeValue exitLoop;
+ RoomID exitRoom;
+ DirectionConstant exitDirection;
+ };
+
+ Entry findEntry(RoomID room, DirectionConstant direction, AlternateID altCode);
+
+ typedef Common::Array<Entry>::iterator iterator;
+ iterator begin() { return _entries.begin(); }
+ iterator end() { return _entries.end(); }
+
+private:
+ Common::Array<Entry> _entries;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/extra.cpp b/engines/pegasus/neighborhood/extra.cpp
new file mode 100644
index 0000000000..b8c4e5b510
--- /dev/null
+++ b/engines/pegasus/neighborhood/extra.cpp
@@ -0,0 +1,58 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/textconsole.h"
+
+#include "pegasus/neighborhood/extra.h"
+
+namespace Pegasus {
+
+void ExtraTable::loadFromStream(Common::SeekableReadStream *stream) {
+ uint32 count = stream->readUint32BE();
+ _entries.resize(count);
+
+ for (uint32 i = 0; i < count; i++) {
+ _entries[i].extra = stream->readUint32BE();
+ _entries[i].movieStart = stream->readUint32BE();
+ _entries[i].movieEnd = stream->readUint32BE();
+ debug(0, "Extra[%d]: %d %d %d", i, _entries[i].extra, _entries[i].movieStart, _entries[i].movieEnd);
+ }
+}
+
+void ExtraTable::clear() {
+ _entries.clear();
+}
+
+ExtraTable::Entry ExtraTable::findEntry(ExtraID extra) {
+ for (uint32 i = 0; i < _entries.size(); i++)
+ if (_entries[i].extra == extra)
+ return _entries[i];
+
+ return Entry();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/extra.h b/engines/pegasus/neighborhood/extra.h
new file mode 100644
index 0000000000..14fcff1009
--- /dev/null
+++ b/engines/pegasus/neighborhood/extra.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_EXTRA_H
+#define PEGASUS_NEIGHBORHOOD_EXTRA_H
+
+#include "common/array.h"
+#include "common/endian.h"
+
+#include "pegasus/constants.h"
+
+namespace Common {
+ class SeekableReadStream;
+}
+
+namespace Pegasus {
+
+class ExtraTable {
+public:
+ ExtraTable() {}
+ ~ExtraTable() {}
+
+ static uint32 getResTag() { return MKTAG('X', 't', 'r', 'a'); }
+
+ void loadFromStream(Common::SeekableReadStream *stream);
+ void clear();
+
+ struct Entry {
+ Entry() { movieStart = 0xffffffff; }
+ bool isEmpty() { return movieStart == 0xffffffff; }
+
+ ExtraID extra;
+ TimeValue movieStart;
+ TimeValue movieEnd;
+ };
+
+ Entry findEntry(ExtraID extra);
+
+private:
+ Common::Array<Entry> _entries;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/hotspotinfo.cpp b/engines/pegasus/neighborhood/hotspotinfo.cpp
new file mode 100644
index 0000000000..c7524f3a0f
--- /dev/null
+++ b/engines/pegasus/neighborhood/hotspotinfo.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/textconsole.h"
+
+#include "pegasus/neighborhood/hotspotinfo.h"
+
+namespace Pegasus {
+
+void HotspotInfoTable::loadFromStream(Common::SeekableReadStream *stream) {
+ uint32 count = stream->readUint32BE();
+ _entries.resize(count);
+
+ for (uint32 i = 0; i < count; i++) {
+ _entries[i].hotspot = stream->readUint16BE();
+ _entries[i].hotspotActivation = stream->readSByte();
+ stream->readByte(); // alignment
+ _entries[i].hotspotRoom = stream->readUint16BE();
+ _entries[i].hotspotDirection = stream->readByte();
+ stream->readByte(); // alignment
+ _entries[i].hotspotExtra = stream->readUint32BE();
+ _entries[i].hotspotItem = stream->readUint16BE();
+ debug(0, "Hotspot[%d]: %d %d %d %d %d %d", i, _entries[i].hotspot, _entries[i].hotspotActivation,
+ _entries[i].hotspotRoom, _entries[i].hotspotDirection, _entries[i].hotspotExtra,
+ _entries[i].hotspotItem);
+ }
+}
+
+void HotspotInfoTable::clear() {
+ _entries.clear();
+}
+
+HotspotInfoTable::Entry HotspotInfoTable::findEntry(HotSpotID hotspot) {
+ for (uint32 i = 0; i < _entries.size(); i++)
+ if (_entries[i].hotspot == hotspot)
+ return _entries[i];
+
+ return Entry();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/hotspotinfo.h b/engines/pegasus/neighborhood/hotspotinfo.h
new file mode 100644
index 0000000000..965f445ba8
--- /dev/null
+++ b/engines/pegasus/neighborhood/hotspotinfo.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_HOTSPOTINFO_H
+#define PEGASUS_NEIGHBORHOOD_HOTSPOTINFO_H
+
+#include "common/array.h"
+#include "common/endian.h"
+
+#include "pegasus/constants.h"
+
+namespace Common {
+ class SeekableReadStream;
+}
+
+namespace Pegasus {
+
+class HotspotInfoTable {
+public:
+ HotspotInfoTable() {}
+ ~HotspotInfoTable() {}
+
+ static uint32 getResTag() { return MKTAG('H', 'S', 'I', 'n'); }
+
+ void loadFromStream(Common::SeekableReadStream *stream);
+ void clear();
+
+ struct Entry {
+ Entry() { hotspotRoom = kNoRoomID; }
+ bool isEmpty() { return hotspotRoom == kNoRoomID; }
+
+ HotSpotID hotspot;
+ HotSpotActivationID hotspotActivation;
+ // Location hot spot lives in:
+ RoomID hotspotRoom;
+ DirectionConstant hotspotDirection;
+ // Extra to play if this is a "play extra" hot spot.
+ ExtraID hotspotExtra;
+ // Item corresponding to this hot spot if it is an item-related hot spot.
+ ItemID hotspotItem;
+ };
+
+ Entry findEntry(HotSpotID hotspot);
+
+ typedef Common::Array<Entry>::iterator iterator;
+ iterator begin() { return _entries.begin(); }
+ iterator end() { return _entries.end(); }
+
+private:
+ Common::Array<Entry> _entries;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/mars/constants.h b/engines/pegasus/neighborhood/mars/constants.h
new file mode 100644
index 0000000000..82a7f03b68
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/constants.h
@@ -0,0 +1,941 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_MARS_CONSTANTS_H
+#define PEGASUS_NEIGHBORHOOD_MARS_CONSTANTS_H
+
+#include "pegasus/constants.h"
+
+namespace Pegasus {
+
+// Element Coordinates
+
+static const CoordType kUndoHiliteLeft = kNavAreaLeft + 140;
+static const CoordType kUndoHiliteTop = kNavAreaTop + 36;
+
+static const CoordType kCurrentGuessLeft = kNavAreaLeft + 146;
+static const CoordType kCurrentGuessTop = kNavAreaTop + 90;
+
+static const CoordType kReactorChoiceHiliteLeft = kNavAreaLeft + 116;
+static const CoordType kReactorChoiceHiliteTop = kNavAreaTop + 158;
+
+static const CoordType kReactorHistoryLeft = kNavAreaLeft + 302;
+static const CoordType kReactorHistoryTop = kNavAreaTop + 39;
+
+static const CoordType kAnswerLeft = kNavAreaLeft + 304;
+static const CoordType kAnswerTop = kNavAreaTop + 180;
+
+static const CoordType kShuttle1Left = 0;
+static const CoordType kShuttle1Top = 0;
+
+static const CoordType kShuttle2Left = 0;
+static const CoordType kShuttle2Top = 96;
+
+static const CoordType kShuttle3Left = 500;
+static const CoordType kShuttle3Top = 96;
+
+static const CoordType kShuttle4Left = 0;
+static const CoordType kShuttle4Top = 320;
+
+static const CoordType kShuttleWindowLeft = 140;
+static const CoordType kShuttleWindowTop = 96;
+static const CoordType kShuttleWindowWidth = 360;
+static const CoordType kShuttleWindowHeight = 224;
+
+static const CoordType kShuttleWindowMidH = (kShuttleWindowLeft * 2 + kShuttleWindowWidth) / 2;
+static const CoordType kShuttleWindowMidV = (kShuttleWindowTop * 2 + kShuttleWindowHeight) / 2;
+
+static const CoordType kShuttleLeftLeft = 0;
+static const CoordType kShuttleLeftTop = 128;
+
+static const CoordType kShuttleRightLeft = 506;
+static const CoordType kShuttleRightTop = 128;
+
+static const CoordType kShuttleLowerLeftLeft = 74;
+static const CoordType kShuttleLowerLeftTop = 358;
+
+static const CoordType kShuttleLowerRightLeft = 486;
+static const CoordType kShuttleLowerRightTop = 354;
+
+static const CoordType kShuttleCenterLeft = 260;
+static const CoordType kShuttleCenterTop = 336;
+
+static const CoordType kShuttleUpperLeftLeft = 30;
+static const CoordType kShuttleUpperLeftTop = 32;
+
+static const CoordType kShuttleUpperRightLeft = 506;
+static const CoordType kShuttleUpperRightTop = 52;
+
+static const CoordType kShuttleLeftEnergyLeft = 110;
+static const CoordType kShuttleLeftEnergyTop = 186;
+
+static const CoordType kShuttleRightEnergyLeft = 510;
+static const CoordType kShuttleRightEnergyTop = 186;
+
+static const CoordType kShuttleEnergyLeft = 186;
+static const CoordType kShuttleEnergyTop = 60;
+static const CoordType kShuttleEnergyWidth = 252;
+static const CoordType kShuttleEnergyHeight = 22;
+
+static const CoordType kPlanetStartLeft = kShuttleWindowLeft;
+static const CoordType kPlanetStartTop = kShuttleWindowTop + kShuttleWindowHeight;
+
+static const CoordType kPlanetStopLeft = kShuttleWindowLeft;
+static const CoordType kPlanetStopTop = kShuttleWindowTop + kShuttleWindowHeight - 100;
+
+static const CoordType kShuttleTractorLeft = kShuttleWindowLeft + 6;
+static const CoordType kShuttleTractorTop = kShuttleWindowTop + 56;
+static const CoordType kShuttleTractorWidth = 348;
+static const CoordType kShuttleTractorHeight = 112;
+
+static const CoordType kShuttleJunkLeft = kShuttleWindowLeft + 6;
+static const CoordType kShuttleJunkTop = kShuttleWindowTop + 6;
+
+static const DisplayOrder kShuttlePlanetOrder = kInterfaceLayer;
+static const DisplayOrder kShuttleAlienShipOrder = kShuttlePlanetOrder + 1;
+static const DisplayOrder kShuttleRobotShipOrder = kShuttleAlienShipOrder + 1;
+static const DisplayOrder kShuttleTractorBeamMovieOrder = kShuttleRobotShipOrder + 1;
+static const DisplayOrder kShuttleWeaponBackOrder = kShuttleTractorBeamMovieOrder + 1;
+static const DisplayOrder kShuttleJunkOrder = kShuttleWeaponBackOrder + 1;
+static const DisplayOrder kShuttleWeaponFrontOrder = kShuttleJunkOrder + 1;
+static const DisplayOrder kShuttleTractorBeamOrder = kShuttleWeaponFrontOrder + 1;
+static const DisplayOrder kShuttleHUDOrder = kShuttleTractorBeamOrder + 1;
+static const DisplayOrder kShuttleBackgroundOrder = kShuttleHUDOrder + 1;
+static const DisplayOrder kShuttleMonitorOrder = kShuttleBackgroundOrder + 1;
+static const DisplayOrder kShuttleStatusOrder = kShuttleMonitorOrder + 1;
+
+static const TimeValue kShuttleSwingStart = 0;
+static const TimeValue kShuttleSwingStop = 5 * 600;
+
+static const TimeValue kCanyonChaseStart = kShuttleSwingStop;
+static const TimeValue kCanyonChaseStop = 60 * 600 + 43 * 600 + 14 * 40;
+
+static const TimeValue kLaunchTubeReachedTime = 60 * 600 + 38 * 600 - kCanyonChaseStart;
+static const TimeValue kCanyonChaseFinishedTime = kCanyonChaseStop - kCanyonChaseStart -
+ kLaunchTubeReachedTime;
+
+// Left shuttle.
+
+static const TimeValue kShuttleLeftIntroStart = 0;
+static const TimeValue kShuttleLeftIntroStop = 400;
+
+static const TimeValue kShuttleLeftBlankTime = 400;
+
+static const TimeValue kShuttleLeftNormalTime = 440;
+
+static const TimeValue kShuttleLeftAutoTestTime = 480;
+
+static const TimeValue kShuttleLeftDamagedTime = 520;
+
+static const TimeValue kShuttleLeftDampingTime = 560;
+
+static const TimeValue kShuttleLeftGravitonTime = 600;
+
+static const TimeValue kShuttleLeftTractorTime = 640;
+
+// Right shuttle.
+
+static const TimeValue kShuttleRightIntroStart = 0;
+static const TimeValue kShuttleRightIntroStop = 400;
+
+static const TimeValue kShuttleRightDestroyedStart = 400;
+static const TimeValue kShuttleRightDestroyedStop = 840;
+
+static const TimeValue kShuttleRightBlankTime = 840;
+
+static const TimeValue kShuttleRightNormalTime = 880;
+
+static const TimeValue kShuttleRightDamagedTime = 920;
+
+static const TimeValue kShuttleRightTargetLockTime = 960;
+
+static const TimeValue kShuttleRightGravitonTime = 1000;
+
+static const TimeValue kShuttleRightOverloadTime = 1040;
+
+// Lower Left shuttle.
+
+static const TimeValue kShuttleLowerLeftCollisionTime = 0;
+
+static const TimeValue kShuttleLowerLeftTubeTime = 40;
+
+static const TimeValue kShuttleLowerLeftAutopilotTime = 80;
+
+// Lower Right shuttle.
+
+static const TimeValue kShuttleLowerRightOffTime = 0;
+
+static const TimeValue kShuttleLowerRightTrackingTime = 40;
+
+static const TimeValue kShuttleLowerRightTransportTime = 80;
+
+static const TimeValue kShuttleLowerRightTransportHiliteTime = 120;
+
+// Center shuttle.
+
+static const TimeValue kShuttleCenterBoardingTime = 0;
+
+static const TimeValue kShuttleCenterCheckTime = 40;
+
+static const TimeValue kShuttleCenterNavCompTime = 80;
+
+static const TimeValue kShuttleCenterCommTime = 120;
+
+static const TimeValue kShuttleCenterWeaponsTime = 160;
+
+static const TimeValue kShuttleCenterAllSystemsTime = 200;
+
+static const TimeValue kShuttleCenterSecureLooseTime = 240;
+
+static const TimeValue kShuttleCenterAutoTestTime = 280;
+
+static const TimeValue kShuttleCenterLaunchTime = 320;
+
+static const TimeValue kShuttleCenterEnterTubeTime = 360;
+
+static const TimeValue kShuttleCenterTargetSightedTime = 400;
+
+static const TimeValue kShuttleCenterVerifyingTime = 440;
+
+static const TimeValue kShuttleCenterScanningTime = 480;
+
+static const TimeValue kShuttleCenterSafeTime = 520;
+
+// Upper Left shuttle.
+
+static const TimeValue kShuttleUpperLeftDimTime = 0;
+
+static const TimeValue kShuttleUpperLeftDampingTime = 40;
+
+static const TimeValue kShuttleUpperLeftGravitonTime = 80;
+
+static const TimeValue kShuttleUpperLeftTractorTime = 120;
+
+// Upper Right shuttle.
+
+static const TimeValue kShuttleUpperRightLockedTime = 0;
+
+static const TimeValue kShuttleUpperRightArmedTime = 40;
+
+static const TimeValue kShuttleUpperRightAlienDestroyedTime = 80;
+
+static const TimeValue kShuttleUpperRightOverloadTime = 120;
+
+static const TimeValue kShuttleUpperRightTargetDestroyedTime = 160;
+
+// Shuttle distance
+
+static const int kShuttleDistance = 500;
+
+static const int kJunkMaxDistance = kShuttleDistance;
+static const int kJunkMinDistance = 40;
+
+static const int kEnergyBeamMaxDistance = kShuttleDistance;
+static const int kEnergyBeamMinDistance = 40;
+
+static const int kGravitonMaxDistance = kShuttleDistance;
+static const int kGravitonMinDistance = 40;
+
+static const TimeValue kMarsOxyMaskOnIn = 0;
+static const TimeValue kMarsOxyMaskOnOut = 1560;
+
+static const TimeValue kMarsAirlockButtonBeepIn = 1560;
+static const TimeValue kMarsAirlockButtonBeepOut = 1620;
+
+static const TimeValue kMarsColorMatchingButtonBeepIn = 1620;
+static const TimeValue kMarsColorMatchingButtonBeepOut = 1680;
+
+static const TimeValue kMarsKioskBeepIn = 1680;
+static const TimeValue kMarsKioskBeepOut = 1740;
+
+static const TimeValue kMarsBumpIntoWallIn = 1740;
+static const TimeValue kMarsBumpIntoWallOut = 1888;
+
+static const TimeValue kMarsGantryDoorCloseIn = 1888;
+static const TimeValue kMarsGantryDoorCloseOut = 2866;
+
+static const TimeValue kMarsTransportDoorCloseIn = 2866;
+static const TimeValue kMarsTransportDoorCloseOut = 3593;
+
+static const TimeValue kMarsAirlockPressurizeIn = 3593;
+static const TimeValue kMarsAirlockPressurizeOut = 4766;
+
+static const TimeValue kMarsBigAirlockDoorCloseIn = 4766;
+static const TimeValue kMarsBigAirlockDoorCloseOut = 7872;
+
+static const TimeValue kMarsSmallAirlockDoorCloseIn = 7872;
+static const TimeValue kMarsSmallAirlockDoorCloseOut = 10000;
+
+static const TimeValue kMarsMazeDoorCloseIn = 10000;
+static const TimeValue kMarsMazeDoorCloseOut = 10969;
+
+static const TimeValue kMarsRobotTakesTransportIn = 10969;
+static const TimeValue kMarsRobotTakesTransportOut = 12802;
+
+static const TimeValue kMarsPodDepartedUpperPlatformIn = 12802;
+static const TimeValue kMarsPodDepartedUpperPlatformOut = 15783;
+
+static const TimeValue kMarsPodDepartedLowerPlatformIn = 15783;
+static const TimeValue kMarsPodDepartedLowerPlatformOut = 18736;
+
+static const TimeValue kMarsPodArrivedUpperPlatformIn = 18736;
+static const TimeValue kMarsPodArrivedUpperPlatformOut = 21605;
+
+static const TimeValue kMarsCheckInRequiredIn = 21605;
+static const TimeValue kMarsCheckInRequiredOut = 27463;
+
+static const TimeValue kMarsCantOpenShuttleIn = 27463;
+static const TimeValue kMarsCantOpenShuttleOut = 29214;
+
+static const TimeValue kMarsShuttleLockOverrideIn = 29214;
+static const TimeValue kMarsShuttleLockOverrideOut = 30330;
+
+static const TimeValue kMarsNoShuttleIn = 30330;
+static const TimeValue kMarsNoShuttleOut = 31502;
+
+static const TimeValue kMustBeUnlockedIn = 31502;
+static const TimeValue kMustBeUnlockedOut = 33960;
+
+static const TimeValue kColorMatchBlueIn = 33960;
+static const TimeValue kColorMatchBlueOut = 34240;
+
+static const TimeValue kColorMatchRedIn = 34240;
+static const TimeValue kColorMatchRedOut = 34538;
+
+static const TimeValue kColorMatchGreenIn = 34538;
+static const TimeValue kColorMatchGreenOut = 34827;
+
+static const TimeValue kColorMatchYellowIn = 34827;
+static const TimeValue kColorMatchYellowOut = 35162;
+
+static const TimeValue kColorMatchPurpleIn = 35162;
+static const TimeValue kColorMatchPurpleOut = 35426;
+
+static const TimeValue kColorMatchZeroNodesIn = 35426;
+static const TimeValue kColorMatchZeroNodesOut = 36376;
+
+static const TimeValue kColorMatchOneNodeIn = 36376;
+static const TimeValue kColorMatchOneNodeOut = 37209;
+
+static const TimeValue kColorMatchTwoNodesIn = 37209;
+static const TimeValue kColorMatchTwoNodesOut = 37983;
+
+static const TimeValue kColorMatchThreeNodesIn = 37983;
+static const TimeValue kColorMatchThreeNodesOut = 38784;
+
+static const TimeValue kMarsShuttle1DepartedIn = 38784;
+static const TimeValue kMarsShuttle1DepartedOut = 40323;
+
+static const TimeValue kMarsShuttle2DepartedIn = 40323;
+static const TimeValue kMarsShuttle2DepartedOut = 41824;
+
+static const TimeValue kShuttleCockpitIn = 41824;
+static const TimeValue kShuttleCockpitOut = 43126;
+
+static const TimeValue kShuttleOnboardIn = 43126;
+static const TimeValue kShuttleOnboardOut = 44284;
+
+static const TimeValue kShuttleNavigationIn = 44284;
+static const TimeValue kShuttleNavigationOut = 46049;
+
+static const TimeValue kShuttleCommunicationIn = 46049;
+static const TimeValue kShuttleCommunicationOut = 47288;
+
+static const TimeValue kShuttleAutoTestingIn = 47288;
+static const TimeValue kShuttleAutoTestingOut = 48179;
+
+static const TimeValue kMarsThrusterAutoTestIn = 48179;
+static const TimeValue kMarsThrusterAutoTestOut = 49979;
+
+static const TimeValue kShuttleAllSystemsIn = 49979;
+static const TimeValue kShuttleAllSystemsOut = 51065;
+
+static const TimeValue kShuttleSecureLooseIn = 51065;
+static const TimeValue kShuttleSecureLooseOut = 52346;
+
+static const TimeValue kShuttlePrepareForDropIn = 52346;
+static const TimeValue kShuttlePrepareForDropOut = 53216;
+
+static const TimeValue kShuttleAllClearIn = 53216;
+static const TimeValue kShuttleAllClearOut = 54031;
+
+static const TimeValue kShuttleConfiguringIn = 54031;
+static const TimeValue kShuttleConfiguringOut = 54994;
+
+static const TimeValue kShuttleGeneratingIn = 54994;
+static const TimeValue kShuttleGeneratingOut = 56033;
+
+static const TimeValue kShuttleBreakawayIn = 56033;
+static const TimeValue kShuttleBreakawayOut = 57346;
+
+static const TimeValue kMarsAtmosphericBreakawayIn = 57346;
+static const TimeValue kMarsAtmosphericBreakawayOut = 59237;
+
+static const TimeValue kMarsCockpitChatterIn = 59237;
+static const TimeValue kMarsCockpitChatterOut = 70344;
+
+static const TimeValue kShuttleDamperDescIn = 70344;
+static const TimeValue kShuttleDamperDescOut = 73262;
+
+static const TimeValue kShuttleGravitonDescIn = 73262;
+static const TimeValue kShuttleGravitonDescOut = 75296;
+
+static const TimeValue kShuttleTractorDescIn = 75296;
+static const TimeValue kShuttleTractorDescOut = 78381;
+
+static const TimeValue kShuttleTargetSightedIn = 78381;
+static const TimeValue kShuttleTargetSightedOut = 79074;
+
+static const TimeValue kShuttleAutopilotEngagedIn = 79074;
+static const TimeValue kShuttleAutopilotEngagedOut = 80414;
+
+static const TimeValue kMarsEDBBlastIn = 80414;
+static const TimeValue kMarsEDBBlastOut = 80705;
+
+static const TimeValue kMarsGravitonBlastIn = 80705;
+static const TimeValue kMarsGravitonBlastOut = 81199;
+
+static const TimeValue kMarsJunkCollisionIn = 81199;
+static const TimeValue kMarsJunkCollisionOut = 81961;
+
+static const TimeValue kShuttleGravitonIn = 81961;
+static const TimeValue kShuttleGravitonOut = 82587;
+
+static const TimeValue kShuttleDampingBeamIn = 82587;
+static const TimeValue kShuttleDampingBeamOut = 83331;
+
+static const TimeValue kShuttleTractorBeamIn = 83331;
+static const TimeValue kShuttleTractorBeamOut = 83802;
+
+static const TimeValue kShuttleHullBreachIn = 83802;
+static const TimeValue kShuttleHullBreachOut = 84721;
+
+static const TimeValue kShuttleWingDamageIn = 84721;
+static const TimeValue kShuttleWingDamageOut = 85640;
+
+static const TimeValue kShuttleHullDamageIn = 85640;
+static const TimeValue kShuttleHullDamageOut = 86513;
+
+static const TimeValue kShuttleEnergyTooLowIn = 86513;
+static const TimeValue kShuttleEnergyTooLowOut = 87578;
+
+static const TimeValue kShuttleTractorLimitedIn = 87578;
+static const TimeValue kShuttleTractorLimitedOut = 89164;
+
+static const TimeValue kShuttleCantHoldIn = 89164;
+static const TimeValue kShuttleCantHoldOut = 90945;
+
+static const TimeValue kShuttleBrokeFreeIn = 90945;
+static const TimeValue kShuttleBrokeFreeOut = 92322;
+
+static const TimeValue kShuttleDestroyedIn = 92322;
+static const TimeValue kShuttleDestroyedOut = 93189;
+
+static const TimeValue kShuttleCoordinatesIn = 93189;
+static const TimeValue kShuttleCoordinatesOut = 94018;
+
+static const TimeValue kShuttleScanningIn = 94018;
+static const TimeValue kShuttleScanningOut = 94975;
+
+static const TimeValue kShuttleSafeIn = 94975;
+static const TimeValue kShuttleSafeOut = 96176;
+
+static const TimeValue kShuttleOverloadedIn = 96176;
+static const TimeValue kShuttleOverloadedOut = 101308;
+
+static const TimeScale kMarsMovieScale = 600;
+static const TimeScale kMarsFramesPerSecond = 15;
+static const TimeScale kMarsFrameDuration = 40;
+
+// Alternate IDs.
+
+static const AlternateID kAltMarsNormal = 0;
+static const AlternateID kAltMarsPodAtMars34 = 1;
+static const AlternateID kAltMarsTookCard = 2;
+static const AlternateID kAltMars35AirlockEast = 3;
+static const AlternateID kAltMars35AirlockWest = 4;
+static const AlternateID kAltMarsPodAtMars45 = 5;
+static const AlternateID kAltMarsTookMask = 6;
+static const AlternateID kAltMarsMaskOnFiller = 7;
+static const AlternateID kAltMars60AirlockEast = 8;
+static const AlternateID kAltMars60AirlockWest = 9;
+
+// Room IDs.
+
+static const RoomID kMars0A = 0;
+static const RoomID kMars00 = 1;
+static const RoomID kMars01 = 2;
+static const RoomID kMars02 = 3;
+static const RoomID kMars03 = 4;
+static const RoomID kMars04 = 5;
+static const RoomID kMars05 = 6;
+static const RoomID kMars06 = 7;
+static const RoomID kMars07 = 8;
+static const RoomID kMars08 = 9;
+static const RoomID kMars09 = 10;
+static const RoomID kMars10 = 11;
+static const RoomID kMars11 = 12;
+static const RoomID kMars12 = 13;
+static const RoomID kMars13 = 14;
+static const RoomID kMars14 = 15;
+static const RoomID kMars15 = 16;
+static const RoomID kMars16 = 17;
+static const RoomID kMars17 = 18;
+static const RoomID kMars18 = 19;
+static const RoomID kMars19 = 20;
+static const RoomID kMars20 = 21;
+static const RoomID kMars21 = 22;
+static const RoomID kMars22 = 23;
+static const RoomID kMars23 = 24;
+static const RoomID kMars24 = 25;
+static const RoomID kMars25 = 26;
+static const RoomID kMars26 = 27;
+static const RoomID kMars27 = 28;
+static const RoomID kMars28 = 29;
+static const RoomID kMars29 = 30;
+static const RoomID kMars30 = 31;
+static const RoomID kMars31 = 32;
+static const RoomID kMars31South = 33;
+static const RoomID kMars32 = 34;
+static const RoomID kMars33 = 35;
+static const RoomID kMars33North = 36;
+static const RoomID kMars34 = 37;
+static const RoomID kMars35 = 38;
+static const RoomID kMars36 = 39;
+static const RoomID kMars37 = 40;
+static const RoomID kMars38 = 41;
+static const RoomID kMars39 = 42;
+static const RoomID kMars41 = 43;
+static const RoomID kMars42 = 44;
+static const RoomID kMars43 = 45;
+static const RoomID kMars44 = 46;
+static const RoomID kMars45 = 47;
+static const RoomID kMars46 = 48;
+static const RoomID kMars47 = 49;
+static const RoomID kMars48 = 50;
+static const RoomID kMars49 = 51;
+static const RoomID kMars50 = 52;
+static const RoomID kMars51 = 53;
+static const RoomID kMars52 = 54;
+static const RoomID kMars54 = 55;
+static const RoomID kMars56 = 56;
+static const RoomID kMars58 = 57;
+static const RoomID kMars60 = 58;
+static const RoomID kMarsRobotShuttle = 59;
+static const RoomID kMarsMaze004 = 60;
+static const RoomID kMarsMaze005 = 61;
+static const RoomID kMarsMaze006 = 62;
+static const RoomID kMarsMaze007 = 63;
+static const RoomID kMarsMaze008 = 64;
+static const RoomID kMarsMaze009 = 65;
+static const RoomID kMarsMaze010 = 66;
+static const RoomID kMarsMaze011 = 67;
+static const RoomID kMarsMaze012 = 68;
+static const RoomID kMarsMaze015 = 69;
+static const RoomID kMarsMaze016 = 70;
+static const RoomID kMarsMaze017 = 71;
+static const RoomID kMarsMaze018 = 72;
+static const RoomID kMarsMaze019 = 73;
+static const RoomID kMarsMaze020 = 74;
+static const RoomID kMarsMaze021 = 75;
+static const RoomID kMarsMaze022 = 76;
+static const RoomID kMarsMaze023 = 77;
+static const RoomID kMarsMaze024 = 78;
+static const RoomID kMarsMaze025 = 79;
+static const RoomID kMarsMaze026 = 80;
+static const RoomID kMarsMaze027 = 81;
+static const RoomID kMarsMaze028 = 82;
+static const RoomID kMarsMaze031 = 83;
+static const RoomID kMarsMaze032 = 84;
+static const RoomID kMarsMaze033 = 85;
+static const RoomID kMarsMaze034 = 86;
+static const RoomID kMarsMaze035 = 87;
+static const RoomID kMarsMaze036 = 88;
+static const RoomID kMarsMaze037 = 89;
+static const RoomID kMarsMaze038 = 90;
+static const RoomID kMarsMaze039 = 91;
+static const RoomID kMarsMaze042 = 92;
+static const RoomID kMarsMaze043 = 93;
+static const RoomID kMarsMaze044 = 94;
+static const RoomID kMarsMaze045 = 95;
+static const RoomID kMarsMaze046 = 96;
+static const RoomID kMarsMaze047 = 97;
+static const RoomID kMarsMaze049 = 98;
+static const RoomID kMarsMaze050 = 99;
+static const RoomID kMarsMaze051 = 100;
+static const RoomID kMarsMaze052 = 101;
+static const RoomID kMarsMaze053 = 102;
+static const RoomID kMarsMaze054 = 103;
+static const RoomID kMarsMaze055 = 104;
+static const RoomID kMarsMaze056 = 105;
+static const RoomID kMarsMaze057 = 106;
+static const RoomID kMarsMaze058 = 107;
+static const RoomID kMarsMaze059 = 108;
+static const RoomID kMarsMaze060 = 109;
+static const RoomID kMarsMaze061 = 110;
+static const RoomID kMarsMaze063 = 111;
+static const RoomID kMarsMaze064 = 112;
+static const RoomID kMarsMaze065 = 113;
+static const RoomID kMarsMaze066 = 114;
+static const RoomID kMarsMaze067 = 115;
+static const RoomID kMarsMaze068 = 116;
+static const RoomID kMarsMaze069 = 117;
+static const RoomID kMarsMaze070 = 118;
+static const RoomID kMarsMaze071 = 119;
+static const RoomID kMarsMaze072 = 120;
+static const RoomID kMarsMaze074 = 121;
+static const RoomID kMarsMaze076 = 122;
+static const RoomID kMarsMaze078 = 123;
+static const RoomID kMarsMaze079 = 124;
+static const RoomID kMarsMaze081 = 125;
+static const RoomID kMarsMaze083 = 126;
+static const RoomID kMarsMaze084 = 127;
+static const RoomID kMarsMaze085 = 128;
+static const RoomID kMarsMaze086 = 129;
+static const RoomID kMarsMaze087 = 130;
+static const RoomID kMarsMaze088 = 131;
+static const RoomID kMarsMaze089 = 132;
+static const RoomID kMarsMaze090 = 133;
+static const RoomID kMarsMaze091 = 134;
+static const RoomID kMarsMaze092 = 135;
+static const RoomID kMarsMaze093 = 136;
+static const RoomID kMarsMaze098 = 137;
+static const RoomID kMarsMaze099 = 138;
+static const RoomID kMarsMaze100 = 139;
+static const RoomID kMarsMaze101 = 140;
+static const RoomID kMarsMaze104 = 141;
+static const RoomID kMarsMaze105 = 142;
+static const RoomID kMarsMaze106 = 143;
+static const RoomID kMarsMaze107 = 144;
+static const RoomID kMarsMaze108 = 145;
+static const RoomID kMarsMaze111 = 146;
+static const RoomID kMarsMaze113 = 147;
+static const RoomID kMarsMaze114 = 148;
+static const RoomID kMarsMaze115 = 149;
+static const RoomID kMarsMaze116 = 150;
+static const RoomID kMarsMaze117 = 151;
+static const RoomID kMarsMaze118 = 152;
+static const RoomID kMarsMaze119 = 153;
+static const RoomID kMarsMaze120 = 154;
+static const RoomID kMarsMaze121 = 155;
+static const RoomID kMarsMaze122 = 156;
+static const RoomID kMarsMaze123 = 157;
+static const RoomID kMarsMaze124 = 158;
+static const RoomID kMarsMaze125 = 159;
+static const RoomID kMarsMaze126 = 160;
+static const RoomID kMarsMaze127 = 161;
+static const RoomID kMarsMaze128 = 162;
+static const RoomID kMarsMaze129 = 163;
+static const RoomID kMarsMaze130 = 164;
+static const RoomID kMarsMaze131 = 165;
+static const RoomID kMarsMaze132 = 166;
+static const RoomID kMarsMaze133 = 167;
+static const RoomID kMarsMaze136 = 168;
+static const RoomID kMarsMaze137 = 169;
+static const RoomID kMarsMaze138 = 170;
+static const RoomID kMarsMaze139 = 171;
+static const RoomID kMarsMaze140 = 172;
+static const RoomID kMarsMaze141 = 173;
+static const RoomID kMarsMaze142 = 174;
+static const RoomID kMarsMaze143 = 175;
+static const RoomID kMarsMaze144 = 176;
+static const RoomID kMarsMaze145 = 177;
+static const RoomID kMarsMaze146 = 178;
+static const RoomID kMarsMaze147 = 179;
+static const RoomID kMarsMaze148 = 180;
+static const RoomID kMarsMaze149 = 181;
+static const RoomID kMarsMaze152 = 182;
+static const RoomID kMarsMaze153 = 183;
+static const RoomID kMarsMaze154 = 184;
+static const RoomID kMarsMaze155 = 185;
+static const RoomID kMarsMaze156 = 186;
+static const RoomID kMarsMaze157 = 187;
+static const RoomID kMarsMaze159 = 188;
+static const RoomID kMarsMaze160 = 189;
+static const RoomID kMarsMaze161 = 190;
+static const RoomID kMarsMaze162 = 191;
+static const RoomID kMarsMaze163 = 192;
+static const RoomID kMarsMaze164 = 193;
+static const RoomID kMarsMaze165 = 194;
+static const RoomID kMarsMaze166 = 195;
+static const RoomID kMarsMaze167 = 196;
+static const RoomID kMarsMaze168 = 197;
+static const RoomID kMarsMaze169 = 198;
+static const RoomID kMarsMaze170 = 199;
+static const RoomID kMarsMaze171 = 200;
+static const RoomID kMarsMaze172 = 201;
+static const RoomID kMarsMaze173 = 202;
+static const RoomID kMarsMaze174 = 203;
+static const RoomID kMarsMaze175 = 204;
+static const RoomID kMarsMaze177 = 205;
+static const RoomID kMarsMaze178 = 206;
+static const RoomID kMarsMaze179 = 207;
+static const RoomID kMarsMaze180 = 208;
+static const RoomID kMarsMaze181 = 209;
+static const RoomID kMarsMaze182 = 210;
+static const RoomID kMarsMaze183 = 211;
+static const RoomID kMarsMaze184 = 212;
+static const RoomID kMarsMaze187 = 213;
+static const RoomID kMarsMaze188 = 214;
+static const RoomID kMarsMaze189 = 215;
+static const RoomID kMarsMaze190 = 216;
+static const RoomID kMarsMaze191 = 217;
+static const RoomID kMarsMaze192 = 218;
+static const RoomID kMarsMaze193 = 219;
+static const RoomID kMarsMaze194 = 220;
+static const RoomID kMarsMaze195 = 221;
+static const RoomID kMarsMaze198 = 222;
+static const RoomID kMarsMaze199 = 223;
+static const RoomID kMarsMaze200 = 224;
+static const RoomID kMarsDeathRoom = 225;
+
+// Hot Spot Activation IDs.
+
+static const HotSpotActivationID kActivationReadyForKiosk = 1;
+static const HotSpotActivationID kActivationKioskChoice = 2;
+static const HotSpotActivationID kActivationTunnelMapReady = 3;
+static const HotSpotActivationID kActivateMarsPodClosed = 4;
+static const HotSpotActivationID kActivateMarsPodOpen = 5;
+static const HotSpotActivationID kActivateReadyToPressurizeAirlock = 6;
+static const HotSpotActivationID kActivateAirlockPressurized = 7;
+static const HotSpotActivationID kActivateMaskOnHolder = 8;
+static const HotSpotActivationID kActivateMaskOnFiller = 9;
+static const HotSpotActivationID kActivateReactorPlatformOut = 10;
+static const HotSpotActivationID kActivateReactorPlatformIn = 11;
+static const HotSpotActivationID kActivateReactorAskLowerScreen = 12;
+static const HotSpotActivationID kActivateReactorReadyForNitrogen = 13;
+static const HotSpotActivationID kActivateReactorReadyForCrowBar = 14;
+static const HotSpotActivationID kActivateReactorAskOperation = 15;
+static const HotSpotActivationID kActivateReactorRanEvaluation = 16;
+static const HotSpotActivationID kActivateReactorRanDiagnostics = 17;
+static const HotSpotActivationID kActivateReactorAnalyzed = 18;
+static const HotSpotActivationID kActivateReactorInstructions = 19;
+static const HotSpotActivationID kActivateReactorInGame = 20;
+static const HotSpotActivationID kActivateReactorBombSafe = 21;
+static const HotSpotActivationID kActivateReactorBombExposed = 22;
+static const HotSpotActivationID kActivationRobotHeadClosed = 23;
+static const HotSpotActivationID kActivationRobotHeadOpen = 24;
+
+// Hot Spot IDs.
+
+static const HotSpotID kMars11NorthKioskSpotID = 5000;
+static const HotSpotID kMars11NorthKioskSightsSpotID = 5001;
+static const HotSpotID kMars11NorthKioskColonySpotID = 5002;
+static const HotSpotID kMars12NorthKioskSpotID = 5003;
+static const HotSpotID kMars12NorthKioskSightsSpotID = 5004;
+static const HotSpotID kMars12NorthKioskColonySpotID = 5005;
+static const HotSpotID kMars31SouthSpotID = 5006;
+static const HotSpotID kMars31SouthOutSpotID = 5007;
+static const HotSpotID kMars31SouthCardSpotID = 5008;
+static const HotSpotID kMars33NorthSpotID = 5009;
+static const HotSpotID kMars33NorthOutSpotID = 5010;
+static const HotSpotID kMars33NorthMonitorSpotID = 5011;
+static const HotSpotID kMars34NorthCardDropSpotID = 5012;
+static const HotSpotID kMars34SouthOpenStorageSpotID = 5013;
+static const HotSpotID kMars34SouthCloseStorageSpotID = 5014;
+static const HotSpotID kMars34SouthCrowbarSpotID = 5015;
+static const HotSpotID kMars35EastPressurizeSpotID = 5016;
+static const HotSpotID kMars35EastSpinSpotID = 5017;
+static const HotSpotID kMars35WestPressurizeSpotID = 5018;
+static const HotSpotID kMars35WestSpinSpotID = 5019;
+static const HotSpotID kMars45NorthOpenStorageSpotID = 5020;
+static const HotSpotID kMars45NorthCloseStorageSpotID = 5021;
+static const HotSpotID kMars45NorthCrowbarSpotID = 5022;
+static const HotSpotID kAttackRobotHotSpotID = 5023;
+static const HotSpotID kMars49AirMaskSpotID = 5024;
+static const HotSpotID kMars49AirMaskFilledSpotID = 5025;
+static const HotSpotID kMars49AirFillingDropSpotID = 5026;
+static const HotSpotID kMars52MoveLeftSpotID = 5027;
+static const HotSpotID kMars52MoveRightSpotID = 5028;
+static const HotSpotID kMars52ExtractSpotID = 5029;
+static const HotSpotID kMars53RetractSpotID = 5030;
+static const HotSpotID kMars54MoveLeftSpotID = 5031;
+static const HotSpotID kMars54MoveRightSpotID = 5032;
+static const HotSpotID kMars54ExtractSpotID = 5033;
+static const HotSpotID kMars55RetractSpotID = 5034;
+static const HotSpotID kMars56MoveLeftSpotID = 5035;
+static const HotSpotID kMars56MoveRightSpotID = 5036;
+static const HotSpotID kMars56ExtractSpotID = 5037;
+static const HotSpotID kMars57RetractSpotID = 5038;
+static const HotSpotID kMars57LowerScreenSpotID = 5039;
+static const HotSpotID kMars57Retract2SpotID = 5040;
+static const HotSpotID kMars57DropNitrogenSpotID = 5041;
+static const HotSpotID kMars57DropCrowBarSpotID = 5042;
+static const HotSpotID kMars57CantOpenPanelSpotID = 5043;
+static const HotSpotID kMars57ShieldEvaluationSpotID = 5044;
+static const HotSpotID kMars57MeasureOutputSpotID = 5045;
+static const HotSpotID kMars57RunDiagnosticsSpotID = 5046;
+static const HotSpotID kMars57BackToOperationMenuSpotID = 5047;
+static const HotSpotID kMars57AnalyzeObjectSpotID = 5048;
+static const HotSpotID kMars57RemoveObjectMenuSpotID = 5049;
+static const HotSpotID kMars57CircuitLinkSpotID = 5050;
+static const HotSpotID kMars57CancelCircuitLinkSpotID = 5051;
+static const HotSpotID kMars57GameInstructionsSpotID = 5052;
+static const HotSpotID kMars57UndoMoveSpotID = 5053;
+static const HotSpotID kMars57RedMoveSpotID = 5054;
+static const HotSpotID kMars57YellowMoveSpotID = 5055;
+static const HotSpotID kMars57GreenMoveSpotID = 5056;
+static const HotSpotID kMars57BlueMoveSpotID = 5057;
+static const HotSpotID kMars57PurpleMoveSpotID = 5058;
+static const HotSpotID kMars57LowerScreenSafelySpotID = 5059;
+static const HotSpotID kMars57GrabBombSpotID = 5060;
+static const HotSpotID kMars58MoveLeftSpotID = 5061;
+static const HotSpotID kMars58MoveRightSpotID = 5062;
+static const HotSpotID kMars58ExtractSpotID = 5063;
+static const HotSpotID kMars59RetractSpotID = 5064;
+static const HotSpotID kMars60EastPressurizeSpotID = 5065;
+static const HotSpotID kMars60EastSpinSpotID = 5066;
+static const HotSpotID kMars60WestPressurizeSpotID = 5067;
+static const HotSpotID kMars60WestSpinSpotID = 5068;
+static const HotSpotID kRobotShuttleOpenHeadSpotID = 5069;
+static const HotSpotID kRobotShuttleMapChipSpotID = 5070;
+static const HotSpotID kRobotShuttleOpticalChipSpotID = 5071;
+static const HotSpotID kRobotShuttleShieldChipSpotID = 5072;
+
+// Extra sequence IDs.
+
+static const ExtraID kMarsArrivalFromTSA = 0;
+static const ExtraID kMars0AWatchShuttleDepart = 1;
+static const ExtraID kRobotThrowsPlayer = 2;
+static const ExtraID kMarsInfoKioskIntro = 3;
+static const ExtraID kMarsColonyInfo = 4;
+static const ExtraID kMarsSightsInfo = 5;
+static const ExtraID kRobotOnWayToShuttle = 6;
+static const ExtraID kMars31SouthZoomInNoCard = 7;
+static const ExtraID kMars31SouthViewNoCard = 8;
+static const ExtraID kMars31SouthZoomOutNoCard = 9;
+static const ExtraID kMars31SouthZoomViewNoCard = 10;
+static const ExtraID kMars33SlideShow1 = 11;
+static const ExtraID kMars33SlideShow2 = 12;
+static const ExtraID kMars33SlideShow3 = 13;
+static const ExtraID kMars33SlideShow4 = 14;
+static const ExtraID kMars34SpotOpenWithBar = 15;
+static const ExtraID kMars34SpotCloseWithBar = 16;
+static const ExtraID kMars34SpotOpenNoBar = 17;
+static const ExtraID kMars34SpotCloseNoBar = 18;
+static const ExtraID kMars34ViewOpenWithBar = 19;
+static const ExtraID kMars34ViewOpenNoBar = 20;
+static const ExtraID kMars34NorthPodGreeting = 21;
+static const ExtraID kMarsTurnOnPod = 22;
+static const ExtraID kMarsTakePodToMars45 = 23;
+static const ExtraID kMars35WestSpinAirlockToEast = 24;
+static const ExtraID kMars35EastSpinAirlockToWest = 25;
+static const ExtraID kMars45SpotOpenWithBar = 26;
+static const ExtraID kMars45SpotCloseWithBar = 27;
+static const ExtraID kMars45SpotOpenNoBar = 28;
+static const ExtraID kMars45SpotCloseNoBar = 29;
+static const ExtraID kMars45ViewOpenWithBar = 30;
+static const ExtraID kMars45ViewOpenNoBar = 31;
+static const ExtraID kMars48RobotApproaches = 32;
+static const ExtraID kMars48RobotKillsPlayer = 33;
+static const ExtraID kMars48RobotLoops = 34;
+static const ExtraID kMars48RobotView = 35;
+static const ExtraID kMars48RobotDefends = 36;
+static const ExtraID kMars49SouthViewMaskFilling = 37;
+static const ExtraID kMars52SpinLeft = 38;
+static const ExtraID kMars52SpinRight = 39;
+static const ExtraID kMars52Extend = 40;
+static const ExtraID kMars53Retract = 41;
+static const ExtraID kMars54SpinLeft = 42;
+static const ExtraID kMars54SpinRight = 43;
+static const ExtraID kMars54Extend = 44;
+static const ExtraID kMars55Retract = 45;
+static const ExtraID kMars56SpinLeft = 46;
+static const ExtraID kMars56SpinRight = 47;
+static const ExtraID kMars56ExtendWithBomb = 48;
+static const ExtraID kMars56ExtendNoBomb = 49;
+static const ExtraID kMars57RetractWithBomb = 50;
+static const ExtraID kMars57RetractNoBomb = 51;
+static const ExtraID kMars57LowerScreenClosed = 52;
+static const ExtraID kMars57CantOpenPanel = 53;
+static const ExtraID kMars57FreezeLock = 54;
+static const ExtraID kMars57BreakLock = 55;
+static const ExtraID kMars57LockFrozenView = 56;
+static const ExtraID kMars57ThawLock = 57;
+static const ExtraID kMars57OpenPanel = 58;
+static const ExtraID kMars57OpenPanelChoices = 59;
+static const ExtraID kMars57ShieldEvaluation = 60;
+static const ExtraID kMars57MeasureOutput = 61;
+static const ExtraID kMars57ShieldOkayLoop = 62;
+static const ExtraID kMars57RunDiagnostics = 63;
+static const ExtraID kMars57BombExplodes = 64;
+static const ExtraID kMars57BombAnalysis = 65;
+static const ExtraID kMars57DontLink = 66;
+static const ExtraID kMars57CircuitLink = 67;
+static const ExtraID kMars57GameLevel1 = 68;
+static const ExtraID kMars57GameLevel2 = 69;
+static const ExtraID kMars57GameLevel3 = 70;
+static const ExtraID kMars57BombExplodesInGame = 71;
+static const ExtraID kMars57GameSolved = 72;
+static const ExtraID kMars57ExposeBomb = 73;
+static const ExtraID kMars57BackToNormal = 74;
+static const ExtraID kMars57ViewOpenNoBomb = 75;
+static const ExtraID kMars58SpinLeft = 76;
+static const ExtraID kMars58SpinRight = 77;
+static const ExtraID kMars58Extend = 78;
+static const ExtraID kMars59Retract = 79;
+static const ExtraID kMars60WestSpinAirlockToEast = 80;
+static const ExtraID kMars60EastSpinAirlockToWest = 81;
+static const ExtraID kMarsRobotHeadOpen = 82;
+static const ExtraID kMarsRobotHeadClose = 83;
+static const ExtraID kMarsRobotHead000 = 84;
+static const ExtraID kMarsRobotHead001 = 85;
+static const ExtraID kMarsRobotHead010 = 86;
+static const ExtraID kMarsRobotHead011 = 87;
+static const ExtraID kMarsRobotHead100 = 88;
+static const ExtraID kMarsRobotHead101 = 89;
+static const ExtraID kMarsRobotHead110 = 90;
+static const ExtraID kMarsRobotHead111 = 91;
+static const ExtraID kMarsMaze007RobotApproach = 92;
+static const ExtraID kMarsMaze007RobotLoop = 93;
+static const ExtraID kMarsMaze007RobotDeath = 94;
+static const ExtraID kMarsMaze015SouthRobotApproach = 95;
+static const ExtraID kMarsMaze015SouthRobotLoop = 96;
+static const ExtraID kMarsMaze015SouthRobotDeath = 97;
+static const ExtraID kMarsMaze101EastRobotApproach = 98;
+static const ExtraID kMarsMaze101EastRobotLoop = 99;
+static const ExtraID kMarsMaze101EastRobotDeath = 100;
+static const ExtraID kMarsMaze104WestLoop = 101;
+static const ExtraID kMarsMaze104WestDeath = 102;
+static const ExtraID kMarsMaze133SouthApproach = 103;
+static const ExtraID kMarsMaze133SouthLoop = 104;
+static const ExtraID kMarsMaze133SouthDeath = 105;
+static const ExtraID kMarsMaze136NorthApproach = 106;
+static const ExtraID kMarsMaze136NorthLoop = 107;
+static const ExtraID kMarsMaze136NorthDeath = 108;
+static const ExtraID kMarsMaze184WestLoop = 109;
+static const ExtraID kMarsMaze184WestDeath = 110;
+static const ExtraID kMars200DeathInBucket = 111;
+
+static const ResIDType kReactorUndoHilitePICTID = 900;
+
+static const int16 kMars52Compass = 90;
+static const int16 kMars54Compass = 180;
+static const int16 kMars56Compass = 270;
+static const int16 kMars58Compass = 0;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/mars/energybeam.cpp b/engines/pegasus/neighborhood/mars/energybeam.cpp
new file mode 100644
index 0000000000..964c8ba381
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/energybeam.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/pegasus.h"
+#include "pegasus/neighborhood/mars/energybeam.h"
+
+namespace Pegasus {
+
+static const TimeValue kEnergyBeamTime = kOneSecond * kShuttleWeaponScale / 2;
+
+static const CoordType kEnergyBeamOriginH = kShuttleWindowMidH;
+static const CoordType kEnergyBeamOriginV = kShuttleWindowTop + kShuttleWindowHeight;
+
+static const float kBeamXOrigin = convertScreenHToSpaceX(kEnergyBeamOriginH, kEnergyBeamMinDistance);
+static const float kBeamYOrigin = convertScreenVToSpaceY(kEnergyBeamOriginV, kEnergyBeamMinDistance);
+static const float kBeamZOrigin = kEnergyBeamMinDistance;
+
+EnergyBeam::EnergyBeam() {
+ _weaponDuration = kEnergyBeamTime;
+ setSegment(0, kEnergyBeamTime);
+ _weaponOrigin = Point3D(kBeamXOrigin, kBeamYOrigin, kBeamZOrigin);
+}
+
+void EnergyBeam::draw(const Common::Rect &) {
+ static const int kBeamColorRed1 = 224;
+ static const int kBeamColorRed2 = 64;
+
+ Graphics::Surface *surface = ((PegasusEngine *)g_engine)->_gfx->getWorkArea();
+
+ byte red = linearInterp(0, kEnergyBeamTime, _lastTime, kBeamColorRed1, kBeamColorRed2);
+ uint32 color = surface->format.RGBToColor(red, 0, 0);
+
+ Point3D startPoint;
+ if (_weaponTime < 0.1)
+ startPoint = _weaponOrigin;
+ else
+ linearInterp(_weaponOrigin, _weaponTarget, _weaponTime - 0.1, startPoint);
+
+ Common::Point lineStart;
+ project3DTo2D(startPoint, lineStart);
+
+ Common::Point lineEnd;
+ project3DTo2D(_weaponLocation, lineEnd);
+
+ surface->drawThickLine(lineStart.x, lineStart.y, lineEnd.x, lineEnd.y, 2, 1, color);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/mars/energybeam.h b/engines/pegasus/neighborhood/mars/energybeam.h
new file mode 100644
index 0000000000..715ed4b01d
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/energybeam.h
@@ -0,0 +1,43 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_MARS_ENERGYBEAM_H
+#define PEGASUS_NEIGHBORHOOD_MARS_ENERGYBEAM_H
+
+#include "pegasus/neighborhood/mars/shuttleweapon.h"
+
+namespace Pegasus {
+
+class EnergyBeam : public ShuttleWeapon {
+public:
+ EnergyBeam();
+ virtual ~EnergyBeam() {}
+
+ void draw(const Common::Rect &);
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/mars/gravitoncannon.cpp b/engines/pegasus/neighborhood/mars/gravitoncannon.cpp
new file mode 100644
index 0000000000..d04b3d08b2
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/gravitoncannon.cpp
@@ -0,0 +1,134 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/neighborhood/mars/gravitoncannon.h"
+#include "pegasus/neighborhood/mars/robotship.h"
+#include "pegasus/neighborhood/mars/spacejunk.h"
+
+namespace Pegasus {
+
+static const TimeValue kGravitonTime = kOneSecond * kShuttleWeaponScale;
+
+static const CoordType kGravitonOriginH = kShuttleWindowLeft - 1;
+static const CoordType kGravitonOriginV = kShuttleWindowMidV;
+
+static const float kGravitonXOrigin = convertScreenHToSpaceX(kGravitonOriginH, kGravitonMinDistance);
+static const float kGravitonYOrigin = convertScreenVToSpaceY(kGravitonOriginV, kGravitonMinDistance);
+static const float kGravitonZOrigin = kGravitonMinDistance;
+
+// Width of graviton sprite...
+static const CoordType kGravitonMaxScreenWidth = 78;
+static const CoordType kGravitonMaxScreenHeight = 46;
+
+static const float kGravitonWidth = convertScreenHToSpaceX(kShuttleWindowMidH + kGravitonMaxScreenWidth / 2, kGravitonMinDistance)
+ - convertScreenHToSpaceX(kShuttleWindowMidH - kGravitonMaxScreenWidth / 2, kGravitonMinDistance);
+static const float kGravitonHeight = convertScreenVToSpaceY(kShuttleWindowMidV - kGravitonMaxScreenHeight / 2, kGravitonMinDistance)
+ - convertScreenVToSpaceY(kShuttleWindowMidV + kGravitonMaxScreenHeight / 2, kGravitonMinDistance);
+
+GravitonCannon::GravitonCannon() {
+ _weaponDuration = kGravitonTime;
+ setSegment(0, kGravitonTime);
+ _weaponOrigin = Point3D(kGravitonXOrigin, kGravitonYOrigin, kGravitonZOrigin);
+ _rightOrigin = Point3D(-kGravitonXOrigin, kGravitonYOrigin, kGravitonZOrigin);
+}
+
+void GravitonCannon::initShuttleWeapon() {
+ ShuttleWeapon::initShuttleWeapon();
+ _gravitonImage.getImageFromPICTFile("Images/Mars/Graviton Cannon");
+ _gravitonImage.getSurfaceBounds(_gravitonBounds);
+}
+
+void GravitonCannon::cleanUpShuttleWeapon() {
+ _gravitonImage.deallocateSurface();
+ ShuttleWeapon::cleanUpShuttleWeapon();
+}
+
+void GravitonCannon::draw(const Common::Rect &) {
+ // Left graviton...
+ Point3D pt3D = _weaponLocation;
+ pt3D.translate(-kGravitonWidth / 2, kGravitonHeight / 2, 0);
+ Common::Point pt2D;
+ project3DTo2D(pt3D, pt2D);
+ Common::Rect gravitonRect;
+ gravitonRect.left = pt2D.x;
+ gravitonRect.top = pt2D.y;
+
+ pt3D.translate(kGravitonWidth, -kGravitonHeight, 0);
+ project3DTo2D(pt3D, pt2D);
+ gravitonRect.right = pt2D.x;
+ gravitonRect.bottom = pt2D.y;
+
+ _gravitonImage.scaleTransparentCopy(_gravitonBounds, gravitonRect);
+
+ // Right graviton...
+ pt3D = _rightLocation;
+ pt3D.translate(-kGravitonWidth / 2, kGravitonHeight / 2, 0);
+ project3DTo2D(pt3D, pt2D);
+ gravitonRect.left = pt2D.x;
+ gravitonRect.top = pt2D.y;
+
+ pt3D.translate(kGravitonWidth, -kGravitonHeight, 0);
+ project3DTo2D(pt3D, pt2D);
+ gravitonRect.right = pt2D.x;
+ gravitonRect.bottom = pt2D.y;
+
+ _gravitonImage.scaleTransparentCopy(_gravitonBounds, gravitonRect);
+}
+
+void GravitonCannon::updateWeaponPosition() {
+ ShuttleWeapon::updateWeaponPosition();
+ if (_weaponTime != 1.0)
+ linearInterp(_rightOrigin, _weaponTarget, _weaponTime, _rightLocation);
+}
+
+bool GravitonCannon::collisionWithJunk(Common::Point &impactPoint) {
+ if (getDisplayOrder() == kShuttleWeaponFrontOrder) {
+ Point3D junkPosition;
+ g_spaceJunk->getJunkPosition(junkPosition);
+
+ if (junkPosition.z < _weaponLocation.z) {
+ setDisplayOrder(kShuttleWeaponBackOrder);
+ project3DTo2D(_weaponLocation, impactPoint);
+
+ if (g_spaceJunk->pointInJunk(impactPoint))
+ return true;
+
+ project3DTo2D(_rightLocation, impactPoint);
+ return g_spaceJunk->pointInJunk(impactPoint);
+ }
+ }
+
+ return false;
+}
+
+void GravitonCannon::hitJunk(Common::Point impactPoint) {
+ g_spaceJunk->hitByGravitonCannon(impactPoint);
+}
+
+void GravitonCannon::hitShuttle(Common::Point impactPoint) {
+ g_robotShip->hitByGravitonCannon(impactPoint);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/mars/gravitoncannon.h b/engines/pegasus/neighborhood/mars/gravitoncannon.h
new file mode 100644
index 0000000000..b94fd55e5b
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/gravitoncannon.h
@@ -0,0 +1,57 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_MARS_GRAVITONCANNON_H
+#define PEGASUS_NEIGHBORHOOD_MARS_GRAVITONCANNON_H
+
+#include "pegasus/surface.h"
+#include "pegasus/neighborhood/mars/shuttleweapon.h"
+
+namespace Pegasus {
+
+class GravitonCannon : public ShuttleWeapon {
+public:
+ GravitonCannon();
+ virtual ~GravitonCannon() {}
+
+ void initShuttleWeapon();
+ void cleanUpShuttleWeapon();
+
+ void draw(const Common::Rect &);
+
+protected:
+ virtual void updateWeaponPosition();
+ virtual bool collisionWithJunk(Common::Point &impactPoint);
+ virtual void hitJunk(Common::Point impactPoint);
+ virtual void hitShuttle(Common::Point impactPoint);
+
+ Surface _gravitonImage;
+ Common::Rect _gravitonBounds;
+ Point3D _rightOrigin, _rightLocation;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/mars/hermite.cpp b/engines/pegasus/neighborhood/mars/hermite.cpp
new file mode 100644
index 0000000000..7f631b369d
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/hermite.cpp
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/neighborhood/mars/hermite.h"
+
+namespace Pegasus {
+
+CoordType hermite(CoordType p1, CoordType p4, CoordType r1, CoordType r4, int32 time, int32 duration) {
+ float t = (float)time / duration;
+ float tsq = t * t;
+ float tcu = t * tsq;
+ float tcu2 = tcu + tcu;
+ float tsq2 = tsq + tsq;
+ float tsq3 = tsq2 + tsq;
+ return (CoordType)((tcu2 - tsq3 + 1) * p1 + (tsq3 - tcu2) * p4 + (tcu - tsq2 + t) * r1 + (tcu - tsq) * r4);
+}
+
+CoordType dHermite(CoordType p1, CoordType p4, CoordType r1, CoordType r4, int32 time, int32 duration) {
+ float t = (float)time / duration;
+ float t2 = t + t;
+ float t4 = t2 + t2;
+ float t6 = t4 + t2;
+ float tsq = t * t;
+ float tsq3 = tsq + tsq + tsq;
+ float tsq6 = tsq3 + tsq3;
+ return (CoordType)((tsq6 - t6) * p1 + (t6 - tsq6) * p4 + (tsq3 - t4 + 1) * r1 + (tsq3 - t2) * r4);
+}
+
+void hermite(Common::Point p1, Common::Point p4, Common::Point r1, Common::Point r4, int32 time, int32 duration, Common::Point &result) {
+ float t = (float)time / duration;
+ float tsq = t * t;
+ float tcu = t * tsq;
+ float tcu2 = tcu + tcu;
+ float tsq2 = tsq + tsq;
+ float tsq3 = tsq2 + tsq;
+
+ result.x = (int16)((tcu2 - tsq3 + 1) * p1.x + (tsq3 - tcu2) * p4.x + (tcu - tsq2 + t) * r1.x + (tcu - tsq) * r4.x);
+ result.y = (int16)((tcu2 - tsq3 + 1) * p1.y + (tsq3 - tcu2) * p4.y + (tcu - tsq2 + t) * r1.y + (tcu - tsq) * r4.y);
+}
+
+void dHermite(Common::Point p1, Common::Point p4, Common::Point r1, Common::Point r4, int32 time, int32 duration, Common::Point &result) {
+ float t = (float)time / duration;
+ float t2 = t + t;
+ float t4 = t2 + t2;
+ float t6 = t4 + t2;
+ float tsq = t * t;
+ float tsq3 = tsq + tsq + tsq;
+ float tsq6 = tsq3 + tsq3;
+
+ result.x = (int16)((tsq6 - t6) * p1.x + (t6 - tsq6) * p4.x + (tsq3 - t4 + 1) * r1.x + (tsq3 - t2) * r4.x);
+ result.y = (int16)((tsq6 - t6) * p1.y + (t6 - tsq6) * p4.y + (tsq3 - t4 + 1) * r1.y + (tsq3 - t2) * r4.y);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/mars/hermite.h b/engines/pegasus/neighborhood/mars/hermite.h
new file mode 100644
index 0000000000..44cb3a5a11
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/hermite.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_MARS_HERMITE_H
+#define PEGASUS_NEIGHBORHOOD_MARS_HERMITE_H
+
+#include "common/rect.h"
+#include "pegasus/types.h"
+
+namespace Pegasus {
+
+CoordType hermite(CoordType p1, CoordType p4, CoordType r1, CoordType r4, int32 t, int32 duration);
+CoordType dHermite(CoordType p1, CoordType p4, CoordType r1, CoordType r4, int32 t, int32 duration);
+void hermite(Common::Point p1, Common::Point p4, Common::Point r1, Common::Point r4, int32 t, int32 duration, Common::Point &result);
+void dHermite(Common::Point p1, Common::Point p4, Common::Point r1, Common::Point r4, int32 t, int32 duration, Common::Point &result);
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/mars/mars.cpp b/engines/pegasus/neighborhood/mars/mars.cpp
new file mode 100644
index 0000000000..34c9e3d0f8
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/mars.cpp
@@ -0,0 +1,3735 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/events.h"
+#include "video/qt_decoder.h"
+
+#include "pegasus/cursor.h"
+#include "pegasus/energymonitor.h"
+#include "pegasus/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/biochips/opticalchip.h"
+#include "pegasus/items/biochips/shieldchip.h"
+#include "pegasus/items/inventory/airmask.h"
+#include "pegasus/neighborhood/mars/mars.h"
+
+namespace Pegasus {
+
+// This should really be 22.5.
+// Probably no one will know the difference.
+static const int16 kMarsShieldPanelOffsetAngle = 22;
+
+static const CanMoveForwardReason kCantMoveRobotBlocking = kCantMoveLastReason + 1;
+
+static const NotificationFlags kTimeForCanyonChaseFlag = kLastNeighborhoodNotificationFlag << 1;
+static const NotificationFlags kExplosionFinishedFlag = kTimeForCanyonChaseFlag << 1;
+static const NotificationFlags kTimeToTransportFlag = kExplosionFinishedFlag << 1;
+
+static const NotificationFlags kMarsNotificationFlags = kTimeForCanyonChaseFlag |
+ kExplosionFinishedFlag |
+ kTimeToTransportFlag;
+
+static const TimeValue kLittleExplosionStart = 0 * 40;
+static const TimeValue kLittleExplosionStop = 24 * 40;
+
+static const TimeValue kBigExplosionStart = 24 * 40;
+static const TimeValue kBigExplosionStop = 62 * 40;
+
+enum {
+ kMaze007RobotLoopingEvent,
+ kMaze015RobotLoopingEvent,
+ kMaze101RobotLoopingEvent,
+ kMaze104RobotLoopingEvent,
+ kMaze133RobotLoopingEvent,
+ kMaze136RobotLoopingEvent,
+ kMaze184RobotLoopingEvent
+};
+
+enum {
+ kMaze007RobotLoopingTime = (64 + 96) * kMarsFrameDuration,
+ kMaze015RobotLoopingTime = (64 + 93) * kMarsFrameDuration,
+ kMaze101RobotLoopingTime = (64 + 45) * kMarsFrameDuration,
+ kMaze104RobotLoopingTime = 96 * kMarsFrameDuration,
+ kMaze133RobotLoopingTime = (64 + 96) * kMarsFrameDuration,
+ kMaze136RobotLoopingTime = (64 + 96) * kMarsFrameDuration,
+ kMaze184RobotLoopingTime = 96 * kMarsFrameDuration
+};
+
+// I've made a couple macros for these rects so we don't
+// have to globally construct them or whatnot
+#define kShuttleEnergyBeamBounds Common::Rect(24, 27, 24 + 112, 27 + 46)
+#define kShuttleGravitonBounds Common::Rect(24, 73, 24 + 112, 73 + 30)
+#define kShuttleTractorBounds Common::Rect(24, 103, 24 + 112, 103 + 30)
+#define kShuttleTransportBounds Common::Rect(484, 353, 89 + 484, 79 + 353)
+
+void MarsTimerEvent::fire() {
+ mars->marsTimerExpired(*this);
+}
+
+Mars::Mars(InputHandler *nextHandler, PegasusEngine *owner) : Neighborhood(nextHandler, owner, "Mars", kMarsID),
+ _guessObject(kNoDisplayElement), _undoPict(kNoDisplayElement), _guessHistory(kNoDisplayElement),
+ _choiceHighlight(kNoDisplayElement), _shuttleInterface1(kNoDisplayElement), _shuttleInterface2(kNoDisplayElement),
+ _shuttleInterface3(kNoDisplayElement), _shuttleInterface4(kNoDisplayElement), _canyonChaseMovie(kNoDisplayElement),
+ _leftShuttleMovie(kNoDisplayElement), _rightShuttleMovie(kNoDisplayElement), _lowerLeftShuttleMovie(kNoDisplayElement),
+ _lowerRightShuttleMovie(kNoDisplayElement), _centerShuttleMovie(kNoDisplayElement),
+ _upperLeftShuttleMovie(kNoDisplayElement), _upperRightShuttleMovie(kNoDisplayElement),
+ _leftDamageShuttleMovie(kNoDisplayElement), _rightDamageShuttleMovie(kNoDisplayElement), _explosions(kNoDisplayElement),
+ _planetMovie(kNoDisplayElement), _junk(kNoDisplayElement), _energyChoiceSpot(kShuttleEnergySpotID),
+ _gravitonChoiceSpot(kShuttleGravitonSpotID), _tractorChoiceSpot(kShuttleTractorSpotID),
+ _shuttleViewSpot(kShuttleViewSpotID), _shuttleTransportSpot(kShuttleTransportSpotID) {
+ _noAirFuse.setFunctor(new Common::Functor0Mem<void, Mars>(this, &Mars::airStageExpired));
+ setIsItemTaken(kMarsCard);
+ setIsItemTaken(kAirMask);
+ setIsItemTaken(kCrowbar);
+ setIsItemTaken(kCardBomb);
+}
+
+Mars::~Mars() {
+ _vm->getAllHotspots().remove(&_energyChoiceSpot);
+ _vm->getAllHotspots().remove(&_gravitonChoiceSpot);
+ _vm->getAllHotspots().remove(&_tractorChoiceSpot);
+ _vm->getAllHotspots().remove(&_shuttleViewSpot);
+ _vm->getAllHotspots().remove(&_shuttleTransportSpot);
+}
+
+void Mars::init() {
+ Neighborhood::init();
+
+ Hotspot *attackSpot = _vm->getAllHotspots().findHotspotByID(kAttackRobotHotSpotID);
+ attackSpot->setMaskedHotspotFlags(kDropItemSpotFlag, kDropItemSpotFlag);
+ _attackingItem = NULL;
+
+ forceStridingStop(kMars08, kNorth, kAltMarsNormal);
+
+ _neighborhoodNotification.notifyMe(this, kMarsNotificationFlags, kMarsNotificationFlags);
+
+ _explosionCallBack.setNotification(&_neighborhoodNotification);
+ _explosionCallBack.setCallBackFlag(kExplosionFinishedFlag);
+
+ _weaponSelection = kNoWeapon;
+}
+
+void Mars::flushGameState() {
+ g_energyMonitor->saveCurrentEnergyValue();
+}
+
+void Mars::start() {
+ g_energyMonitor->stopEnergyDraining();
+ g_energyMonitor->restoreLastEnergyValue();
+ _vm->resetEnergyDeathReason();
+ g_energyMonitor->startEnergyDraining();
+ Neighborhood::start();
+}
+
+class AirMaskCondition : public AICondition {
+public:
+ AirMaskCondition(const uint32);
+
+ virtual bool fireCondition();
+
+protected:
+ uint32 _airThreshold;
+ uint32 _lastAirLevel;
+};
+
+AirMaskCondition::AirMaskCondition(const uint32 airThreshold) {
+ _airThreshold = airThreshold;
+ _lastAirLevel = g_airMask->getAirLeft();
+}
+
+bool AirMaskCondition::fireCondition() {
+ bool result = g_airMask && g_airMask->isAirMaskOn() &&
+ g_airMask->getAirLeft() <= _airThreshold && _lastAirLevel > _airThreshold;
+
+ _lastAirLevel = g_airMask->getAirLeft();
+ return result;
+}
+
+void Mars::setUpAIRules() {
+ Neighborhood::setUpAIRules();
+
+ // Don't add these rules if we're going to the robot's shuttle...
+ if (g_AIArea && !GameState.getMarsReadyForShuttleTransport()) {
+ AIPlayMessageAction *messageAction = new AIPlayMessageAction("Images/AI/Globals/XGLOB1E", false);
+ AILocationCondition *locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kMars47, kSouth));
+ AIRule *rule = new AIRule(locCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Mars/XM27NB", false);
+ locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kMars27, kNorth));
+ rule = new AIRule(locCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Mars/XM27NB", false);
+ locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kMars28, kNorth));
+ rule = new AIRule(locCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Mars/XM41ED", false);
+ locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kMars19, kEast));
+ rule = new AIRule(locCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ AIDeactivateRuleAction *deactivate = new AIDeactivateRuleAction(rule);
+ locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kMars35, kWest));
+ rule = new AIRule(locCondition, deactivate);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Mars/XM41ED", false);
+ locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kMars48, kWest));
+ rule = new AIRule(locCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ AirMaskCondition *airMask50Condition = new AirMaskCondition(50);
+ messageAction = new AIPlayMessageAction("Images/AI/Mars/XMMAZB1", false);
+ AIRule *rule50 = new AIRule(airMask50Condition, messageAction);
+
+ AirMaskCondition *airMask25Condition = new AirMaskCondition(25);
+ AICompoundAction *compound = new AICompoundAction();
+ messageAction = new AIPlayMessageAction("Images/AI/Mars/XMMAZB2", false);
+ compound->addAction(messageAction);
+ deactivate = new AIDeactivateRuleAction(rule50);
+ compound->addAction(deactivate);
+ AIRule *rule25 = new AIRule(airMask25Condition, compound);
+
+ AirMaskCondition *airMask5Condition = new AirMaskCondition(5);
+ compound = new AICompoundAction;
+ messageAction = new AIPlayMessageAction("Images/AI/Mars/XMMAZB3", false);
+ compound->addAction(messageAction);
+ deactivate = new AIDeactivateRuleAction(rule50);
+ compound->addAction(deactivate);
+ deactivate = new AIDeactivateRuleAction(rule25);
+ compound->addAction(deactivate);
+ AIRule *rule5 = new AIRule(airMask5Condition, compound);
+
+ g_AIArea->addAIRule(rule5);
+ g_AIArea->addAIRule(rule25);
+ g_AIArea->addAIRule(rule50);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Mars/XM51ND", false);
+ AIDoorOpenedCondition *doorOpen = new AIDoorOpenedCondition(MakeRoomView(kMars51, kEast));
+ rule = new AIRule(doorOpen, messageAction);
+ g_AIArea->addAIRule(rule);
+ }
+}
+
+uint16 Mars::getDateResID() const {
+ return kDate2185ID;
+}
+
+TimeValue Mars::getViewTime(const RoomID room, const DirectionConstant direction) {
+ ExtraTable::Entry extra;
+ SpotTable::Entry spotEntry;
+ uint32 extraID = 0xffffffff;
+
+ switch (MakeRoomView(room, direction)) {
+ case MakeRoomView(kMars0A, kNorth):
+ if (!GameState.getMarsSeenTimeStream()) {
+ getExtraEntry(kMarsArrivalFromTSA, extra);
+ return extra.movieStart;
+ }
+ break;
+ case MakeRoomView(kMars31South, kSouth):
+ if (GameState.isTakenItemID(kMarsCard))
+ extraID = kMars31SouthZoomViewNoCard;
+ break;
+ case MakeRoomView(kMars31, kSouth):
+ if (GameState.isTakenItemID(kMarsCard))
+ extraID = kMars31SouthViewNoCard;
+ break;
+ case MakeRoomView(kMars34, kSouth):
+ if (_privateFlags.getFlag(kMarsPrivatePodStorageOpenFlag)) {
+ if (GameState.isTakenItemID(kCrowbar))
+ extraID = kMars34ViewOpenNoBar;
+ else
+ extraID = kMars34ViewOpenWithBar;
+ }
+ break;
+ case MakeRoomView(kMars36, kSouth):
+ case MakeRoomView(kMars37, kSouth):
+ case MakeRoomView(kMars38, kSouth):
+ findSpotEntry(room, direction, kSpotOnTurnMask | kSpotLoopsMask, spotEntry);
+ return spotEntry.movieStart;
+ case MakeRoomView(kMars45, kNorth):
+ if (_privateFlags.getFlag(kMarsPrivatePodStorageOpenFlag)) {
+ if (GameState.isTakenItemID(kCrowbar))
+ extraID = kMars45ViewOpenNoBar;
+ else
+ extraID = kMars45ViewOpenWithBar;
+ }
+ break;
+ case MakeRoomView(kMars48, kEast):
+ if (GameState.getMarsSeenRobotAtReactor() && !GameState.getMarsAvoidedReactorRobot())
+ extraID = kMars48RobotView;
+ break;
+ case MakeRoomView(kMars56, kEast):
+ if (_privateFlags.getFlag(kMarsPrivateBombExposedFlag)) {
+ if (_privateFlags.getFlag(kMarsPrivateDraggingBombFlag))
+ extraID = kMars57ViewOpenNoBomb;
+ else
+ extraID = kMars57ExposeBomb;
+ } else if (GameState.getMarsLockBroken()) {
+ extraID = kMars57OpenPanelChoices;
+ } else if (GameState.getMarsLockFrozen()) {
+ extraID = kMars57LockFrozenView;
+ }
+ break;
+ case MakeRoomView(kMarsRobotShuttle, kEast):
+ if (getCurrentActivation() == kActivationRobotHeadOpen) {
+ extraID = kMarsRobotHead111;
+
+ if (_privateFlags.getFlag(kMarsPrivateGotMapChipFlag))
+ extraID -= 1;
+ if (_privateFlags.getFlag(kMarsPrivateGotOpticalChipFlag))
+ extraID -= 2;
+ if (_privateFlags.getFlag(kMarsPrivateGotShieldChipFlag))
+ extraID -= 4;
+ }
+ break;
+ }
+
+ if (extraID == 0xffffffff)
+ return Neighborhood::getViewTime(room, direction);
+
+ getExtraEntry(extraID, extra);
+ return extra.movieEnd - 1;
+}
+
+void Mars::getZoomEntry(const HotSpotID spotID, ZoomTable::Entry &entry) {
+ Neighborhood::getZoomEntry(spotID, entry);
+
+ uint32 extraID = 0xffffffff;
+
+ switch (spotID) {
+ case kMars31SouthSpotID:
+ if (GameState.getCurrentDirection() == kSouth && GameState.isTakenItemID(kMarsCard))
+ extraID = kMars31SouthZoomInNoCard;
+ break;
+ case kMars31SouthOutSpotID:
+ if (GameState.getCurrentDirection() == kSouth && GameState.isTakenItemID(kMarsCard))
+ extraID = kMars31SouthZoomOutNoCard;
+ break;
+ }
+
+ if (extraID != 0xffffffff) {
+ ExtraTable::Entry extra;
+ getExtraEntry(extraID, extra);
+ entry.movieStart = extra.movieStart;
+ entry.movieEnd = extra.movieEnd;
+ }
+}
+
+void Mars::findSpotEntry(const RoomID room, const DirectionConstant direction, SpotFlags flags, SpotTable::Entry &entry) {
+ Neighborhood::findSpotEntry(room, direction, flags, entry);
+
+ if ((flags & (kSpotOnArrivalMask | kSpotOnTurnMask)) != 0) {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kMars27, kNorth):
+ if (GameState.getMarsSeenThermalScan())
+ entry.clear();
+ else
+ GameState.setMarsSeenThermalScan(true);
+ break;
+ case MakeRoomView(kMars28, kNorth):
+ if (GameState.getMarsSeenThermalScan())
+ entry.clear();
+ else
+ GameState.setMarsSeenThermalScan(true);
+ break;
+ }
+ }
+}
+
+CanMoveForwardReason Mars::canMoveForward(ExitTable::Entry &entry) {
+ CanMoveForwardReason reason = Neighborhood::canMoveForward(entry);
+
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kMars48, kEast):
+ if (GameState.getMarsSeenRobotAtReactor() && !GameState.getMarsAvoidedReactorRobot())
+ reason = kCantMoveRobotBlocking;
+ break;
+ case MakeRoomView(kMars48, kSouth):
+ if (GameState.getMarsSeenRobotAtReactor() && !GameState.getMarsAvoidedReactorRobot())
+ _utilityFuse.stopFuse();
+ break;
+ }
+
+ return reason;
+}
+
+void Mars::cantMoveThatWay(CanMoveForwardReason reason) {
+ if (reason == kCantMoveRobotBlocking) {
+ startExtraSequence(kMars48RobotKillsPlayer, kExtraCompletedFlag, kFilterNoInput);
+ loadLoopSound2("");
+ } else {
+ Neighborhood::cantMoveThatWay(reason);
+ }
+}
+
+void Mars::moveForward() {
+ if (GameState.getCurrentRoom() == kMars02 || (GameState.getCurrentRoom() >= kMars05 && GameState.getCurrentRoom() <= kMars08))
+ loadLoopSound2("");
+
+ Neighborhood::moveForward();
+}
+
+void Mars::bumpIntoWall() {
+ requestSpotSound(kMarsBumpIntoWallIn, kMarsBumpIntoWallOut, kFilterNoInput, 0);
+ Neighborhood::bumpIntoWall();
+}
+
+CanOpenDoorReason Mars::canOpenDoor(DoorTable::Entry &entry) {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kMars05, kEast):
+ case MakeRoomView(kMars06, kEast):
+ case MakeRoomView(kMars07, kEast):
+ if (!GameState.getMarsSecurityDown())
+ return kCantOpenLocked;
+ break;
+ case MakeRoomView(kMarsMaze037, kWest):
+ case MakeRoomView(kMarsMaze038, kEast):
+ if (GameState.getMarsMazeDoorPair1())
+ return kCantOpenLocked;
+ break;
+ case MakeRoomView(kMarsMaze050, kNorth):
+ case MakeRoomView(kMarsMaze058, kSouth):
+ if (!GameState.getMarsMazeDoorPair1())
+ return kCantOpenLocked;
+ break;
+ case MakeRoomView(kMarsMaze047, kNorth):
+ case MakeRoomView(kMarsMaze142, kSouth):
+ if (GameState.getMarsMazeDoorPair2())
+ return kCantOpenLocked;
+ break;
+ case MakeRoomView(kMarsMaze057, kNorth):
+ case MakeRoomView(kMarsMaze136, kSouth):
+ if (!GameState.getMarsMazeDoorPair2())
+ return kCantOpenLocked;
+ break;
+ case MakeRoomView(kMarsMaze120, kWest):
+ case MakeRoomView(kMarsMaze121, kEast):
+ if (GameState.getMarsMazeDoorPair3())
+ return kCantOpenLocked;
+ break;
+ case MakeRoomView(kMarsMaze081, kNorth):
+ case MakeRoomView(kMarsMaze083, kSouth):
+ if (!GameState.getMarsMazeDoorPair3())
+ return kCantOpenLocked;
+ break;
+ }
+
+ return Neighborhood::canOpenDoor(entry);
+}
+
+void Mars::cantOpenDoor(CanOpenDoorReason reason) {
+ switch (GameState.getCurrentRoom()) {
+ case kMars05:
+ case kMars06:
+ case kMars07:
+ playSpotSoundSync(kMarsCantOpenShuttleIn, kMarsCantOpenShuttleOut);
+ break;
+ default:
+ Neighborhood::cantOpenDoor(reason);
+ break;
+ }
+}
+
+void Mars::openDoor() {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kMars06, kEast):
+ case MakeRoomView(kMars07, kEast):
+ if (GameState.getMarsSecurityDown())
+ playSpotSoundSync(kMarsNoShuttleIn, kMarsNoShuttleOut);
+ break;
+ case MakeRoomView(kMars47, kSouth):
+ if (GameState.isTakenItemID(kAirMask))
+ setCurrentAlternate(kAltMarsTookMask);
+ else
+ setCurrentAlternate(kAltMarsNormal);
+ break;
+ case MakeRoomView(kMars48, kNorth):
+ if (GameState.getMarsPodAtUpperPlatform())
+ setCurrentAlternate(kAltMarsNormal);
+ else
+ setCurrentAlternate(kAltMarsPodAtMars45);
+ break;
+ case MakeRoomView(kMars48, kEast):
+ if (GameState.getMarsSeenRobotAtReactor() && !GameState.getMarsAvoidedReactorRobot()) {
+ die(kDeathDidntGetOutOfWay);
+ return;
+ }
+ break;
+ }
+
+ Neighborhood::openDoor();
+}
+
+void Mars::doorOpened() {
+ switch (GameState.getCurrentRoom()) {
+ case kMars27:
+ case kMars28:
+ if (GameState.getCurrentDirection() == kNorth)
+ _vm->die(kDeathArrestedInMars);
+ else
+ Neighborhood::doorOpened();
+ break;
+ case kMars41:
+ case kMars42:
+ if (GameState.getCurrentDirection() == kEast)
+ _vm->die(kDeathWrongShuttleLock);
+ else
+ Neighborhood::doorOpened();
+ break;
+ case kMars51:
+ Neighborhood::doorOpened();
+ setUpReactorEnergyDrain();
+
+ if (g_AIArea)
+ g_AIArea->checkRules();
+ break;
+ case kMars19:
+ if (GameState.getCurrentDirection() == kEast)
+ GameState.setMarsAirlockOpen(true);
+
+ Neighborhood::doorOpened();
+ break;
+ case kMars48:
+ if (GameState.getCurrentDirection() == kWest)
+ GameState.setMarsAirlockOpen(true);
+
+ Neighborhood::doorOpened();
+ break;
+ default:
+ Neighborhood::doorOpened();
+ break;
+ }
+}
+
+void Mars::setUpReactorEnergyDrain() {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kMars51, kEast):
+ if (GameState.isCurrentDoorOpen()) {
+ if (g_energyMonitor->getEnergyDrainRate() == kEnergyDrainNormal) {
+ if (GameState.getShieldOn()) {
+ g_shield->setItemState(kShieldRadiation);
+ g_energyMonitor->setEnergyDrainRate(kMarsReactorEnergyDrainWithShield);
+ } else {
+ g_energyMonitor->setEnergyDrainRate(kMarsReactorEnergyDrainNoShield);
+ }
+ _vm->setEnergyDeathReason(kDeathReactorBurn);
+ }
+ } else {
+ if (g_energyMonitor->getEnergyDrainRate() != kEnergyDrainNormal) {
+ if (GameState.getShieldOn())
+ g_shield->setItemState(kShieldNormal);
+ g_energyMonitor->setEnergyDrainRate(kEnergyDrainNormal);
+ _vm->resetEnergyDeathReason();
+ }
+ }
+ break;
+ case MakeRoomView(kMars52, kNorth):
+ case MakeRoomView(kMars52, kSouth):
+ case MakeRoomView(kMars52, kEast):
+ case MakeRoomView(kMars52, kWest):
+ case MakeRoomView(kMars54, kNorth):
+ case MakeRoomView(kMars54, kSouth):
+ case MakeRoomView(kMars54, kEast):
+ case MakeRoomView(kMars54, kWest):
+ case MakeRoomView(kMars56, kNorth):
+ case MakeRoomView(kMars56, kSouth):
+ case MakeRoomView(kMars56, kEast):
+ case MakeRoomView(kMars56, kWest):
+ case MakeRoomView(kMars58, kNorth):
+ case MakeRoomView(kMars58, kSouth):
+ case MakeRoomView(kMars58, kEast):
+ case MakeRoomView(kMars58, kWest):
+ if (g_energyMonitor->getEnergyDrainRate() == kEnergyDrainNormal) {
+ if (GameState.getShieldOn()) {
+ g_shield->setItemState(kShieldRadiation);
+ g_energyMonitor->setEnergyDrainRate(kMarsReactorEnergyDrainWithShield);
+ } else {
+ g_energyMonitor->setEnergyDrainRate(kMarsReactorEnergyDrainNoShield);
+ }
+ _vm->setEnergyDeathReason(kDeathReactorBurn);
+ }
+ break;
+ default:
+ if (g_energyMonitor->getEnergyDrainRate() != kEnergyDrainNormal) {
+ if (GameState.getShieldOn())
+ g_shield->setItemState(kShieldNormal);
+ g_energyMonitor->setEnergyDrainRate(kEnergyDrainNormal);
+ _vm->resetEnergyDeathReason();
+ }
+ break;
+ }
+}
+
+void Mars::closeDoorOffScreen(const RoomID room, const DirectionConstant direction) {
+ switch (room) {
+ case kMars51:
+ playSpotSoundSync(kMarsGantryDoorCloseIn, kMarsGantryDoorCloseOut);
+ if (GameState.getShieldOn())
+ g_shield->setItemState(kShieldNormal);
+ g_energyMonitor->setEnergyDrainRate(kEnergyDrainNormal);
+ _vm->resetEnergyDeathReason();
+ break;
+ case kMars05:
+ case kMars06:
+ case kMars07:
+ case kMars13:
+ case kMars22:
+ case kMars47:
+ case kMars52:
+ playSpotSoundSync(kMarsGantryDoorCloseIn, kMarsGantryDoorCloseOut);
+ break;
+ case kMars18:
+ case kMars32:
+ playSpotSoundSync(kMarsTransportDoorCloseIn, kMarsTransportDoorCloseOut);
+ break;
+ case kMars19:
+ if (GameState.getCurrentRoom() != kMars35) {
+ playSpotSoundSync(kMarsBigAirlockDoorCloseIn, kMarsBigAirlockDoorCloseOut);
+ GameState.setMarsAirlockOpen(false);
+ }
+ break;
+ case kMars36:
+ if (GameState.getCurrentRoom() != kMars35)
+ playSpotSoundSync(kMarsSmallAirlockDoorCloseIn, kMarsSmallAirlockDoorCloseOut);
+ break;
+ case kMars48:
+ if (direction == kWest) {
+ if (GameState.getCurrentRoom() != kMars60) {
+ playSpotSoundSync(kMarsSmallAirlockDoorCloseIn, kMarsSmallAirlockDoorCloseOut);
+ GameState.setMarsAirlockOpen(false);
+ }
+ } else {
+ playSpotSoundSync(kMarsGantryDoorCloseIn, kMarsGantryDoorCloseOut);
+ }
+ break;
+ case kMars41:
+ case kMars42:
+ case kMars43:
+ if (direction == kWest)
+ playSpotSoundSync(kMarsGantryDoorCloseIn, kMarsGantryDoorCloseOut);
+ break;
+ case kMarsMaze037:
+ case kMarsMaze038:
+ case kMarsMaze012:
+ case kMarsMaze066:
+ case kMarsMaze050:
+ case kMarsMaze058:
+ case kMarsMaze057:
+ case kMarsMaze136:
+ case kMarsMaze047:
+ case kMarsMaze142:
+ case kMarsMaze133:
+ case kMarsMaze132:
+ case kMarsMaze113:
+ case kMarsMaze114:
+ case kMarsMaze120:
+ case kMarsMaze121:
+ case kMarsMaze081:
+ case kMarsMaze083:
+ case kMarsMaze088:
+ case kMarsMaze089:
+ case kMarsMaze179:
+ case kMarsMaze180:
+ playSpotSoundSync(kMarsMazeDoorCloseIn, kMarsMazeDoorCloseOut);
+ break;
+ }
+}
+
+void Mars::checkAirlockDoors() {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kMars19, kWest):
+ case MakeRoomView(kMars18, kWest):
+ case MakeRoomView(kMars17, kWest):
+ case MakeRoomView(kMars16, kWest):
+ case MakeRoomView(kMars15, kWest):
+ case MakeRoomView(kMars14, kWest):
+ case MakeRoomView(kMars12, kWest):
+ case MakeRoomView(kMars11, kWest):
+ case MakeRoomView(kMars10, kWest):
+ if (GameState.getMarsInAirlock()) {
+ playSpotSoundSync(kMarsBigAirlockDoorCloseIn, kMarsBigAirlockDoorCloseOut);
+ GameState.setMarsInAirlock(false);
+ }
+ break;
+ case MakeRoomView(kMars36, kEast):
+ case MakeRoomView(kMars37, kEast):
+ case MakeRoomView(kMars38, kEast):
+ case MakeRoomView(kMars39, kEast):
+ case MakeRoomView(kMars48, kEast):
+ case MakeRoomView(kMars50, kEast):
+ case MakeRoomView(kMars51, kEast):
+ case MakeRoomView(kMars52, kEast):
+ if (GameState.getMarsInAirlock()) {
+ playSpotSoundSync(kMarsSmallAirlockDoorCloseIn, kMarsSmallAirlockDoorCloseOut);
+ GameState.setMarsInAirlock(false);
+ }
+ break;
+ case MakeRoomView(kMars35, kWest):
+ case MakeRoomView(kMars35, kEast):
+ case MakeRoomView(kMars60, kWest):
+ case MakeRoomView(kMars60, kEast):
+ GameState.setMarsInAirlock(true);
+ break;
+ default:
+ GameState.setMarsInAirlock(false);
+ break;
+ }
+}
+
+int16 Mars::getStaticCompassAngle(const RoomID room, const DirectionConstant dir) {
+ int16 angle = Neighborhood::getStaticCompassAngle(room, dir);
+
+ switch (MakeRoomView(room, dir)) {
+ case MakeRoomView(kMars0A, kNorth):
+ angle -= 20;
+ break;
+ case MakeRoomView(kMars23, kNorth):
+ case MakeRoomView(kMars23, kSouth):
+ case MakeRoomView(kMars23, kEast):
+ case MakeRoomView(kMars23, kWest):
+ case MakeRoomView(kMars26, kNorth):
+ case MakeRoomView(kMars26, kSouth):
+ case MakeRoomView(kMars26, kEast):
+ case MakeRoomView(kMars26, kWest):
+ angle += 30;
+ break;
+ case MakeRoomView(kMars24, kNorth):
+ case MakeRoomView(kMars24, kSouth):
+ case MakeRoomView(kMars24, kEast):
+ case MakeRoomView(kMars24, kWest):
+ case MakeRoomView(kMars25, kNorth):
+ case MakeRoomView(kMars25, kSouth):
+ case MakeRoomView(kMars25, kEast):
+ case MakeRoomView(kMars25, kWest):
+ angle -= 30;
+ break;
+ case MakeRoomView(kMars54, kNorth):
+ case MakeRoomView(kMars54, kSouth):
+ case MakeRoomView(kMars54, kEast):
+ case MakeRoomView(kMars54, kWest):
+ angle += 90;
+ break;
+ case MakeRoomView(kMars56, kNorth):
+ case MakeRoomView(kMars56, kSouth):
+ case MakeRoomView(kMars56, kEast):
+ case MakeRoomView(kMars56, kWest):
+ angle += 180;
+ break;
+ case MakeRoomView(kMars58, kNorth):
+ case MakeRoomView(kMars58, kSouth):
+ case MakeRoomView(kMars58, kEast):
+ case MakeRoomView(kMars58, kWest):
+ angle -= 90;
+ break;
+ }
+
+ return angle;
+}
+
+void Mars::getExitCompassMove(const ExitTable::Entry &exitEntry, FaderMoveSpec &compassMove) {
+ Neighborhood::getExitCompassMove(exitEntry, compassMove);
+
+ if (exitEntry.room == kMars43 && exitEntry.direction == kEast) {
+ compassMove.insertFaderKnot(exitEntry.movieStart + 16 * kMarsFrameDuration, 90);
+ compassMove.insertFaderKnot(exitEntry.movieStart + 32 * kMarsFrameDuration, 270);
+ } else if (exitEntry.room == kMars46 && exitEntry.direction == kWest && exitEntry.altCode != kAltMarsPodAtMars45) {
+ compassMove.makeTwoKnotFaderSpec(kMarsMovieScale, exitEntry.movieStart, 270, exitEntry.movieEnd, 360);
+ compassMove.insertFaderKnot(exitEntry.movieStart + 43 * kMarsFrameDuration, 270);
+ compassMove.insertFaderKnot(exitEntry.movieStart + 58 * kMarsFrameDuration, 360);
+ }
+}
+
+void Mars::getExtraCompassMove(const ExtraTable::Entry &entry, FaderMoveSpec &compassMove) {
+ switch (entry.extra) {
+ case kMarsTakePodToMars45:
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), entry.movieStart, 0, entry.movieEnd, 180);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * (kMarsFramesPerSecond * 3), 30);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * (kMarsFramesPerSecond * 11), 10);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * (kMarsFramesPerSecond * 14), 40);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * (kMarsFramesPerSecond * 16), 30);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * (kMarsFramesPerSecond * 23), 100);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * (kMarsFramesPerSecond * 31), 70);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * (kMarsFramesPerSecond * 34), 100);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * (kMarsFramesPerSecond * 37), 85);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * (kMarsFramesPerSecond * 42), 135);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * (kMarsFramesPerSecond * 44), 125);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * (kMarsFramesPerSecond * 46), 145);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * (kMarsFramesPerSecond * 49), 160);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * (kMarsFramesPerSecond * 51), 180);
+ break;
+ case kMars35WestSpinAirlockToEast:
+ case kMars60WestSpinAirlockToEast:
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), entry.movieStart, 90, entry.movieEnd, 270);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsMovieScale, 90);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsMovieScale * 3, 270);
+ break;
+ case kMars35EastSpinAirlockToWest:
+ case kMars60EastSpinAirlockToWest:
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), entry.movieStart, 270, entry.movieEnd, 90);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsMovieScale, 270);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsMovieScale * 3, 90);
+ break;
+ case kMars52SpinLeft:
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), entry.movieStart, kMars52Compass, entry.movieEnd, kMars54Compass);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 10, kMars52Compass);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 110, kMars54Compass);
+ break;
+ case kMars52SpinRight:
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), entry.movieStart, kMars52Compass, entry.movieEnd, kMars58Compass);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 10, kMars52Compass);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 110, kMars58Compass);
+ break;
+ case kMars52Extend:
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), entry.movieStart, kMars52Compass,
+ entry.movieEnd, kMars52Compass + kMarsShieldPanelOffsetAngle);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 10, kMars52Compass);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 60, kMars52Compass + kMarsShieldPanelOffsetAngle);
+ break;
+ case kMars53Retract:
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), entry.movieStart,
+ kMars52Compass + kMarsShieldPanelOffsetAngle, entry.movieEnd, kMars52Compass);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 10, kMars52Compass + kMarsShieldPanelOffsetAngle);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 60, kMars52Compass);
+ break;
+ case kMars56ExtendWithBomb:
+ case kMars56ExtendNoBomb:
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), entry.movieStart, kMars56Compass,
+ entry.movieEnd, kMars56Compass - kMarsShieldPanelOffsetAngle);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 10, kMars56Compass);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 60, kMars56Compass - kMarsShieldPanelOffsetAngle);
+ break;
+ case kMars57RetractWithBomb:
+ case kMars57RetractNoBomb:
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), entry.movieStart,
+ kMars56Compass - kMarsShieldPanelOffsetAngle, entry.movieEnd, kMars56Compass);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 10, kMars56Compass - kMarsShieldPanelOffsetAngle);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 60, kMars56Compass);
+ break;
+ case kMars54SpinLeft:
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), entry.movieStart, kMars54Compass, entry.movieEnd, kMars56Compass);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 10, kMars54Compass);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 110, kMars56Compass);
+ break;
+ case kMars54SpinRight:
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), entry.movieStart, kMars54Compass, entry.movieEnd, kMars52Compass);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 10, kMars54Compass);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 110, kMars52Compass);
+ break;
+ case kMars56SpinLeft:
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), entry.movieStart, kMars56Compass,
+ entry.movieEnd, kMars58Compass + 360);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 10, kMars56Compass);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 110, kMars58Compass + 360);
+ break;
+ case kMars56SpinRight:
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), entry.movieStart, kMars56Compass, entry.movieEnd, kMars54Compass);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 10, kMars56Compass);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 110, kMars54Compass);
+ break;
+ case kMars58SpinLeft:
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), entry.movieStart, kMars58Compass,
+ entry.movieEnd, kMars52Compass);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 10, kMars58Compass);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 110, kMars52Compass);
+ break;
+ case kMars58SpinRight:
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), entry.movieStart,
+ kMars58Compass + 360, entry.movieEnd, kMars56Compass);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 10, kMars58Compass + 360);
+ compassMove.insertFaderKnot(entry.movieStart + kMarsFrameDuration * 110, kMars56Compass);
+ break;
+ default:
+ Neighborhood::getExtraCompassMove(entry, compassMove);
+ }
+}
+
+void Mars::loadAmbientLoops() {
+ RoomID room = GameState.getCurrentRoom();
+
+ if ((room >= kMars0A && room <= kMars21) || (room >= kMars41 && room <= kMars43)) {
+ if (GameState.getMarsSeenTimeStream())
+ loadLoopSound1("Sounds/Mars/Gantry Ambient.22K.8.AIFF");
+ } else if (room >= kMars22 && room <= kMars31South) {
+ loadLoopSound1("Sounds/Mars/Reception.02.22K.8.AIFF", 0x100 / 4);
+ } else if (room >= kMars32 && room <= kMars34) {
+ loadLoopSound1("Sounds/Mars/Pod Room Ambient.22K.8.AIFF");
+ } else if (room == kMars35) {
+ if (getAirQuality(room) == kAirQualityVacuum)
+ loadLoopSound1("Sounds/Mars/Gear Room Ambient.22K.8.AIFF");
+ else
+ loadLoopSound1("Sounds/Mars/Gantry Ambient.22K.8.AIFF", 0x100 / 2);
+ } else if (room >= kMars36 && room <= kMars39) {
+ loadLoopSound1("Sounds/Mars/Gear Room Ambient.22K.8.AIFF");
+ } else if (room >= kMars45 && room <= kMars51) {
+ loadLoopSound1("Sounds/Mars/Lower Mars Ambient.22K.8.AIFF");
+ } else if (room >= kMars52 && room <= kMars58) {
+ loadLoopSound1("Sounds/Mars/ReactorLoop.22K.8.AIFF");
+ } else if (room == kMars60) {
+ if (getAirQuality(room) == kAirQualityVacuum)
+ loadLoopSound1("Sounds/Mars/Mars Maze Ambient.22K.8.AIFF");
+ else
+ loadLoopSound1("Sounds/Mars/Lower Mars Ambient.22K.8.AIFF", 0x100 / 2);
+ } else if (room >= kMarsMaze004 && room <= kMarsMaze200) {
+ loadLoopSound1("Sounds/Mars/Mars Maze Ambient.22K.8.AIFF");
+ } else if (room == kMarsRobotShuttle) {
+ loadLoopSound1("Sounds/Mars/Robot Shuttle.22K.8.AIFF");
+ }
+
+ if (!_noAirFuse.isFuseLit()) {
+ switch (room) {
+ case kMars02:
+ case kMars05:
+ case kMars06:
+ case kMars07:
+ case kMars08:
+ loadLoopSound2("Sounds/Mars/Gantry Loop.aiff", 0x100, 0, 0);
+ break;
+ // Robot at maze 48
+ case kMarsMaze037:
+ if (GameState.isCurrentDoorOpen())
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100 / 2);
+ else
+ loadLoopSound2("");
+ break;
+ case kMarsMaze038:
+ case kMarsMaze039:
+ case kMarsMaze049:
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100);
+ break;
+ case kMarsMaze050:
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100 * 3 / 4);
+ break;
+ case kMarsMaze051:
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100 / 2);
+ break;
+ case kMarsMaze052:
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100 / 4);
+ break;
+ case kMarsMaze042:
+ case kMarsMaze053:
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100 / 8);
+ break;
+ case kMarsMaze058:
+ if (GameState.isCurrentDoorOpen())
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100 / 4);
+ else
+ loadLoopSound2("");
+ break;
+ // Robot at 151
+ case kMarsMaze148:
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100);
+ break;
+ case kMarsMaze147:
+ case kMarsMaze149:
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100 * 3 / 4);
+ break;
+ case kMarsMaze146:
+ case kMarsMaze152:
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100 / 2);
+ break;
+ case kMarsMaze145:
+ case kMarsMaze153:
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100 / 4);
+ break;
+ // Robots at 80 and 82.
+ case kMarsMaze079:
+ case kMarsMaze081:
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100);
+ break;
+ case kMarsMaze078:
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100 * 3 / 4);
+ break;
+ case kMarsMaze083:
+ if (GameState.isCurrentDoorOpen())
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100 * 3 / 4);
+ else
+ loadLoopSound2("");
+ break;
+ case kMarsMaze118:
+ case kMarsMaze076:
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100 / 2);
+ break;
+ case kMarsMaze074:
+ case kMarsMaze117:
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100 / 4);
+ break;
+ // Robot at 94
+ case kMarsMaze093:
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100);
+ break;
+ case kMarsMaze091:
+ case kMarsMaze092:
+ case kMarsMaze098:
+ case kMarsMaze101:
+ case kMarsMaze100:
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100 * 3 / 4);
+ break;
+ case kMarsMaze090:
+ case kMarsMaze099:
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100 / 2);
+ break;
+ case kMarsMaze089:
+ if (GameState.isCurrentDoorOpen())
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100 / 2);
+ break;
+ case kMarsMaze178:
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100 / 4);
+ break;
+ // Robot at 197
+ case kMarsMaze191:
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100);
+ break;
+ case kMarsMaze190:
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100 * 3 / 4);
+ break;
+ case kMarsMaze198:
+ case kMarsMaze189:
+ loadLoopSound2("Sounds/Mars/Maze Sparks.22K.AIFF", 0x100 / 2);
+ break;
+ default:
+ loadLoopSound2("");
+ break;
+ }
+ }
+}
+
+void Mars::checkContinuePoint(const RoomID room, const DirectionConstant direction) {
+ switch (MakeRoomView(room, direction)) {
+ case MakeRoomView(kMars02, kSouth):
+ case MakeRoomView(kMars19, kEast):
+ case MakeRoomView(kMars22, kNorth):
+ case MakeRoomView(kMars43, kEast):
+ case MakeRoomView(kMars51, kEast):
+ case MakeRoomView(kMars56, kEast):
+ case MakeRoomView(kMars60, kWest):
+ case MakeRoomView(kMarsMaze004, kWest):
+ case MakeRoomView(kMarsMaze009, kWest):
+ case MakeRoomView(kMarsMaze012, kWest):
+ case MakeRoomView(kMarsMaze037, kWest):
+ case MakeRoomView(kMarsMaze047, kNorth):
+ case MakeRoomView(kMarsMaze052, kWest):
+ case MakeRoomView(kMarsMaze057, kNorth):
+ case MakeRoomView(kMarsMaze071, kWest):
+ case MakeRoomView(kMarsMaze081, kNorth):
+ case MakeRoomView(kMarsMaze088, kWest):
+ case MakeRoomView(kMarsMaze093, kWest):
+ case MakeRoomView(kMarsMaze115, kNorth):
+ case MakeRoomView(kMarsMaze120, kWest):
+ case MakeRoomView(kMarsMaze126, kEast):
+ case MakeRoomView(kMarsMaze133, kNorth):
+ case MakeRoomView(kMarsMaze144, kNorth):
+ case MakeRoomView(kMarsMaze156, kEast):
+ case MakeRoomView(kMarsMaze162, kNorth):
+ case MakeRoomView(kMarsMaze177, kWest):
+ case MakeRoomView(kMarsMaze180, kNorth):
+ case MakeRoomView(kMarsMaze187, kWest):
+ case MakeRoomView(kMarsMaze199, kWest):
+ makeContinuePoint();
+ break;
+ case MakeRoomView(kMars05, kEast):
+ case MakeRoomView(kMars06, kEast):
+ case MakeRoomView(kMars07, kEast):
+ if (GameState.getMarsSecurityDown())
+ makeContinuePoint();
+ break;
+ case MakeRoomView(kMars46, kSouth):
+ if (!GameState.getMarsSeenRobotAtReactor())
+ makeContinuePoint();
+ break;
+ case MakeRoomView(kMars46, kWest):
+ if (GameState.getMarsAvoidedReactorRobot())
+ makeContinuePoint();
+ break;
+ }
+}
+
+void Mars::launchMaze007Robot() {
+ startExtraLongSequence(kMarsMaze007RobotApproach, kMarsMaze007RobotDeath, kExtraCompletedFlag, kFilterAllInput);
+ scheduleEvent(kMaze007RobotLoopingTime, kMarsMovieScale, kMaze007RobotLoopingEvent);
+}
+
+void Mars::launchMaze015Robot() {
+ startExtraLongSequence(kMarsMaze015SouthRobotApproach, kMarsMaze015SouthRobotDeath, kExtraCompletedFlag, kFilterAllInput);
+ scheduleEvent(kMaze015RobotLoopingTime, kMarsMovieScale, kMaze015RobotLoopingEvent);
+}
+
+void Mars::launchMaze101Robot() {
+ startExtraLongSequence(kMarsMaze101EastRobotApproach, kMarsMaze101EastRobotDeath, kExtraCompletedFlag, kFilterAllInput);
+ scheduleEvent(kMaze101RobotLoopingTime, kMarsMovieScale, kMaze101RobotLoopingEvent);
+}
+
+void Mars::launchMaze104Robot() {
+ startExtraLongSequence(kMarsMaze104WestLoop, kMarsMaze104WestDeath, kExtraCompletedFlag, kFilterAllInput);
+ scheduleEvent(kMaze104RobotLoopingTime, kMarsMovieScale, kMaze104RobotLoopingEvent);
+}
+
+void Mars::launchMaze133Robot() {
+ startExtraLongSequence(kMarsMaze133SouthApproach, kMarsMaze133SouthDeath, kExtraCompletedFlag, kFilterAllInput);
+ scheduleEvent(kMaze133RobotLoopingTime, kMarsMovieScale, kMaze133RobotLoopingEvent);
+}
+
+void Mars::launchMaze136Robot() {
+ startExtraLongSequence(kMarsMaze136NorthApproach, kMarsMaze136NorthDeath, kExtraCompletedFlag, kFilterAllInput);
+ scheduleEvent(kMaze136RobotLoopingTime, kMarsMovieScale, kMaze136RobotLoopingEvent);
+}
+
+void Mars::launchMaze184Robot() {
+ startExtraLongSequence(kMarsMaze184WestLoop, kMarsMaze184WestDeath, kExtraCompletedFlag, kFilterAllInput);
+ scheduleEvent(kMaze184RobotLoopingTime, kMarsMovieScale, kMaze184RobotLoopingEvent);
+}
+
+void Mars::timerExpired(const uint32 eventType) {
+ switch (eventType) {
+ case kMaze007RobotLoopingEvent:
+ case kMaze015RobotLoopingEvent:
+ case kMaze101RobotLoopingEvent:
+ case kMaze104RobotLoopingEvent:
+ case kMaze133RobotLoopingEvent:
+ case kMaze136RobotLoopingEvent:
+ case kMaze184RobotLoopingEvent:
+ _interruptionFilter = kFilterNoInput;
+ break;
+ }
+}
+
+void Mars::arriveAt(const RoomID room, const DirectionConstant direction) {
+ switch (MakeRoomView(room, direction)) {
+ case MakeRoomView(kMars18, kNorth):
+ if (GameState.getMarsPodAtUpperPlatform())
+ setCurrentAlternate(kAltMarsPodAtMars34);
+ break;
+ case MakeRoomView(kMars27, kEast):
+ case MakeRoomView(kMars29, kEast):
+ if (GameState.isTakenItemID(kMarsCard))
+ setCurrentAlternate(kAltMarsTookCard);
+ else
+ setCurrentAlternate(kAltMarsNormal);
+ break;
+ case MakeRoomView(kMars35, kEast):
+ case MakeRoomView(kMars35, kWest):
+ if (GameState.getMarsAirlockOpen())
+ setCurrentAlternate(kAltMars35AirlockWest);
+ else
+ setCurrentAlternate(kAltMars35AirlockEast);
+ break;
+ case MakeRoomView(kMars60, kEast):
+ case MakeRoomView(kMars60, kWest):
+ if (GameState.getMarsAirlockOpen())
+ setCurrentAlternate(kAltMars60AirlockEast);
+ else
+ setCurrentAlternate(kAltMars60AirlockWest);
+ break;
+ case MakeRoomView(kMars45, kNorth):
+ case MakeRoomView(kMars45, kSouth):
+ case MakeRoomView(kMars45, kEast):
+ case MakeRoomView(kMars45, kWest):
+ GameState.setMarsPodAtUpperPlatform(false);
+ setCurrentAlternate(kAltMarsPodAtMars45);
+ break;
+ case MakeRoomView(kMars46, kNorth):
+ case MakeRoomView(kMars46, kSouth):
+ case MakeRoomView(kMars46, kEast):
+ case MakeRoomView(kMars46, kWest):
+ case MakeRoomView(kMars47, kNorth):
+ case MakeRoomView(kMars47, kSouth):
+ case MakeRoomView(kMars47, kEast):
+ case MakeRoomView(kMars47, kWest):
+ if (GameState.getMarsPodAtUpperPlatform())
+ setCurrentAlternate(kAltMarsNormal);
+ else
+ setCurrentAlternate(kAltMarsPodAtMars45);
+ break;
+ case MakeRoomView(kMars48, kNorth):
+ case MakeRoomView(kMars48, kSouth):
+ case MakeRoomView(kMars48, kEast):
+ case MakeRoomView(kMars48, kWest):
+ case MakeRoomView(kMars49, kNorth):
+ case MakeRoomView(kMars49, kEast):
+ case MakeRoomView(kMars49, kWest):
+ if (GameState.isTakenItemID(kAirMask))
+ setCurrentAlternate(kAltMarsTookMask);
+ else
+ setCurrentAlternate(kAltMarsNormal);
+ break;
+ case MakeRoomView(kMars49, kSouth):
+ if (GameState.getMarsMaskOnFiller())
+ setCurrentAlternate(kAltMarsMaskOnFiller);
+ else if (GameState.isTakenItemID(kAirMask))
+ setCurrentAlternate(kAltMarsTookMask);
+ else
+ setCurrentAlternate(kAltMarsNormal);
+ break;
+ }
+
+ Neighborhood::arriveAt(room, direction);
+ checkAirlockDoors();
+ setUpReactorEnergyDrain();
+
+ switch (MakeRoomView(room, direction)) {
+ case MakeRoomView(kMars0A, kNorth):
+ if (!GameState.getMarsSeenTimeStream())
+ startExtraLongSequence(kMarsArrivalFromTSA, kMars0AWatchShuttleDepart, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case MakeRoomView(kMars07, kSouth):
+ case MakeRoomView(kMars13, kNorth):
+ if (!GameState.getMarsHeardCheckInMessage()) {
+ playSpotSoundSync(kMarsCheckInRequiredIn, kMarsCheckInRequiredOut);
+ GameState.setMarsHeardCheckInMessage(true);
+ }
+ break;
+ case MakeRoomView(kMars44, kWest):
+ if (GameState.getMarsReadyForShuttleTransport())
+ startUpFromFinishedSpaceChase();
+ else if (GameState.getMarsFinishedCanyonChase())
+ startUpFromSpaceChase();
+ else
+ _neighborhoodNotification.setNotificationFlags(kTimeForCanyonChaseFlag, kTimeForCanyonChaseFlag);
+ break;
+ case MakeRoomView(kMars10, kNorth):
+ if (!GameState.getMarsRobotThrownPlayer())
+ startExtraSequence(kRobotThrowsPlayer, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case MakeRoomView(kMars11, kSouth):
+ case MakeRoomView(kMars12, kSouth):
+ setCurrentActivation(kActivationReadyForKiosk);
+ break;
+ case MakeRoomView(kMars15, kWest):
+ if (GameState.getMarsThreadedMaze() && !GameState.getMarsSecurityDown()) {
+ playSpotSoundSync(kMarsShuttle2DepartedIn, kMarsShuttle2DepartedOut);
+ restoreStriding(kMars17, kWest, kAltMarsNormal);
+ GameState.setMarsSecurityDown(true);
+ }
+ break;
+ case MakeRoomView(kMars17, kNorth):
+ case MakeRoomView(kMars17, kSouth):
+ case MakeRoomView(kMars17, kEast):
+ case MakeRoomView(kMars17, kWest):
+ if (GameState.getMarsThreadedMaze() && !GameState.getMarsSecurityDown())
+ forceStridingStop(kMars17, kWest, kAltMarsNormal);
+
+ if (GameState.getMarsThreadedMaze() && !GameState.getMarsSawRobotLeave()) {
+ startExtraSequence(kRobotOnWayToShuttle, kExtraCompletedFlag, kFilterNoInput);
+ restoreStriding(kMars19, kWest, kAltMarsNormal);
+ GameState.setMarsSawRobotLeave(true);
+ }
+ break;
+ case MakeRoomView(kMars19, kNorth):
+ case MakeRoomView(kMars19, kSouth):
+ case MakeRoomView(kMars19, kWest):
+ if (GameState.getMarsThreadedMaze() && !GameState.getMarsSawRobotLeave())
+ forceStridingStop(kMars19, kWest, kAltMarsNormal);
+
+ if (GameState.getMarsThreadedMaze() && !GameState.getMarsSecurityDown())
+ forceStridingStop(kMars17, kWest, kAltMarsNormal);
+ break;
+ case MakeRoomView(kMars19, kEast):
+ if (GameState.getMarsThreadedMaze() && !GameState.getMarsSawRobotLeave())
+ forceStridingStop(kMars19, kWest, kAltMarsNormal);
+
+ if (GameState.getMarsThreadedMaze() && !GameState.getMarsSecurityDown())
+ forceStridingStop(kMars17, kWest, kAltMarsNormal);
+ break;
+ case MakeRoomView(kMars32, kNorth):
+ if (!GameState.getMarsPodAtUpperPlatform()) {
+ playSpotSoundSync(kMarsPodArrivedUpperPlatformIn, kMarsPodArrivedUpperPlatformOut);
+ GameState.setMarsPodAtUpperPlatform(true);
+ }
+ break;
+ case MakeRoomView(kMars33North, kNorth):
+ setCurrentActivation(kActivationTunnelMapReady);
+ // Fall through...
+ case MakeRoomView(kMars33, kSouth):
+ case MakeRoomView(kMars33, kEast):
+ case MakeRoomView(kMars33, kWest):
+ case MakeRoomView(kMars32, kSouth):
+ case MakeRoomView(kMars32, kEast):
+ case MakeRoomView(kMars32, kWest):
+ if (!GameState.getMarsPodAtUpperPlatform())
+ GameState.setMarsPodAtUpperPlatform(true);
+ break;
+ case MakeRoomView(kMars34, kNorth):
+ startExtraSequence(kMars34NorthPodGreeting, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case MakeRoomView(kMars34, kSouth):
+ case MakeRoomView(kMars45, kNorth):
+ setCurrentActivation(kActivateMarsPodClosed);
+ break;
+ case MakeRoomView(kMars35, kWest):
+ if (GameState.getMarsThreadedMaze() && !GameState.getMarsSecurityDown())
+ forceStridingStop(kMars19, kWest, kAltMarsNormal);
+ // Fall through...
+ case MakeRoomView(kMars60, kEast):
+ if (!GameState.getMarsAirlockOpen())
+ setCurrentActivation(kActivateReadyToPressurizeAirlock);
+ break;
+ case MakeRoomView(kMars35, kEast):
+ case MakeRoomView(kMars60, kWest):
+ if (GameState.getMarsAirlockOpen())
+ setCurrentActivation(kActivateReadyToPressurizeAirlock);
+ break;
+ case MakeRoomView(kMars39, kWest):
+ if (GameState.getLastRoom() == kMarsMaze200)
+ GameState.setMarsPodAtUpperPlatform(false);
+ break;
+ case MakeRoomView(kMars45, kSouth):
+ // Set up maze doors here.
+ // Doing it here makes sure that it will be the same if the player comes
+ // back out of the maze and goes back in, but will vary if
+ // the player comes back down to the maze a second time.
+ GameState.setMarsMazeDoorPair1(_vm->getRandomBit());
+ GameState.setMarsMazeDoorPair2(_vm->getRandomBit());
+ GameState.setMarsMazeDoorPair3(_vm->getRandomBit());
+ GameState.setMarsArrivedBelow(true);
+ break;
+ case MakeRoomView(kMars48, kEast):
+ if (!GameState.getMarsSeenRobotAtReactor()) {
+ // Preload the looping sound...
+ loadLoopSound2("Sounds/Mars/Robot Loop.aiff", 0, 0, 0);
+ startExtraSequence(kMars48RobotApproaches, kExtraCompletedFlag, kFilterNoInput);
+ } else if (!GameState.getMarsAvoidedReactorRobot()) {
+ loadLoopSound2("Sounds/Mars/Robot Loop.aiff", 0x100, 0, 0);
+ loopExtraSequence(kMars48RobotLoops);
+ _utilityFuse.primeFuse(kMarsRobotPatienceLimit);
+ _utilityFuse.setFunctor(new Common::Functor0Mem<void, Mars>(this, &Mars::robotTiredOfWaiting));
+ _utilityFuse.lightFuse();
+ }
+ break;
+ case MakeRoomView(kMars48, kSouth):
+ if (GameState.getMarsSeenRobotAtReactor() && !GameState.getMarsAvoidedReactorRobot()) {
+ loadLoopSound2("Sounds/Mars/Robot Loop.aiff", 0x100, 0, 0);
+ _utilityFuse.primeFuse(kMarsRobotPatienceLimit);
+ _utilityFuse.setFunctor(new Common::Functor0Mem<void, Mars>(this, &Mars::robotTiredOfWaiting));
+ _utilityFuse.lightFuse();
+ }
+ break;
+ case MakeRoomView(kMars49, kSouth):
+ if (GameState.getMarsSeenRobotAtReactor() && !GameState.getMarsAvoidedReactorRobot()) {
+ playSpotSoundSync(kMarsRobotTakesTransportIn, kMarsRobotTakesTransportOut);
+ playSpotSoundSync(kMarsPodDepartedLowerPlatformIn, kMarsPodDepartedLowerPlatformOut);
+ GameState.setMarsAvoidedReactorRobot(true);
+ GameState.setMarsPodAtUpperPlatform(true);
+ GameState.setScoringAvoidedRobot();
+ }
+
+ if (GameState.isTakenItemID(kAirMask))
+ setCurrentActivation(kActivateHotSpotAlways);
+ else if (GameState.getMarsMaskOnFiller())
+ setCurrentActivation(kActivateMaskOnFiller);
+ else
+ setCurrentActivation(kActivateMaskOnHolder);
+ break;
+ case MakeRoomView(kMars51, kWest):
+ case MakeRoomView(kMars50, kWest):
+ case MakeRoomView(kMars48, kWest):
+ if (GameState.getShieldOn())
+ g_shield->setItemState(kShieldNormal);
+ g_energyMonitor->setEnergyDrainRate(kEnergyDrainNormal);
+ _vm->resetEnergyDeathReason();
+ break;
+ case MakeRoomView(kMars52, kNorth):
+ case MakeRoomView(kMars52, kSouth):
+ case MakeRoomView(kMars52, kEast):
+ case MakeRoomView(kMars52, kWest):
+ case MakeRoomView(kMars54, kNorth):
+ case MakeRoomView(kMars54, kSouth):
+ case MakeRoomView(kMars54, kEast):
+ case MakeRoomView(kMars54, kWest):
+ case MakeRoomView(kMars56, kNorth):
+ case MakeRoomView(kMars56, kSouth):
+ case MakeRoomView(kMars56, kWest):
+ case MakeRoomView(kMars58, kNorth):
+ case MakeRoomView(kMars58, kSouth):
+ case MakeRoomView(kMars58, kEast):
+ case MakeRoomView(kMars58, kWest):
+ setCurrentActivation(kActivateReactorPlatformOut);
+ break;
+ case MakeRoomView(kMars56, kEast):
+ if (GameState.getMarsLockBroken()) {
+ setCurrentActivation(kActivateReactorAskOperation);
+ _privateFlags.setFlag(kMarsPrivatePlatformZoomedInFlag, true);
+ } else if (GameState.getMarsLockFrozen()) {
+ setCurrentActivation(kActivateReactorReadyForCrowBar);
+ _privateFlags.setFlag(kMarsPrivatePlatformZoomedInFlag, true);
+ _utilityFuse.primeFuse(kLockFreezeTimeLmit);
+ _utilityFuse.setFunctor(new Common::Functor0Mem<void, Mars>(this, &Mars::lockThawed));
+ _utilityFuse.lightFuse();
+ } else {
+ setCurrentActivation(kActivateReactorPlatformOut);
+ }
+ break;
+ case MakeRoomView(kMarsRobotShuttle, kEast):
+ setCurrentActivation(kActivationRobotHeadClosed);
+ break;
+ case MakeRoomView(kMarsMaze007, kNorth):
+ launchMaze007Robot();
+ break;
+ case MakeRoomView(kMarsMaze015, kSouth):
+ launchMaze015Robot();
+ break;
+ case MakeRoomView(kMarsMaze101, kEast):
+ launchMaze101Robot();
+ break;
+ case MakeRoomView(kMarsMaze104, kWest):
+ launchMaze104Robot();
+ break;
+ case MakeRoomView(kMarsMaze133, kSouth):
+ launchMaze133Robot();
+ break;
+ case MakeRoomView(kMarsMaze136, kNorth):
+ launchMaze136Robot();
+ break;
+ case MakeRoomView(kMarsMaze184, kWest):
+ launchMaze184Robot();
+ break;
+ case MakeRoomView(kMarsMaze199, kSouth):
+ GameState.setScoringThreadedMaze();
+ GameState.setMarsThreadedMaze(true);
+ break;
+ case MakeRoomView(kMarsDeathRoom, kNorth):
+ case MakeRoomView(kMarsDeathRoom, kSouth):
+ case MakeRoomView(kMarsDeathRoom, kEast):
+ case MakeRoomView(kMarsDeathRoom, kWest):
+ switch (GameState.getLastRoom()) {
+ case kMars39:
+ die(kDeathDidntLeaveBucket);
+ break;
+ case kMars46:
+ die(kDeathRunOverByPod);
+ break;
+ }
+ break;
+ }
+
+ checkAirMask();
+}
+
+void Mars::shieldOn() {
+ setUpReactorEnergyDrain();
+}
+
+void Mars::shieldOff() {
+ setUpReactorEnergyDrain();
+}
+
+void Mars::turnTo(const DirectionConstant direction) {
+ switch (MakeRoomView(GameState.getCurrentRoom(), direction)) {
+ case MakeRoomView(kMars27, kNorth):
+ case MakeRoomView(kMars27, kSouth):
+ case MakeRoomView(kMars27, kEast):
+ case MakeRoomView(kMars29, kNorth):
+ case MakeRoomView(kMars29, kSouth):
+ case MakeRoomView(kMars29, kEast):
+ if (GameState.isTakenItemID(kMarsCard))
+ setCurrentAlternate(kAltMarsTookCard);
+ break;
+ case MakeRoomView(kMars35, kNorth):
+ case MakeRoomView(kMars35, kSouth):
+ case MakeRoomView(kMars60, kNorth):
+ case MakeRoomView(kMars60, kSouth):
+ if (getCurrentActivation() == kActivateAirlockPressurized)
+ playSpotSoundSync(kMarsAirlockPressurizeIn, kMarsAirlockPressurizeOut);
+ break;
+ }
+
+ Neighborhood::turnTo(direction);
+
+ switch (MakeRoomView(GameState.getCurrentRoom(), direction)) {
+ case MakeRoomView(kMars11, kSouth):
+ case MakeRoomView(kMars12, kSouth):
+ setCurrentActivation(kActivationReadyForKiosk);
+ break;
+ case MakeRoomView(kMars18, kNorth):
+ if (GameState.getMarsPodAtUpperPlatform())
+ setCurrentAlternate(kAltMarsPodAtMars34);
+ break;
+ case MakeRoomView(kMars22, kSouth):
+ if (!GameState.getMarsHeardCheckInMessage()) {
+ playSpotSoundSync(kMarsCheckInRequiredIn, kMarsCheckInRequiredOut);
+ GameState.setMarsHeardCheckInMessage(true);
+ }
+ break;
+ case MakeRoomView(kMars34, kSouth):
+ case MakeRoomView(kMars45, kNorth):
+ setCurrentActivation(kActivateMarsPodClosed);
+ break;
+ case MakeRoomView(kMars34, kNorth):
+ startExtraSequence(kMars34NorthPodGreeting, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case MakeRoomView(kMars35, kEast):
+ case MakeRoomView(kMars60, kWest):
+ if (GameState.getMarsAirlockOpen())
+ setCurrentActivation(kActivateReadyToPressurizeAirlock);
+ break;
+ case MakeRoomView(kMars60, kEast):
+ if (!GameState.getMarsAirlockOpen())
+ setCurrentActivation(kActivateReadyToPressurizeAirlock);
+ break;
+ case MakeRoomView(kMars35, kWest):
+ if (!GameState.getMarsAirlockOpen())
+ setCurrentActivation(kActivateReadyToPressurizeAirlock);
+
+ // Do this here because this will be called after spinning the airlock after
+ // going through the gear room.
+ if (GameState.getMarsThreadedMaze())
+ GameState.setScoringThreadedGearRoom();
+ break;
+ case MakeRoomView(kMars48, kNorth):
+ if (GameState.getMarsSeenRobotAtReactor() && !GameState.getMarsAvoidedReactorRobot())
+ die(kDeathDidntGetOutOfWay);
+ break;
+ case MakeRoomView(kMars48, kEast):
+ if (!GameState.getMarsSeenRobotAtReactor()) {
+ // Preload the looping sound...
+ loadLoopSound2("Sounds/Mars/Robot Loop.aiff", 0, 0, 0);
+ startExtraSequence(kMars48RobotApproaches, kExtraCompletedFlag, kFilterNoInput);
+ } else if (!GameState.getMarsAvoidedReactorRobot()) {
+ loopExtraSequence(kMars48RobotLoops);
+ } else if (GameState.isTakenItemID(kAirMask)) {
+ setCurrentAlternate(kAltMarsTookMask);
+ } else {
+ setCurrentAlternate(kAltMarsNormal);
+ }
+ break;
+ case MakeRoomView(kMars48, kWest):
+ if (GameState.getMarsSeenRobotAtReactor() && !GameState.getMarsAvoidedReactorRobot())
+ die(kDeathDidntGetOutOfWay);
+ else if (GameState.isTakenItemID(kAirMask))
+ setCurrentAlternate(kAltMarsTookMask);
+ else
+ setCurrentAlternate(kAltMarsNormal);
+ break;
+ case MakeRoomView(kMars49, kSouth):
+ if (GameState.isTakenItemID(kAirMask))
+ setCurrentActivation(kActivateHotSpotAlways);
+ else
+ setCurrentActivation(kActivateMaskOnHolder);
+ break;
+ case MakeRoomView(kMars52, kNorth):
+ case MakeRoomView(kMars52, kSouth):
+ case MakeRoomView(kMars52, kEast):
+ case MakeRoomView(kMars52, kWest):
+ case MakeRoomView(kMars54, kNorth):
+ case MakeRoomView(kMars54, kSouth):
+ case MakeRoomView(kMars54, kEast):
+ case MakeRoomView(kMars54, kWest):
+ case MakeRoomView(kMars56, kNorth):
+ case MakeRoomView(kMars56, kSouth):
+ case MakeRoomView(kMars56, kEast):
+ case MakeRoomView(kMars56, kWest):
+ case MakeRoomView(kMars58, kNorth):
+ case MakeRoomView(kMars58, kSouth):
+ case MakeRoomView(kMars58, kEast):
+ case MakeRoomView(kMars58, kWest):
+ setCurrentActivation(kActivateReactorPlatformOut);
+ break;
+ case MakeRoomView(kMarsMaze007, kNorth):
+ launchMaze007Robot();
+ break;
+ case MakeRoomView(kMarsMaze015, kSouth):
+ launchMaze015Robot();
+ break;
+ case MakeRoomView(kMarsMaze101, kEast):
+ launchMaze101Robot();
+ break;
+ case MakeRoomView(kMarsMaze104, kWest):
+ launchMaze104Robot();
+ break;
+ case MakeRoomView(kMarsMaze133, kSouth):
+ launchMaze133Robot();
+ break;
+ case MakeRoomView(kMarsMaze136, kNorth):
+ launchMaze136Robot();
+ break;
+ case MakeRoomView(kMarsMaze184, kWest):
+ launchMaze184Robot();
+ break;
+ }
+}
+
+void Mars::activateOneHotspot(HotspotInfoTable::Entry &entry, Hotspot *hotspot) {
+ switch (hotspot->getObjectID()) {
+ case kMars57RedMoveSpotID:
+ case kMars57YellowMoveSpotID:
+ case kMars57GreenMoveSpotID:
+ if (!_choiceHighlight.choiceHighlighted(hotspot->getObjectID() - kMars57RedMoveSpotID))
+ hotspot->setActive();
+ break;
+ case kMars57BlueMoveSpotID:
+ if (_reactorStage >= 2 && !_choiceHighlight.choiceHighlighted(3))
+ hotspot->setActive();
+ break;
+ case kMars57PurpleMoveSpotID:
+ if (_reactorStage == 3 && !_choiceHighlight.choiceHighlighted(4))
+ hotspot->setActive();
+ break;
+ default:
+ Neighborhood::activateOneHotspot(entry, hotspot);
+ break;
+ }
+}
+
+void Mars::activateHotspots() {
+ InventoryItem *item;
+
+ Neighborhood::activateHotspots();
+
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kMars48, kEast):
+ if ((_navMovie.getFlags() & kLoopTimeBase) != 0 && _vm->getDragType() == kDragInventoryUse)
+ _vm->getAllHotspots().activateOneHotspot(kAttackRobotHotSpotID);
+ break;
+ case MakeRoomView(kMars56, kEast):
+ switch (getCurrentActivation()) {
+ case kActivateReactorReadyForNitrogen:
+ item = (InventoryItem *)_vm->getAllItems().findItemByID(kNitrogenCanister);
+ if (item->getItemState() != kNitrogenFull)
+ _vm->getAllHotspots().deactivateOneHotspot(kMars57DropNitrogenSpotID);
+ // Fall through...
+ case kActivateReactorReadyForCrowBar:
+ _vm->getAllHotspots().activateOneHotspot(kMars57CantOpenPanelSpotID);
+ break;
+ }
+ break;
+ case MakeRoomView(kMarsRobotShuttle, kEast):
+ if (_privateFlags.getFlag(kMarsPrivateGotMapChipFlag))
+ _vm->getAllHotspots().deactivateOneHotspot(kRobotShuttleMapChipSpotID);
+ else
+ _vm->getAllHotspots().activateOneHotspot(kRobotShuttleMapChipSpotID);
+
+ if (_privateFlags.getFlag(kMarsPrivateGotOpticalChipFlag))
+ _vm->getAllHotspots().deactivateOneHotspot(kRobotShuttleOpticalChipSpotID);
+ else
+ _vm->getAllHotspots().activateOneHotspot(kRobotShuttleOpticalChipSpotID);
+
+ if (_privateFlags.getFlag(kMarsPrivateGotShieldChipFlag))
+ _vm->getAllHotspots().deactivateOneHotspot(kRobotShuttleShieldChipSpotID);
+ else
+ _vm->getAllHotspots().activateOneHotspot(kRobotShuttleShieldChipSpotID);
+ break;
+ default:
+ if (_privateFlags.getFlag(kMarsPrivateInSpaceChaseFlag)) {
+ if (GameState.getMarsReadyForShuttleTransport()) {
+ _shuttleTransportSpot.setActive();
+ } else {
+ _energyChoiceSpot.setActive();
+ _gravitonChoiceSpot.setActive();
+ _tractorChoiceSpot.setActive();
+ if (_weaponSelection != kNoWeapon)
+ _shuttleViewSpot.setActive();
+ }
+ }
+ break;
+ }
+}
+
+void Mars::clickInHotspot(const Input &input, const Hotspot *clickedSpot) {
+ switch (clickedSpot->getObjectID()) {
+ case kMars11NorthKioskSpotID:
+ case kMars12NorthKioskSpotID:
+ playSpotSoundSync(kMarsKioskBeepIn, kMarsKioskBeepOut);
+ Neighborhood::clickInHotspot(input, clickedSpot);
+ break;
+ case kMars11NorthKioskSightsSpotID:
+ case kMars12NorthKioskSightsSpotID:
+ playSpotSoundSync(kMarsKioskBeepIn, kMarsKioskBeepOut);
+ if (!startExtraSequenceSync(kMarsSightsInfo, kFilterAllInput))
+ showExtraView(kMarsInfoKioskIntro);
+ break;
+ case kMars11NorthKioskColonySpotID:
+ case kMars12NorthKioskColonySpotID:
+ playSpotSoundSync(kMarsKioskBeepIn, kMarsKioskBeepOut);
+ if (!startExtraSequenceSync(kMarsColonyInfo, kFilterAllInput))
+ showExtraView(kMarsInfoKioskIntro);
+ break;
+ case kMars33NorthMonitorSpotID:
+ switch (_lastExtra) {
+ case kMars33SlideShow1:
+ startExtraSequence(kMars33SlideShow2, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kMars33SlideShow2:
+ startExtraSequence(kMars33SlideShow3, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kMars33SlideShow3:
+ startExtraSequence(kMars33SlideShow4, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kMars33SlideShow4:
+ // Should never happen...
+ default:
+ startExtraSequence(kMars33SlideShow1, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ }
+ break;
+ case kMars34SouthOpenStorageSpotID:
+ if (GameState.isTakenItemID(kCrowbar))
+ startExtraSequence(kMars34SpotOpenNoBar, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraSequence(kMars34SpotOpenWithBar, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kMars34SouthCloseStorageSpotID:
+ if (GameState.isTakenItemID(kCrowbar))
+ startExtraSequence(kMars34SpotCloseNoBar, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraSequence(kMars34SpotCloseWithBar, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kMars35WestPressurizeSpotID:
+ case kMars35EastPressurizeSpotID:
+ case kMars60WestPressurizeSpotID:
+ case kMars60EastPressurizeSpotID:
+ playSpotSoundSync(kMarsAirlockButtonBeepIn, kMarsAirlockButtonBeepOut);
+ playSpotSoundSync(kMarsAirlockPressurizeIn, kMarsAirlockPressurizeOut);
+ setCurrentActivation(kActivateAirlockPressurized);
+ break;
+ case kMars45NorthOpenStorageSpotID:
+ if (GameState.isTakenItemID(kCrowbar))
+ startExtraSequence(kMars45SpotOpenNoBar, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraSequence(kMars45SpotOpenWithBar, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kMars45NorthCloseStorageSpotID:
+ if (GameState.isTakenItemID(kCrowbar))
+ startExtraSequence(kMars45SpotCloseNoBar, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraSequence(kMars45SpotCloseWithBar, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kMars56ExtractSpotID:
+ if (GameState.isTakenItemID(kCardBomb)) {
+ startExtraSequence(kMars56ExtendNoBomb, kExtraCompletedFlag, kFilterNoInput);
+ setCurrentActivation(kActivateReactorPlatformIn);
+ } else {
+ startExtraSequence(kMars56ExtendWithBomb, kExtraCompletedFlag, kFilterNoInput);
+ setCurrentActivation(kActivateReactorAskLowerScreen);
+ }
+ break;
+ case kMars57UndoMoveSpotID:
+ playSpotSoundSync(kMarsColorMatchingButtonBeepIn, kMarsColorMatchingButtonBeepOut);
+ doUndoOneGuess();
+ break;
+ case kMars57RedMoveSpotID:
+ playSpotSoundSync(kMarsColorMatchingButtonBeepIn, kMarsColorMatchingButtonBeepOut);
+ doReactorGuess(0);
+ break;
+ case kMars57YellowMoveSpotID:
+ playSpotSoundSync(kMarsColorMatchingButtonBeepIn, kMarsColorMatchingButtonBeepOut);
+ doReactorGuess(1);
+ break;
+ case kMars57GreenMoveSpotID:
+ playSpotSoundSync(kMarsColorMatchingButtonBeepIn, kMarsColorMatchingButtonBeepOut);
+ doReactorGuess(2);
+ break;
+ case kMars57BlueMoveSpotID:
+ playSpotSoundSync(kMarsColorMatchingButtonBeepIn, kMarsColorMatchingButtonBeepOut);
+ doReactorGuess(3);
+ break;
+ case kMars57PurpleMoveSpotID:
+ playSpotSoundSync(kMarsColorMatchingButtonBeepIn, kMarsColorMatchingButtonBeepOut);
+ doReactorGuess(4);
+ break;
+ case kShuttleEnergySpotID:
+ case kShuttleGravitonSpotID:
+ case kShuttleTractorSpotID:
+ case kShuttleViewSpotID:
+ case kShuttleTransportSpotID:
+ spaceChaseClick(input, clickedSpot->getObjectID());
+ break;
+ default:
+ Neighborhood::clickInHotspot(input, clickedSpot);
+ break;
+ }
+}
+
+InputBits Mars::getInputFilter() {
+ InputBits result = Neighborhood::getInputFilter();
+
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kMars49, kSouth):
+ if (GameState.getMarsMaskOnFiller())
+ // Can't move when mask is on filler.
+ result &= ~kFilterAllDirections;
+ break;
+ case MakeRoomView(kMars52, kNorth):
+ case MakeRoomView(kMars52, kSouth):
+ case MakeRoomView(kMars52, kEast):
+ case MakeRoomView(kMars52, kWest):
+ case MakeRoomView(kMars54, kNorth):
+ case MakeRoomView(kMars54, kSouth):
+ case MakeRoomView(kMars54, kEast):
+ case MakeRoomView(kMars54, kWest):
+ case MakeRoomView(kMars56, kNorth):
+ case MakeRoomView(kMars56, kSouth):
+ case MakeRoomView(kMars56, kEast):
+ case MakeRoomView(kMars56, kWest):
+ case MakeRoomView(kMars58, kNorth):
+ case MakeRoomView(kMars58, kSouth):
+ case MakeRoomView(kMars58, kEast):
+ case MakeRoomView(kMars58, kWest):
+ if (_privateFlags.getFlag(kMarsPrivatePlatformZoomedInFlag))
+ // Can't move when platform is extended.
+ result &= ~kFilterAllDirections;
+ break;
+ case MakeRoomView(kMars44, kWest):
+ if (_canyonChaseMovie.isMovieValid() && _canyonChaseMovie.isRunning())
+ result &= ~kFilterAllDirections;
+ break;
+ }
+
+ return result;
+}
+
+// Only called when trying to pick up an item and the player can't (because
+// the inventory is too full or because the player lets go of the item before
+// dropping it into the inventory).
+Hotspot *Mars::getItemScreenSpot(Item *item, DisplayElement *element) {
+ HotSpotID destSpotID;
+
+ switch (item->getObjectID()) {
+ case kCardBomb:
+ destSpotID = kMars57GrabBombSpotID;
+ break;
+ case kMarsCard:
+ destSpotID = kMars31SouthCardSpotID;
+ break;
+ case kAirMask:
+ if (GameState.getMarsMaskOnFiller())
+ destSpotID = kMars49AirFillingDropSpotID;
+ else
+ destSpotID = kMars49AirMaskSpotID;
+ break;
+ case kCrowbar:
+ if (GameState.getCurrentRoom() == kMars34)
+ destSpotID = kMars34SouthCrowbarSpotID;
+ else
+ destSpotID = kMars45NorthCrowbarSpotID;
+ break;
+ case kMapBiochip:
+ destSpotID = kRobotShuttleMapChipSpotID;
+ break;
+ case kOpticalBiochip:
+ destSpotID = kRobotShuttleOpticalChipSpotID;
+ break;
+ case kShieldBiochip:
+ destSpotID = kRobotShuttleShieldChipSpotID;
+ break;
+ default:
+ destSpotID = kNoHotSpotID;
+ break;
+ }
+
+ if (destSpotID == kNoHotSpotID)
+ return Neighborhood::getItemScreenSpot(item, element);
+
+ return _vm->getAllHotspots().findHotspotByID(destSpotID);
+}
+
+void Mars::takeItemFromRoom(Item *item) {
+ switch (item->getObjectID()) {
+ case kAirMask:
+ setCurrentAlternate(kAltMarsTookMask);
+ break;
+ case kCardBomb:
+ _privateFlags.setFlag(kMarsPrivateDraggingBombFlag, true);
+ break;
+ case kMapBiochip:
+ _privateFlags.setFlag(kMarsPrivateGotMapChipFlag, true);
+ break;
+ case kShieldBiochip:
+ _privateFlags.setFlag(kMarsPrivateGotShieldChipFlag, true);
+ break;
+ case kOpticalBiochip:
+ _privateFlags.setFlag(kMarsPrivateGotOpticalChipFlag, true);
+ break;
+ }
+
+ Neighborhood::takeItemFromRoom(item);
+}
+
+void Mars::pickedUpItem(Item *item) {
+ switch (item->getObjectID()) {
+ case kAirMask:
+ setCurrentActivation(kActivateHotSpotAlways);
+ if (!GameState.getScoringGotOxygenMask()) {
+ g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/Mars/XM48SB", false, kWarningInterruption);
+ GameState.setScoringGotOxygenMask();
+ }
+ break;
+ case kCrowbar:
+ GameState.setScoringGotCrowBar();
+ g_AIArea->checkMiddleArea();
+ break;
+ case kMarsCard:
+ GameState.setScoringGotMarsCard();
+ g_AIArea->checkMiddleArea();
+ break;
+ case kCardBomb:
+ GameState.setScoringGotCardBomb();
+ if (GameState.getMarsLockBroken()) {
+ startExtraSequence(kMars57BackToNormal, kExtraCompletedFlag, kFilterNoInput);
+ GameState.setMarsLockBroken(false);
+ }
+
+ _privateFlags.setFlag(kMarsPrivateDraggingBombFlag, false);
+ break;
+ case kMapBiochip:
+ if (_privateFlags.getFlag(kMarsPrivateGotMapChipFlag) &&
+ _privateFlags.getFlag(kMarsPrivateGotShieldChipFlag) &&
+ _privateFlags.getFlag(kMarsPrivateGotOpticalChipFlag)) {
+ GameState.setMarsFinished(true);
+ GameState.setScoringMarsGandhi();
+ startExtraSequence(kMarsRobotHeadClose, kExtraCompletedFlag, kFilterNoInput);
+ }
+ break;
+ case kShieldBiochip:
+ if (_privateFlags.getFlag(kMarsPrivateGotMapChipFlag) &&
+ _privateFlags.getFlag(kMarsPrivateGotShieldChipFlag) &&
+ _privateFlags.getFlag(kMarsPrivateGotOpticalChipFlag)) {
+ GameState.setMarsFinished(true);
+ GameState.setScoringMarsGandhi();
+ startExtraSequence(kMarsRobotHeadClose, kExtraCompletedFlag, kFilterNoInput);
+ }
+ break;
+ case kOpticalBiochip:
+ g_opticalChip->addAries();
+ GameState.setScoringGotMarsOpMemChip();
+
+ if (_privateFlags.getFlag(kMarsPrivateGotMapChipFlag) &&
+ _privateFlags.getFlag(kMarsPrivateGotShieldChipFlag) &&
+ _privateFlags.getFlag(kMarsPrivateGotOpticalChipFlag)) {
+ GameState.setMarsFinished(true);
+ GameState.setScoringMarsGandhi();
+ startExtraSequence(kMarsRobotHeadClose, kExtraCompletedFlag, kFilterNoInput);
+ }
+ break;
+ }
+}
+
+void Mars::dropItemIntoRoom(Item *item, Hotspot *dropSpot) {
+ if (dropSpot->getObjectID() == kAttackRobotHotSpotID) {
+ _attackingItem = (InventoryItem *)item;
+ startExtraSequence(kMars48RobotDefends, kExtraCompletedFlag, kFilterNoInput);
+ loadLoopSound2("");
+ } else {
+ switch (item->getObjectID()) {
+ case kMarsCard:
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ if (dropSpot && dropSpot->getObjectID() == kMars34NorthCardDropSpotID)
+ startExtraSequence(kMarsTurnOnPod, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kNitrogenCanister:
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ if (dropSpot && dropSpot->getObjectID() == kMars57DropNitrogenSpotID)
+ startExtraSequence(kMars57FreezeLock, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kCrowbar:
+ _utilityFuse.stopFuse();
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ if (dropSpot && dropSpot->getObjectID() == kMars57DropCrowBarSpotID)
+ startExtraSequence(kMars57BreakLock, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kAirMask:
+ if (dropSpot) {
+ if (dropSpot->getObjectID() == kMars49AirFillingDropSpotID) {
+ if (!GameState.getMarsMaskOnFiller()) {
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ startExtraSequence(kMars49SouthViewMaskFilling, kExtraCompletedFlag, kFilterNoInput);
+ } else {
+ setCurrentActivation(kActivateMaskOnFiller);
+ setCurrentAlternate(kAltMarsMaskOnFiller);
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ }
+ } else if (dropSpot->getObjectID() == kMars49AirMaskSpotID) {
+ setCurrentAlternate(kAltMarsNormal);
+ setCurrentActivation(kActivateMaskOnHolder);
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ }
+ }
+ break;
+ case kCardBomb:
+ _privateFlags.setFlag(kMarsPrivateDraggingBombFlag, false);
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ break;
+ case kMapBiochip:
+ _privateFlags.setFlag(kMarsPrivateGotMapChipFlag, false);
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ break;
+ case kShieldBiochip:
+ _privateFlags.setFlag(kMarsPrivateGotShieldChipFlag, false);
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ break;
+ case kOpticalBiochip:
+ _privateFlags.setFlag(kMarsPrivateGotOpticalChipFlag, false);
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ break;
+ default:
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ break;
+ }
+ }
+}
+
+void Mars::robotTiredOfWaiting() {
+ if (GameState.getCurrentRoomAndView() == MakeRoomView(kMars48, kEast)) {
+ if (_attackingItem) {
+ startExtraSequence(kMars48RobotKillsPlayer, kExtraCompletedFlag, kFilterNoInput);
+ loadLoopSound2("");
+ } else {
+ _privateFlags.setFlag(kMarsPrivateRobotTiredOfWaitingFlag, true);
+ }
+ } else {
+ die(kDeathDidntGetOutOfWay);
+ }
+}
+
+void Mars::turnLeft() {
+ if (isEventTimerRunning())
+ cancelEvent();
+
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kMars34, kSouth):
+ if (_privateFlags.getFlag(kMarsPrivatePodStorageOpenFlag)) {
+ _privateFlags.setFlag(kMarsPrivatePodTurnLeftFlag, true);
+ if (GameState.isTakenItemID(kCrowbar))
+ startExtraSequence(kMars34SpotCloseNoBar, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraSequence(kMars34SpotCloseWithBar, kExtraCompletedFlag, kFilterNoInput);
+ } else {
+ Neighborhood::turnLeft();
+ }
+ break;
+ case MakeRoomView(kMars45, kNorth):
+ if (_privateFlags.getFlag(kMarsPrivatePodStorageOpenFlag)) {
+ _privateFlags.setFlag(kMarsPrivatePodTurnLeftFlag, true);
+ if (GameState.isTakenItemID(kCrowbar))
+ startExtraSequence(kMars45SpotCloseNoBar, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraSequence(kMars45SpotCloseWithBar, kExtraCompletedFlag, kFilterNoInput);
+ } else {
+ Neighborhood::turnLeft();
+ }
+ break;
+ default:
+ Neighborhood::turnLeft();
+ break;
+ }
+}
+
+void Mars::turnRight() {
+ if (isEventTimerRunning())
+ cancelEvent();
+
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kMars34, kSouth):
+ if (_privateFlags.getFlag(kMarsPrivatePodStorageOpenFlag)) {
+ _privateFlags.setFlag(kMarsPrivatePodTurnRightFlag, true);
+ if (GameState.isTakenItemID(kCrowbar))
+ startExtraSequence(kMars34SpotCloseNoBar, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraSequence(kMars34SpotCloseWithBar, kExtraCompletedFlag, kFilterNoInput);
+ } else {
+ Neighborhood::turnRight();
+ }
+ break;
+ case MakeRoomView(kMars45, kNorth):
+ if (_privateFlags.getFlag(kMarsPrivatePodStorageOpenFlag)) {
+ _privateFlags.setFlag(kMarsPrivatePodTurnRightFlag, true);
+ if (GameState.isTakenItemID(kCrowbar))
+ startExtraSequence(kMars45SpotCloseNoBar, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraSequence(kMars45SpotCloseWithBar, kExtraCompletedFlag, kFilterNoInput);
+ } else {
+ Neighborhood::turnRight();
+ }
+ break;
+ default:
+ Neighborhood::turnRight();
+ break;
+ }
+}
+
+void Mars::receiveNotification(Notification *notification, const NotificationFlags flag) {
+ InventoryItem *item;
+
+ Neighborhood::receiveNotification(notification, flag);
+
+ if ((flag & kExtraCompletedFlag) != 0) {
+ _interruptionFilter = kFilterAllInput;
+
+ switch (_lastExtra) {
+ case kMarsArrivalFromTSA:
+ GameState.setMarsSeenTimeStream(true);
+ loadAmbientLoops();
+ playSpotSoundSync(kMarsShuttle1DepartedIn, kMarsShuttle1DepartedOut);
+ makeContinuePoint();
+ break;
+ case kRobotThrowsPlayer:
+ GameState.setMarsRobotThrownPlayer(true);
+ GameState.setScoringThrownByRobot();
+ restoreStriding(kMars08, kNorth, kAltMarsNormal);
+ arriveAt(kMars08, kNorth);
+ if (!GameState.getMarsHeardUpperPodMessage()) {
+ playSpotSoundSync(kMarsPodDepartedUpperPlatformIn,
+ kMarsPodDepartedUpperPlatformOut);
+ GameState.setMarsHeardUpperPodMessage(true);
+ }
+ break;
+ case kMarsInfoKioskIntro:
+ GameState.setScoringSawMarsKiosk();
+ setCurrentActivation(kActivationKioskChoice);
+ break;
+ case kMars33SlideShow4:
+ GameState.setScoringSawTransportMap();
+ setCurrentActivation(kActivateHotSpotAlways);
+ break;
+ case kMars34SpotOpenNoBar:
+ case kMars34SpotOpenWithBar:
+ case kMars45SpotOpenNoBar:
+ case kMars45SpotOpenWithBar:
+ _privateFlags.setFlag(kMarsPrivatePodStorageOpenFlag, true);
+ setCurrentActivation(kActivateMarsPodOpen);
+ break;
+ case kMars34SpotCloseNoBar:
+ case kMars34SpotCloseWithBar:
+ case kMars45SpotCloseNoBar:
+ case kMars45SpotCloseWithBar:
+ _privateFlags.setFlag(kMarsPrivatePodStorageOpenFlag, false);
+ setCurrentActivation(kActivateMarsPodClosed);
+ if (_privateFlags.getFlag(kMarsPrivatePodTurnLeftFlag)) {
+ _privateFlags.setFlag(kMarsPrivatePodTurnLeftFlag, false);
+ turnLeft();
+ } else if (_privateFlags.getFlag(kMarsPrivatePodTurnRightFlag)) {
+ _privateFlags.setFlag(kMarsPrivatePodTurnRightFlag, false);
+ turnRight();
+ }
+ break;
+ case kMarsTurnOnPod:
+ item = (InventoryItem *)_vm->getAllItems().findItemByID(kMarsCard);
+ _vm->addItemToInventory(item);
+ GameState.setScoringTurnedOnTransport();
+ loadLoopSound1("");
+ loadLoopSound2("");
+ startExtraSequence(kMarsTakePodToMars45, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kMarsTakePodToMars45:
+ arriveAt(kMars45, kSouth);
+ break;
+ case kMars35WestSpinAirlockToEast:
+ GameState.setMarsAirlockOpen(false);
+ setCurrentAlternate(kAltMars35AirlockEast);
+ turnTo(kWest);
+ setCurrentActivation(kActivateReadyToPressurizeAirlock);
+ g_airMask->airQualityChanged();
+ checkAirMask();
+ loadAmbientLoops();
+ break;
+ case kMars35EastSpinAirlockToWest:
+ GameState.setMarsAirlockOpen(true);
+ setCurrentAlternate(kAltMars35AirlockWest);
+ turnTo(kEast);
+ setCurrentActivation(kActivateReadyToPressurizeAirlock);
+ g_airMask->airQualityChanged();
+ checkAirMask();
+ loadAmbientLoops();
+ break;
+ case kMars48RobotApproaches:
+ loadLoopSound2("Sounds/Mars/Robot Loop.aiff", 0x100, 0, 0);
+ GameState.setMarsSeenRobotAtReactor(true);
+ loopExtraSequence(kMars48RobotLoops);
+ _utilityFuse.primeFuse(kMarsRobotPatienceLimit);
+ _utilityFuse.setFunctor(new Common::Functor0Mem<void, Mars>(this, &Mars::robotTiredOfWaiting));
+ _utilityFuse.lightFuse();
+ break;
+ case kMars48RobotDefends:
+ _vm->addItemToInventory(_attackingItem);
+ _attackingItem = 0;
+ if (_privateFlags.getFlag(kMarsPrivateRobotTiredOfWaitingFlag)) {
+ startExtraSequence(kMars48RobotKillsPlayer, kExtraCompletedFlag, kFilterNoInput);
+ loadLoopSound2("", 0x100, 0, 0);
+ } else {
+ loadLoopSound2("Sounds/Mars/Robot Loop.aiff", 0x100, 0, 0);
+ loopExtraSequence(kMars48RobotLoops, kExtraCompletedFlag);
+ }
+ break;
+ case kMars48RobotKillsPlayer:
+ loadLoopSound2("");
+ die(kDeathDidntGetOutOfWay);
+ break;
+ case kMars49SouthViewMaskFilling:
+ setCurrentActivation(kActivateMaskOnFiller);
+ setCurrentAlternate(kAltMarsMaskOnFiller);
+ GameState.setMarsMaskOnFiller(true);
+ break;
+ case kMars58SpinLeft:
+ case kMars54SpinRight:
+ GameState.setScoringActivatedPlatform();
+ arriveAt(kMars52, kEast);
+ break;
+ case kMars52SpinLeft:
+ case kMars56SpinRight:
+ GameState.setScoringActivatedPlatform();
+ arriveAt(kMars54, kEast);
+ break;
+ case kMars54SpinLeft:
+ case kMars58SpinRight:
+ GameState.setScoringActivatedPlatform();
+ arriveAt(kMars56, kEast);
+ break;
+ case kMars56SpinLeft:
+ case kMars52SpinRight:
+ GameState.setScoringActivatedPlatform();
+ arriveAt(kMars58, kEast);
+ break;
+ case kMars52Extend:
+ case kMars54Extend:
+ case kMars56ExtendNoBomb:
+ case kMars58Extend:
+ GameState.setScoringActivatedPlatform();
+ setCurrentActivation(kActivateReactorPlatformIn);
+ _privateFlags.setFlag(kMarsPrivatePlatformZoomedInFlag, true);
+ break;
+ case kMars53Retract:
+ case kMars55Retract:
+ case kMars57RetractWithBomb:
+ case kMars57RetractNoBomb:
+ case kMars59Retract:
+ GameState.setScoringActivatedPlatform();
+ setCurrentActivation(kActivateReactorPlatformOut);
+ _privateFlags.setFlag(kMarsPrivatePlatformZoomedInFlag, false);
+ break;
+ case kMars56ExtendWithBomb:
+ playSpotSoundSync(kMustBeUnlockedIn, kMustBeUnlockedOut);
+ GameState.setScoringActivatedPlatform();
+ _privateFlags.setFlag(kMarsPrivatePlatformZoomedInFlag, true);
+ break;
+ case kMars57CantOpenPanel:
+ GameState.setScoringActivatedPlatform();
+ setCurrentActivation(kActivateReactorAskLowerScreen);
+ break;
+ case kMars57LowerScreenClosed:
+ case kMars57ThawLock:
+ setCurrentActivation(kActivateReactorReadyForNitrogen);
+ GameState.setMarsLockFrozen(false);
+ break;
+ case kMars57FreezeLock:
+ item = (InventoryItem *)_vm->getAllItems().findItemByID(kNitrogenCanister);
+ item->setItemState(kNitrogenEmpty);
+ _vm->addItemToInventory(item);
+ setCurrentActivation(kActivateReactorReadyForCrowBar);
+ GameState.setScoringUsedLiquidNitrogen();
+ GameState.setMarsLockFrozen(true);
+ showExtraView(kMars57LockFrozenView);
+ _utilityFuse.primeFuse(kLockFreezeTimeLmit);
+ _utilityFuse.setFunctor(new Common::Functor0Mem<void, Mars>(this, &Mars::lockThawed));
+ _utilityFuse.lightFuse();
+ break;
+ case kMars57BreakLock:
+ item = (InventoryItem *)_vm->getAllItems().findItemByID(kCrowbar);
+ _vm->addItemToInventory(item);
+ GameState.setScoringUsedCrowBar();
+ GameState.setMarsLockBroken(true);
+ GameState.setMarsLockFrozen(false);
+ startExtraLongSequence(kMars57OpenPanel, kMars57OpenPanelChoices, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kMars57OpenPanel:
+ case kMars57OpenPanelChoices:
+ setCurrentActivation(kActivateReactorAskOperation);
+ break;
+ case kMars57ShieldEvaluation:
+ case kMars57MeasureOutput:
+ setCurrentActivation(kActivateReactorRanEvaluation);
+ loopExtraSequence(kMars57ShieldOkayLoop);
+ break;
+ case kMars57RunDiagnostics:
+ setCurrentActivation(kActivateReactorRanDiagnostics);
+ GameState.setScoringFoundCardBomb();
+ break;
+ case kMars57BombExplodes:
+ case kMars57BombExplodesInGame:
+ die(kDeathDidntDisarmMarsBomb);
+ break;
+ case kMars57BombAnalysis:
+ setCurrentActivation(kActivateReactorAnalyzed);
+ break;
+ case kMars57DontLink:
+ startExtraSequence(kMars57OpenPanelChoices, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kMars57CircuitLink:
+ setCurrentActivation(kActivateReactorInstructions);
+ break;
+ case kMars57GameLevel1:
+ setUpReactorLevel1();
+ break;
+ case kMars57GameLevel2:
+ case kMars57GameLevel3:
+ setUpNextReactorLevel();
+ break;
+ case kMars57GameSolved:
+ setCurrentActivation(kActivateReactorBombSafe);
+ break;
+ case kMars57ExposeBomb:
+ setCurrentActivation(kActivateReactorBombExposed);
+ _privateFlags.setFlag(kMarsPrivateBombExposedFlag, true);
+ break;
+ case kMars57BackToNormal:
+ setCurrentActivation(kActivateReactorPlatformIn);
+ _privateFlags.setFlag(kMarsPrivateBombExposedFlag, false);
+ g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/Mars/XM51SW", false, kWarningInterruption);
+ break;
+ case kMars60WestSpinAirlockToEast:
+ GameState.setMarsAirlockOpen(true);
+ setCurrentAlternate(kAltMars60AirlockEast);
+ turnTo(kWest);
+ setCurrentActivation(kActivateReadyToPressurizeAirlock);
+ g_airMask->airQualityChanged();
+ checkAirMask();
+ loadAmbientLoops();
+ break;
+ case kMars60EastSpinAirlockToWest:
+ GameState.setMarsAirlockOpen(false);
+ setCurrentAlternate(kAltMars60AirlockWest);
+ turnTo(kEast);
+ setCurrentActivation(kActivateReadyToPressurizeAirlock);
+ g_airMask->airQualityChanged();
+ checkAirMask();
+ loadAmbientLoops();
+ break;
+ case kMarsRobotHeadOpen:
+ setCurrentActivation(kActivationRobotHeadOpen);
+ break;
+ case kMarsRobotHeadClose:
+ recallToTSASuccess();
+ break;
+ case kMarsMaze007RobotApproach:
+ case kMarsMaze015SouthRobotApproach:
+ case kMarsMaze101EastRobotApproach:
+ case kMarsMaze104WestLoop:
+ case kMarsMaze133SouthApproach:
+ case kMarsMaze136NorthApproach:
+ case kMarsMaze184WestLoop:
+ die(kDeathGroundByMazebot);
+ break;
+ }
+ } else if ((flag & kTimeForCanyonChaseFlag) != 0) {
+ doCanyonChase();
+ } else if ((flag & kExplosionFinishedFlag) != 0) {
+ _explosions.stop();
+ _explosions.hide();
+ if (g_robotShip->isDead()) {
+ GameState.setMarsFinished(true);
+ _centerShuttleMovie.hide();
+ _upperRightShuttleMovie.show();
+ _upperRightShuttleMovie.setTime(kShuttleUpperRightTargetDestroyedTime);
+ _upperRightShuttleMovie.redrawMovieWorld();
+ _rightDamageShuttleMovie.hide();
+ playMovieSegment(&_rightShuttleMovie, kShuttleRightDestroyedStart, kShuttleRightDestroyedStop);
+ playSpotSoundSync(kShuttleDestroyedIn, kShuttleDestroyedOut);
+ throwAwayMarsShuttle();
+ reinstateMonocleInterface();
+ recallToTSASuccess();
+ }
+ } else if ((flag & kTimeToTransportFlag) != 0) {
+ transportToRobotShip();
+ }
+
+ if (g_AIArea)
+ g_AIArea->checkMiddleArea();
+}
+
+void Mars::spotCompleted() {
+ Neighborhood::spotCompleted();
+
+ if (GameState.getCurrentRoom() == kMarsRobotShuttle)
+ g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/Mars/XN59WD", false, kWarningInterruption);
+}
+
+void Mars::doCanyonChase() {
+ GameState.setScoringEnteredShuttle();
+ setNextHandler(_vm);
+ throwAwayInterface();
+
+ _vm->_cursor->hide();
+
+ // Open the spot sounds movie again...
+ _spotSounds.initFromQuickTime(getSoundSpotsName());
+ _spotSounds.setVolume(_vm->getSoundFXLevel());
+
+ Video::VideoDecoder *video = new Video::QuickTimeDecoder();
+ if (!video->loadFile("Images/Mars/M44ESA.movie"))
+ error("Could not load interface->shuttle transition video");
+
+ video->start();
+
+ while (!_vm->shouldQuit() && !video->endOfVideo()) {
+ if (video->needsUpdate()) {
+ const Graphics::Surface *frame = video->decodeNextFrame();
+
+ if (frame)
+ _vm->drawScaledFrame(frame, 0, 0);
+ }
+
+ Common::Event event;
+ while (g_system->getEventManager()->pollEvent(event))
+ ;
+
+ g_system->delayMillis(10);
+ }
+
+ delete video;
+
+ if (_vm->shouldQuit())
+ return;
+
+ initOnePicture(&_shuttleInterface1, "Images/Mars/MCmain1.pict", kShuttleBackgroundOrder, kShuttle1Left,
+ kShuttle1Top, true);
+ initOnePicture(&_shuttleInterface2, "Images/Mars/MCmain2.pict", kShuttleBackgroundOrder, kShuttle2Left,
+ kShuttle2Top, true);
+ initOnePicture(&_shuttleInterface3, "Images/Mars/MCmain3.pict", kShuttleBackgroundOrder, kShuttle3Left,
+ kShuttle3Top, true);
+ initOnePicture(&_shuttleInterface4, "Images/Mars/MCmain4.pict", kShuttleBackgroundOrder, kShuttle4Left,
+ kShuttle4Top, true);
+
+ initOneMovie(&_canyonChaseMovie, "Images/Mars/Canyon.movie",
+ kShuttleMonitorOrder, kShuttleWindowLeft, kShuttleWindowTop, true);
+ _canyonChaseMovie.setVolume(_vm->getSoundFXLevel());
+
+ loadLoopSound1("Sounds/Mars/Inside Cockpit.22K.8.AIFF");
+
+ // Swing shuttle around...
+ playMovieSegment(&_canyonChaseMovie, kShuttleSwingStart, kShuttleSwingStop);
+
+ initOneMovie(&_leftShuttleMovie, "Images/Mars/Left Shuttle.movie",
+ kShuttleMonitorOrder, kShuttleLeftLeft, kShuttleLeftTop, false);
+
+ initOneMovie(&_rightShuttleMovie, "Images/Mars/Right Shuttle.movie",
+ kShuttleMonitorOrder, kShuttleRightLeft, kShuttleRightTop, false);
+
+ initOneMovie(&_lowerLeftShuttleMovie, "Images/Mars/Lower Left Shuttle.movie", kShuttleMonitorOrder,
+ kShuttleLowerLeftLeft, kShuttleLowerLeftTop, false);
+
+ initOneMovie(&_lowerRightShuttleMovie, "Images/Mars/Lower Right Shuttle.movie", kShuttleMonitorOrder,
+ kShuttleLowerRightLeft, kShuttleLowerRightTop, false);
+
+ initOneMovie(&_centerShuttleMovie, "Images/Mars/Center Shuttle.movie",
+ kShuttleMonitorOrder, kShuttleCenterLeft, kShuttleCenterTop, false);
+
+ initOneMovie(&_upperLeftShuttleMovie, "Images/Mars/Upper Left Shuttle.movie", kShuttleMonitorOrder,
+ kShuttleUpperLeftLeft, kShuttleUpperLeftTop, false);
+
+ initOneMovie(&_upperRightShuttleMovie, "Images/Mars/Upper Right Shuttle.movie", kShuttleMonitorOrder,
+ kShuttleUpperRightLeft, kShuttleUpperRightTop, false);
+
+ initOneMovie(&_leftDamageShuttleMovie, "Images/Mars/Left Damage Shuttle.movie",
+ kShuttleStatusOrder, kShuttleLeftEnergyLeft, kShuttleLeftEnergyTop, false);
+
+ initOneMovie(&_rightDamageShuttleMovie, "Images/Mars/Right Damage Shuttle.movie",
+ kShuttleStatusOrder, kShuttleRightEnergyLeft, kShuttleRightEnergyTop, false);
+
+ _centerShuttleMovie.show();
+ _centerShuttleMovie.setTime(kShuttleCenterBoardingTime);
+ playSpotSoundSync(kShuttleCockpitIn, kShuttleCockpitOut);
+
+ _centerShuttleMovie.setTime(kShuttleCenterCheckTime);
+ playSpotSoundSync(kShuttleOnboardIn, kShuttleOnboardOut);
+
+ _shuttleEnergyMeter.initShuttleEnergyMeter();
+ _shuttleEnergyMeter.powerUpMeter();
+ while (_shuttleEnergyMeter.isFading()) {
+ _vm->checkCallBacks();
+ _vm->refreshDisplay();
+ g_system->updateScreen();
+ }
+
+ _leftShuttleMovie.show();
+ playMovieSegment(&_leftShuttleMovie, kShuttleLeftIntroStart, kShuttleLeftIntroStop);
+
+ _leftShuttleMovie.setTime(kShuttleLeftNormalTime);
+ _leftShuttleMovie.redrawMovieWorld();
+
+ _leftDamageShuttleMovie.show();
+ playMovieSegment(&_leftDamageShuttleMovie);
+
+ // Take it down a tick initially. This sets the time to the time of the last tick,
+ // so that subsequence drops will drop it down a tick.
+ _leftDamageShuttleMovie.setTime(_leftDamageShuttleMovie.getTime() - 40);
+ _leftDamageShuttleMovie.redrawMovieWorld();
+
+ _lowerRightShuttleMovie.show();
+ _lowerRightShuttleMovie.setTime(kShuttleLowerRightOffTime);
+ _lowerRightShuttleMovie.redrawMovieWorld();
+ _centerShuttleMovie.setTime(kShuttleCenterNavCompTime);
+ _centerShuttleMovie.redrawMovieWorld();
+ playSpotSoundSync(kShuttleNavigationIn, kShuttleNavigationOut);
+
+ _centerShuttleMovie.setTime(kShuttleCenterCommTime);
+ _centerShuttleMovie.redrawMovieWorld();
+ playSpotSoundSync(kShuttleCommunicationIn, kShuttleCommunicationOut);
+
+ _centerShuttleMovie.setTime(kShuttleCenterAllSystemsTime);
+ _centerShuttleMovie.redrawMovieWorld();
+ playSpotSoundSync(kShuttleAllSystemsIn, kShuttleAllSystemsOut);
+
+ _centerShuttleMovie.setTime(kShuttleCenterSecureLooseTime);
+ _centerShuttleMovie.redrawMovieWorld();
+ playSpotSoundSync(kShuttleSecureLooseIn, kShuttleSecureLooseOut);
+
+ _centerShuttleMovie.setTime(kShuttleCenterAutoTestTime);
+ _centerShuttleMovie.redrawMovieWorld();
+ playSpotSoundSync(kShuttleAutoTestingIn, kShuttleAutoTestingOut);
+
+ _leftShuttleMovie.setTime(kShuttleLeftAutoTestTime);
+ _leftShuttleMovie.redrawMovieWorld();
+ playSpotSoundSync(kMarsThrusterAutoTestIn, kMarsThrusterAutoTestOut);
+ _leftShuttleMovie.setTime(kShuttleLeftNormalTime);
+ _leftShuttleMovie.redrawMovieWorld();
+
+ _centerShuttleMovie.setTime(kShuttleCenterLaunchTime);
+ _centerShuttleMovie.redrawMovieWorld();
+ playSpotSoundSync(kShuttlePrepareForDropIn, kShuttlePrepareForDropOut);
+
+ playSpotSoundSync(kShuttleAllClearIn, kShuttleAllClearOut);
+
+ _centerShuttleMovie.setTime(kShuttleCenterEnterTubeTime);
+ _centerShuttleMovie.redrawMovieWorld();
+
+ _lowerLeftShuttleMovie.show();
+ _lowerLeftShuttleMovie.setTime(kShuttleLowerLeftCollisionTime);
+
+ loadLoopSound1("");
+
+ _canyonChaseMovie.setSegment(kCanyonChaseStart, kCanyonChaseStop);
+ _canyonChaseMovie.start();
+
+ startMarsTimer(kLaunchTubeReachedTime, kMovieTicksPerSecond, kMarsLaunchTubeReached);
+}
+
+void Mars::startUpFromFinishedSpaceChase() {
+ setNextHandler(_vm);
+ throwAwayInterface();
+
+ initOnePicture(&_shuttleInterface1, "Images/Mars/MCmain1.pict", kShuttleBackgroundOrder, kShuttle1Left,
+ kShuttle1Top, true);
+ initOnePicture(&_shuttleInterface2, "Images/Mars/MCmain2.pict", kShuttleBackgroundOrder, kShuttle2Left,
+ kShuttle2Top, true);
+ initOnePicture(&_shuttleInterface3, "Images/Mars/MCmain3.pict", kShuttleBackgroundOrder, kShuttle3Left,
+ kShuttle3Top, true);
+ initOnePicture(&_shuttleInterface4, "Images/Mars/MCmain4.pict", kShuttleBackgroundOrder, kShuttle4Left,
+ kShuttle4Top, true);
+
+ initOneMovie(&_leftShuttleMovie, "Images/Mars/Left Shuttle.movie",
+ kShuttleMonitorOrder, kShuttleLeftLeft, kShuttleLeftTop, false);
+
+ initOneMovie(&_rightShuttleMovie, "Images/Mars/Right Shuttle.movie",
+ kShuttleMonitorOrder, kShuttleRightLeft, kShuttleRightTop, false);
+
+ initOneMovie(&_lowerLeftShuttleMovie, "Images/Mars/Lower Left Shuttle.movie", kShuttleMonitorOrder,
+ kShuttleLowerLeftLeft, kShuttleLowerLeftTop, false);
+
+ initOneMovie(&_lowerRightShuttleMovie, "Images/Mars/Lower Right Shuttle.movie", kShuttleMonitorOrder,
+ kShuttleLowerRightLeft, kShuttleLowerRightTop, false);
+
+ initOneMovie(&_centerShuttleMovie, "Images/Mars/Center Shuttle.movie",
+ kShuttleMonitorOrder, kShuttleCenterLeft, kShuttleCenterTop, false);
+
+ initOneMovie(&_upperLeftShuttleMovie, "Images/Mars/Upper Left Shuttle.movie", kShuttleMonitorOrder,
+ kShuttleUpperLeftLeft, kShuttleUpperLeftTop, false);
+
+ initOneMovie(&_upperRightShuttleMovie, "Images/Mars/Upper Right Shuttle.movie", kShuttleMonitorOrder,
+ kShuttleUpperRightLeft, kShuttleUpperRightTop, false);
+
+ initOneMovie(&_leftDamageShuttleMovie, "Images/Mars/Left Damage Shuttle.movie",
+ kShuttleStatusOrder, kShuttleLeftEnergyLeft, kShuttleLeftEnergyTop, false);
+
+ initOneMovie(&_rightDamageShuttleMovie, "Images/Mars/Right Damage Shuttle.movie",
+ kShuttleStatusOrder, kShuttleRightEnergyLeft, kShuttleRightEnergyTop, false);
+
+ _centerShuttleMovie.show();
+
+ _shuttleEnergyMeter.initShuttleEnergyMeter();
+ _shuttleEnergyMeter.setEnergyValue(kFullShuttleEnergy);
+
+ _leftShuttleMovie.show();
+ _leftShuttleMovie.setTime(kShuttleLeftNormalTime);
+ _leftShuttleMovie.redrawMovieWorld();
+
+ _leftDamageShuttleMovie.show();
+ _leftDamageShuttleMovie.setTime(_leftDamageShuttleMovie.getDuration() - 40);
+ _leftDamageShuttleMovie.redrawMovieWorld();
+
+ _lowerRightShuttleMovie.show();
+
+ _lowerLeftShuttleMovie.show();
+
+ loadLoopSound1("Sounds/Mars/Space Ambient.22K.8.AIFF");
+
+ initOneMovie(&_junk, "Images/Mars/Junk.movie", kShuttleJunkOrder, kShuttleJunkLeft,
+ kShuttleJunkTop, false);
+
+ initOneMovie(&_explosions, "Images/Mars/Explosions.movie", kShuttleWeaponFrontOrder, 0, 0, false);
+ _explosionCallBack.initCallBack(&_explosions, kCallBackAtExtremes);
+
+ _energyBeam.initShuttleWeapon();
+ _gravitonCannon.initShuttleWeapon();
+
+ _upperLeftShuttleMovie.show();
+ _upperLeftShuttleMovie.setTime(kShuttleUpperLeftDimTime);
+ _upperLeftShuttleMovie.redrawMovieWorld();
+
+ _rightShuttleMovie.show();
+ _rightShuttleMovie.setTime(kShuttleRightIntroStop - 1);
+ _rightShuttleMovie.redrawMovieWorld();
+
+ _rightDamageShuttleMovie.show();
+ _rightDamageShuttleMovie.setTime(40);
+ _rightDamageShuttleMovie.redrawMovieWorld();
+
+ _lowerLeftShuttleMovie.setTime(kShuttleLowerLeftAutopilotTime);
+ _lowerLeftShuttleMovie.redrawMovieWorld();
+
+ _shuttleTransportSpot.setArea(kShuttleTransportBounds);
+ _shuttleTransportSpot.setHotspotFlags(kNeighborhoodSpotFlag | kClickSpotFlag);
+ _vm->getAllHotspots().push_back(&_shuttleTransportSpot);
+
+ _privateFlags.setFlag(kMarsPrivateInSpaceChaseFlag, true);
+
+ _upperRightShuttleMovie.show();
+ _upperRightShuttleMovie.setTime(kShuttleUpperRightOverloadTime);
+ _upperRightShuttleMovie.redrawMovieWorld();
+
+ _centerShuttleMovie.setTime(kShuttleCenterSafeTime);
+ _centerShuttleMovie.redrawMovieWorld();
+
+ _lowerRightShuttleMovie.setTime(kShuttleLowerRightTransportTime);
+ _lowerRightShuttleMovie.redrawMovieWorld();
+
+ initOneMovie(&_canyonChaseMovie, "Images/Mars/M98EAS.movie", kShuttleTractorBeamMovieOrder,
+ kShuttleWindowLeft, kShuttleWindowTop, true);
+ _canyonChaseMovie.setTime(_canyonChaseMovie.getDuration());
+ _canyonChaseMovie.redrawMovieWorld();
+}
+
+void Mars::startUpFromSpaceChase() {
+ setNextHandler(_vm);
+ throwAwayInterface();
+
+ // Open the spot sounds movie again...
+ _spotSounds.initFromQuickTime(getSoundSpotsName());
+ _spotSounds.setVolume(_vm->getSoundFXLevel());;
+
+ initOnePicture(&_shuttleInterface1, "Images/Mars/MCmain1.pict", kShuttleBackgroundOrder, kShuttle1Left,
+ kShuttle1Top, true);
+ initOnePicture(&_shuttleInterface2, "Images/Mars/MCmain2.pict", kShuttleBackgroundOrder, kShuttle2Left,
+ kShuttle2Top, true);
+ initOnePicture(&_shuttleInterface3, "Images/Mars/MCmain3.pict", kShuttleBackgroundOrder, kShuttle3Left,
+ kShuttle3Top, true);
+ initOnePicture(&_shuttleInterface4, "Images/Mars/MCmain4.pict", kShuttleBackgroundOrder, kShuttle4Left,
+ kShuttle4Top, true);
+
+ initOneMovie(&_leftShuttleMovie, "Images/Mars/Left Shuttle.movie",
+ kShuttleMonitorOrder, kShuttleLeftLeft, kShuttleLeftTop, false);
+
+ initOneMovie(&_rightShuttleMovie, "Images/Mars/Right Shuttle.movie",
+ kShuttleMonitorOrder, kShuttleRightLeft, kShuttleRightTop, false);
+
+ initOneMovie(&_lowerLeftShuttleMovie, "Images/Mars/Lower Left Shuttle.movie", kShuttleMonitorOrder,
+ kShuttleLowerLeftLeft, kShuttleLowerLeftTop, false);
+
+ initOneMovie(&_lowerRightShuttleMovie, "Images/Mars/Lower Right Shuttle.movie", kShuttleMonitorOrder,
+ kShuttleLowerRightLeft, kShuttleLowerRightTop, false);
+
+ initOneMovie(&_centerShuttleMovie, "Images/Mars/Center Shuttle.movie",
+ kShuttleMonitorOrder, kShuttleCenterLeft, kShuttleCenterTop, false);
+
+ initOneMovie(&_upperLeftShuttleMovie, "Images/Mars/Upper Left Shuttle.movie", kShuttleMonitorOrder,
+ kShuttleUpperLeftLeft, kShuttleUpperLeftTop, false);
+
+ initOneMovie(&_upperRightShuttleMovie, "Images/Mars/Upper Right Shuttle.movie", kShuttleMonitorOrder,
+ kShuttleUpperRightLeft, kShuttleUpperRightTop, false);
+
+ initOneMovie(&_leftDamageShuttleMovie, "Images/Mars/Left Damage Shuttle.movie",
+ kShuttleStatusOrder, kShuttleLeftEnergyLeft, kShuttleLeftEnergyTop, false);
+
+ initOneMovie(&_rightDamageShuttleMovie, "Images/Mars/Right Damage Shuttle.movie",
+ kShuttleStatusOrder, kShuttleRightEnergyLeft, kShuttleRightEnergyTop, false);
+
+ _centerShuttleMovie.show();
+
+ _shuttleEnergyMeter.initShuttleEnergyMeter();
+ _shuttleEnergyMeter.setEnergyValue(kFullShuttleEnergy);
+
+ _leftShuttleMovie.show();
+ _leftShuttleMovie.setTime(kShuttleLeftNormalTime);
+ _leftShuttleMovie.redrawMovieWorld();
+
+ _leftDamageShuttleMovie.show();
+ _leftDamageShuttleMovie.setTime(_leftDamageShuttleMovie.getDuration() - 40);
+ _leftDamageShuttleMovie.redrawMovieWorld();
+
+ _lowerRightShuttleMovie.show();
+
+ _lowerLeftShuttleMovie.show();
+
+ loadLoopSound1("Sounds/Mars/Space Ambient.22K.8.AIFF");
+
+ initOneMovie(&_planetMovie, "Images/Mars/Planet.movie", kShuttlePlanetOrder,
+ kPlanetStartLeft, kPlanetStartTop, true);
+ _planetMovie.setFlags(kLoopTimeBase);
+
+ initOneMovie(&_junk, "Images/Mars/Junk.movie", kShuttleJunkOrder, kShuttleJunkLeft,
+ kShuttleJunkTop, false);
+
+ initOneMovie(&_explosions, "Images/Mars/Explosions.movie", kShuttleWeaponFrontOrder, 0, 0, false);
+ _explosionCallBack.initCallBack(&_explosions, kCallBackAtExtremes);
+
+ _energyBeam.initShuttleWeapon();
+ _gravitonCannon.initShuttleWeapon();
+
+ _upperLeftShuttleMovie.show();
+
+ _robotShip.initRobotShip();
+
+ _planetMovie.start();
+ _planetMover.startMoving(&_planetMovie);
+
+ _upperLeftShuttleMovie.setTime(kShuttleUpperLeftDimTime);
+ _upperLeftShuttleMovie.redrawMovieWorld();
+
+ _centerShuttleMovie.setTime(kShuttleCenterTargetSightedTime);
+ _centerShuttleMovie.redrawMovieWorld();
+
+ _lowerRightShuttleMovie.setTime(kShuttleLowerRightTrackingTime);
+ _lowerRightShuttleMovie.redrawMovieWorld();
+
+ _rightShuttleMovie.show();
+ _rightShuttleMovie.setTime(kShuttleRightIntroStop - 1);
+ _rightShuttleMovie.redrawMovieWorld();
+
+ _rightDamageShuttleMovie.show();
+ _rightDamageShuttleMovie.setTime(_rightDamageShuttleMovie.getDuration() - 40);
+ _rightDamageShuttleMovie.redrawMovieWorld();
+
+ _lowerLeftShuttleMovie.setTime(kShuttleLowerLeftAutopilotTime);
+ _lowerLeftShuttleMovie.redrawMovieWorld();
+
+ _robotShip.startMoving();
+
+ _shuttleHUD.initShuttleHUD();
+
+ _tractorBeam.startDisplaying();
+
+ _energyChoiceSpot.setArea(kShuttleEnergyBeamBounds);
+ _energyChoiceSpot.setHotspotFlags(kNeighborhoodSpotFlag | kClickSpotFlag);
+ _vm->getAllHotspots().push_back(&_energyChoiceSpot);
+ _gravitonChoiceSpot.setArea(kShuttleGravitonBounds);
+ _gravitonChoiceSpot.setHotspotFlags(kNeighborhoodSpotFlag | kClickSpotFlag);
+ _vm->getAllHotspots().push_back(&_gravitonChoiceSpot);
+ _tractorChoiceSpot.setArea(kShuttleTractorBounds);
+ _tractorChoiceSpot.setHotspotFlags(kNeighborhoodSpotFlag | kClickSpotFlag);
+ _vm->getAllHotspots().push_back(&_tractorChoiceSpot);
+ _shuttleViewSpot.setArea(kShuttleWindowLeft, kShuttleWindowTop,
+ kShuttleWindowLeft + kShuttleWindowWidth, kShuttleWindowTop + kShuttleWindowHeight);
+ _shuttleViewSpot.setHotspotFlags(kNeighborhoodSpotFlag | kClickSpotFlag);
+ _vm->getAllHotspots().push_back(&_shuttleViewSpot);
+ _shuttleTransportSpot.setArea(kShuttleTransportBounds);
+ _shuttleTransportSpot.setHotspotFlags(kNeighborhoodSpotFlag | kClickSpotFlag);
+ _vm->getAllHotspots().push_back(&_shuttleTransportSpot);
+
+ _privateFlags.setFlag(kMarsPrivateInSpaceChaseFlag, true);
+
+ startMarsTimer(kSpaceChaseTimeLimit, kOneTickPerSecond, kMarsSpaceChaseFinished);
+}
+
+void Mars::setSoundFXLevel(const uint16 level) {
+ Neighborhood::setSoundFXLevel(level);
+
+ if (_canyonChaseMovie.isMovieValid())
+ _canyonChaseMovie.setVolume(level);
+
+ if (_explosions.isMovieValid())
+ _explosions.setVolume(level);
+}
+
+void Mars::startMarsTimer(TimeValue time, TimeScale scale, MarsTimerCode code) {
+ _utilityFuse.primeFuse(time, scale);
+ _marsEvent.mars = this;
+ _marsEvent.event = code;
+ _utilityFuse.setFunctor(new Common::Functor0Mem<void, MarsTimerEvent>(&_marsEvent, &MarsTimerEvent::fire));
+ _utilityFuse.lightFuse();
+}
+
+void Mars::marsTimerExpired(MarsTimerEvent &event) {
+ Common::Rect r;
+ uint16 x, y;
+
+ switch (event.event) {
+ case kMarsLaunchTubeReached:
+ _lowerLeftShuttleMovie.setTime(kShuttleLowerLeftTubeTime);
+ _lowerLeftShuttleMovie.redrawMovieWorld();
+ startMarsTimer(kCanyonChaseFinishedTime, kMovieTicksPerSecond, kMarsCanyonChaseFinished);
+ break;
+ case kMarsCanyonChaseFinished:
+ GameState.setScoringEnteredLaunchTube();
+
+ while (_canyonChaseMovie.isRunning()) {
+ _vm->checkCallBacks();
+ _vm->refreshDisplay();
+ _vm->_system->delayMillis(10);
+ }
+
+ _canyonChaseMovie.stop();
+ _canyonChaseMovie.stopDisplaying();
+ _canyonChaseMovie.releaseMovie();
+
+ _vm->_gfx->enableErase();
+
+ loadLoopSound1("Sounds/Mars/Space Ambient.22K.8.AIFF");
+
+ playSpotSoundSync(kShuttleConfiguringIn, kShuttleConfiguringOut);
+ playSpotSoundSync(kShuttleGeneratingIn, kShuttleGeneratingOut);
+ playSpotSoundSync(kShuttleBreakawayIn, kShuttleBreakawayOut);
+ playSpotSoundSync(kMarsAtmosphericBreakawayIn, kMarsAtmosphericBreakawayOut);
+
+ initOneMovie(&_planetMovie, "Images/Mars/Planet.movie", kShuttlePlanetOrder, kPlanetStartLeft, kPlanetStartTop, true);
+ _planetMovie.setFlags(kLoopTimeBase);
+
+ initOneMovie(&_junk, "Images/Mars/Junk.movie", kShuttleJunkOrder, kShuttleJunkLeft, kShuttleJunkTop, false);
+
+ initOneMovie(&_explosions, "Images/Mars/Explosions.movie", kShuttleWeaponFrontOrder, 0, 0, false);
+ _explosionCallBack.initCallBack(&_explosions, kCallBackAtExtremes);
+
+ _energyBeam.initShuttleWeapon();
+ _gravitonCannon.initShuttleWeapon();
+
+ _centerShuttleMovie.setTime(kShuttleCenterWeaponsTime);
+ _centerShuttleMovie.redrawMovieWorld();
+
+ _upperLeftShuttleMovie.show();
+ _upperLeftShuttleMovie.setTime(kShuttleUpperLeftDampingTime);
+ _upperLeftShuttleMovie.redrawMovieWorld();
+
+ _robotShip.initRobotShip();
+
+ _planetMovie.start();
+ _planetMover.startMoving(&_planetMovie);
+
+ playSpotSoundSync(kShuttleDamperDescIn, kShuttleDamperDescOut);
+ _upperLeftShuttleMovie.setTime(kShuttleUpperLeftGravitonTime);
+ _upperLeftShuttleMovie.redrawMovieWorld();
+
+ playSpotSoundSync(kShuttleGravitonDescIn, kShuttleGravitonDescOut);
+ _upperLeftShuttleMovie.setTime(kShuttleUpperLeftTractorTime);
+ _upperLeftShuttleMovie.redrawMovieWorld();
+
+ playSpotSoundSync(kShuttleTractorDescIn, kShuttleTractorDescOut);
+ _upperLeftShuttleMovie.setTime(kShuttleUpperLeftDimTime);
+ _upperLeftShuttleMovie.redrawMovieWorld();
+
+ _centerShuttleMovie.setTime(kShuttleCenterTargetSightedTime);
+ _centerShuttleMovie.redrawMovieWorld();
+ playSpotSoundSync(kShuttleTargetSightedIn, kShuttleTargetSightedOut);
+
+ _lowerRightShuttleMovie.setTime(kShuttleLowerRightTrackingTime);
+ _lowerRightShuttleMovie.redrawMovieWorld();
+ _rightShuttleMovie.show();
+ playMovieSegment(&_rightShuttleMovie, kShuttleRightIntroStart, kShuttleRightIntroStop);
+
+ _rightDamageShuttleMovie.show();
+ playMovieSegment(&_rightDamageShuttleMovie);
+
+ // Take it down a tick initially. This sets the time to the time of the last tick,
+ // so that subsequence drops will drop it down a tick.
+ _rightDamageShuttleMovie.setTime(_rightDamageShuttleMovie.getTime() - 40);
+ _rightDamageShuttleMovie.redrawMovieWorld();
+
+ _lowerLeftShuttleMovie.setTime(kShuttleLowerLeftAutopilotTime);
+ _lowerLeftShuttleMovie.redrawMovieWorld();
+ playSpotSoundSync(kShuttleAutopilotEngagedIn, kShuttleAutopilotEngagedOut);
+
+ _robotShip.startMoving();
+
+ _shuttleHUD.initShuttleHUD();
+
+ _tractorBeam.startDisplaying();
+
+ _energyChoiceSpot.setArea(kShuttleEnergyBeamBounds);
+ _energyChoiceSpot.setHotspotFlags(kNeighborhoodSpotFlag | kClickSpotFlag);
+ _vm->getAllHotspots().push_back(&_energyChoiceSpot);
+ _gravitonChoiceSpot.setArea(kShuttleGravitonBounds);
+ _gravitonChoiceSpot.setHotspotFlags(kNeighborhoodSpotFlag | kClickSpotFlag);
+ _vm->getAllHotspots().push_back(&_gravitonChoiceSpot);
+ _tractorChoiceSpot.setArea(kShuttleTractorBounds);
+ _tractorChoiceSpot.setHotspotFlags(kNeighborhoodSpotFlag | kClickSpotFlag);
+ _vm->getAllHotspots().push_back(&_tractorChoiceSpot);
+ _shuttleViewSpot.setArea(kShuttleWindowLeft, kShuttleWindowTop,
+ kShuttleWindowLeft + kShuttleWindowWidth, kShuttleWindowTop + kShuttleWindowHeight);
+ _shuttleViewSpot.setHotspotFlags(kNeighborhoodSpotFlag | kClickSpotFlag);
+ _vm->getAllHotspots().push_back(&_shuttleViewSpot);
+ _shuttleTransportSpot.setArea(kShuttleTransportBounds);
+ _shuttleTransportSpot.setHotspotFlags(kNeighborhoodSpotFlag | kClickSpotFlag);
+ _vm->getAllHotspots().push_back(&_shuttleTransportSpot);
+
+ _privateFlags.setFlag(kMarsPrivateInSpaceChaseFlag, true);
+
+ playSpotSoundSync(kMarsCockpitChatterIn, kMarsCockpitChatterOut);
+
+ GameState.setMarsFinishedCanyonChase(true);
+
+ startMarsTimer(kSpaceChaseTimeLimit, kOneTickPerSecond, kMarsSpaceChaseFinished);
+
+ _vm->_cursor->hideUntilMoved();
+ break;
+ case kMarsSpaceChaseFinished:
+ // Player failed to stop the robot in time...
+ _interruptionFilter = kFilterNoInput;
+
+ _rightShuttleMovie.setTime(kShuttleRightTargetLockTime);
+ _rightShuttleMovie.redrawMovieWorld();
+
+ _upperRightShuttleMovie.show();
+ _upperRightShuttleMovie.setTime(kShuttleUpperRightLockedTime);
+ _upperRightShuttleMovie.redrawMovieWorld();
+
+ _rightShuttleMovie.setTime(kShuttleRightGravitonTime);
+ _rightShuttleMovie.redrawMovieWorld();
+ _upperRightShuttleMovie.setTime(kShuttleUpperRightArmedTime);
+ _upperRightShuttleMovie.redrawMovieWorld();
+
+ _vm->delayShell(3, 1);
+
+ x = _vm->getRandomNumber(19);
+ y = _vm->getRandomNumber(19);
+
+ r = Common::Rect(kShuttleWindowMidH - x, kShuttleWindowMidV - y,
+ kShuttleWindowMidH - x + 20, kShuttleWindowMidV - y + 20);
+ showBigExplosion(r, kShuttleAlienShipOrder);
+
+ while (_explosions.isRunning()) {
+ _vm->checkCallBacks();
+ _vm->refreshDisplay();
+ g_system->delayMillis(10);
+ }
+
+ throwAwayMarsShuttle();
+ reinstateMonocleInterface();
+ recallToTSAFailure();
+ break;
+ default:
+ break;
+ }
+
+ _interruptionFilter = kFilterAllInput;
+}
+
+void Mars::throwAwayMarsShuttle() {
+ _shuttleInterface1.deallocateSurface();
+ _shuttleInterface1.stopDisplaying();
+ _shuttleInterface2.deallocateSurface();
+ _shuttleInterface2.stopDisplaying();
+ _shuttleInterface3.deallocateSurface();
+ _shuttleInterface3.stopDisplaying();
+ _shuttleInterface4.deallocateSurface();
+ _shuttleInterface4.stopDisplaying();
+
+ _spotSounds.disposeSound();
+
+ _canyonChaseMovie.releaseMovie();
+ _canyonChaseMovie.stopDisplaying();
+ _leftShuttleMovie.releaseMovie();
+ _leftShuttleMovie.stopDisplaying();
+ _rightShuttleMovie.releaseMovie();
+ _rightShuttleMovie.stopDisplaying();
+ _lowerLeftShuttleMovie.releaseMovie();
+ _lowerLeftShuttleMovie.stopDisplaying();
+ _lowerRightShuttleMovie.releaseMovie();
+ _lowerRightShuttleMovie.stopDisplaying();
+ _centerShuttleMovie.releaseMovie();
+ _centerShuttleMovie.stopDisplaying();
+ _upperLeftShuttleMovie.releaseMovie();
+ _upperLeftShuttleMovie.stopDisplaying();
+ _upperRightShuttleMovie.releaseMovie();
+ _upperRightShuttleMovie.stopDisplaying();
+ _leftDamageShuttleMovie.releaseMovie();
+ _leftDamageShuttleMovie.stopDisplaying();
+ _rightDamageShuttleMovie.releaseMovie();
+ _rightDamageShuttleMovie.stopDisplaying();
+
+ _shuttleEnergyMeter.disposeShuttleEnergyMeter();
+ _robotShip.cleanUpRobotShip();
+ _shuttleHUD.cleanUpShuttleHUD();
+ _tractorBeam.stopDisplaying();
+ _junk.releaseMovie();
+ _junk.stopDisplaying();
+ _energyBeam.cleanUpShuttleWeapon();
+ _gravitonCannon.cleanUpShuttleWeapon();
+ _vm->getAllHotspots().remove(&_energyChoiceSpot);
+ _vm->getAllHotspots().remove(&_gravitonChoiceSpot);
+ _vm->getAllHotspots().remove(&_tractorChoiceSpot);
+ _vm->getAllHotspots().remove(&_shuttleViewSpot);
+ _vm->getAllHotspots().remove(&_shuttleTransportSpot);
+ _explosions.releaseMovie();
+ _explosions.stopDisplaying();
+
+ loadLoopSound1("");
+}
+
+void Mars::transportToRobotShip() {
+ throwAwayMarsShuttle();
+
+ Video::VideoDecoder *video = new Video::QuickTimeDecoder();
+ if (!video->loadFile("Images/Mars/M98EAE.movie"))
+ error("Could not load shuttle->interface transition video");
+
+ video->start();
+
+ while (!_vm->shouldQuit() && !video->endOfVideo()) {
+ if (video->needsUpdate()) {
+ const Graphics::Surface *frame = video->decodeNextFrame();
+
+ if (frame)
+ _vm->drawScaledFrame(frame, 0, 0);
+ }
+
+ Common::Event event;
+ while (g_system->getEventManager()->pollEvent(event))
+ ;
+
+ g_system->delayMillis(10);
+ }
+
+ delete video;
+
+ if (_vm->shouldQuit())
+ return;
+
+ reinstateMonocleInterface();
+
+ g_energyMonitor->stopEnergyDraining();
+ g_energyMonitor->restoreLastEnergyValue();
+ _vm->resetEnergyDeathReason();
+ g_energyMonitor->startEnergyDraining();
+
+ arriveAt(kMarsRobotShuttle, kEast);
+
+ _navMovie.stop();
+ _navMovie.setTime(_navMovie.getStart());
+ _navMovie.start();
+}
+
+const int kRobotTooStrong = 1;
+const int kTractorTooWeak = 2;
+const int kCapturedRobotShip = 3;
+
+void Mars::spaceChaseClick(const Input &input, const HotSpotID id) {
+ Common::Point pt;
+
+ switch (id) {
+ case kShuttleEnergySpotID:
+ _upperLeftShuttleMovie.setTime(kShuttleUpperLeftDampingTime);
+ _upperLeftShuttleMovie.redrawMovieWorld();
+ _leftShuttleMovie.setTime(kShuttleLeftDampingTime);
+ _leftShuttleMovie.redrawMovieWorld();
+ _shuttleHUD.hide();
+ _weaponSelection = kEnergyBeam;
+ playSpotSoundSync(kShuttleDampingBeamIn, kShuttleDampingBeamOut);
+ break;
+ case kShuttleGravitonSpotID:
+ _upperLeftShuttleMovie.setTime(kShuttleUpperLeftGravitonTime);
+ _upperLeftShuttleMovie.redrawMovieWorld();
+ _leftShuttleMovie.setTime(kShuttleLeftGravitonTime);
+ _leftShuttleMovie.redrawMovieWorld();
+ _shuttleHUD.hide();
+ _weaponSelection = kGravitonCannon;
+ playSpotSoundSync(kShuttleGravitonIn, kShuttleGravitonOut);
+ break;
+ case kShuttleTractorSpotID:
+ _upperLeftShuttleMovie.setTime(kShuttleUpperLeftTractorTime);
+ _upperLeftShuttleMovie.redrawMovieWorld();
+ _leftShuttleMovie.setTime(kShuttleLeftTractorTime);
+ _leftShuttleMovie.redrawMovieWorld();
+ _shuttleHUD.show();
+ _weaponSelection = kTractorBeam;
+ playSpotSoundSync(kShuttleTractorBeamIn, kShuttleTractorBeamOut);
+ break;
+ case kShuttleViewSpotID:
+ switch (_weaponSelection) {
+ case kEnergyBeam:
+ if (_shuttleEnergyMeter.getEnergyValue() < kMinDampingEnergy) {
+ playSpotSoundSync(kShuttleEnergyTooLowIn, kShuttleEnergyTooLowOut);
+ } else {
+ if (_energyBeam.canFireWeapon()) {
+ _shuttleEnergyMeter.dropEnergyValue(kMinDampingEnergy);
+ input.getInputLocation(pt);
+ _energyBeam.fireWeapon(pt.x, pt.y);
+ playSpotSoundSync(kMarsEDBBlastIn, kMarsEDBBlastOut);
+ }
+ }
+ break;
+ case kGravitonCannon:
+ if (_shuttleEnergyMeter.getEnergyValue() < kMinGravitonEnergy) {
+ playSpotSoundSync(kShuttleEnergyTooLowIn, kShuttleEnergyTooLowOut);
+ } else {
+ if (_gravitonCannon.canFireWeapon()) {
+ _shuttleEnergyMeter.dropEnergyValue(kMinGravitonEnergy);
+ input.getInputLocation(pt);
+ _gravitonCannon.fireWeapon(pt.x, pt.y);
+ playSpotSoundSync(kMarsGravitonBlastIn, kMarsGravitonBlastOut);
+ }
+ }
+ break;
+ case kTractorBeam:
+ if (_shuttleHUD.isTargetLocked()) {
+ // play tractor beam sound?
+ _utilityFuse.stopFuse();
+
+ _tractorBeam.show();
+
+ int capture;
+ if (_rightDamageShuttleMovie.getTime() > 40) {
+ capture = kRobotTooStrong;
+ } else if (!_shuttleEnergyMeter.enoughEnergyForTractorBeam()) {
+ capture = kTractorTooWeak;
+ } else {
+ _robotShip.snareByTractorBeam();
+ capture = kCapturedRobotShip;
+ _planetMover.dropPlanetOutOfSight();
+ }
+
+ _shuttleEnergyMeter.drainForTractorBeam();
+
+ while (_shuttleEnergyMeter.isFading()) {
+ _vm->checkCallBacks();
+ _vm->refreshDisplay();
+ _vm->_system->delayMillis(10);
+ }
+
+ _shuttleEnergyMeter.setEnergyValue(_shuttleEnergyMeter.getEnergyValue());
+
+ switch (capture) {
+ case kRobotTooStrong:
+ _tractorBeam.hide();
+ playSpotSoundSync(kShuttleBrokeFreeIn, kShuttleBrokeFreeOut);
+ _utilityFuse.lightFuse();
+ break;
+ case kTractorTooWeak:
+ playSpotSoundSync(kShuttleCantHoldIn, kShuttleCantHoldOut);
+ _tractorBeam.hide();
+ _utilityFuse.lightFuse();
+ break;
+ case kCapturedRobotShip:
+ _tractorBeam.hide();
+ _shuttleHUD.hide();
+ _robotShip.cleanUpRobotShip();
+ _planetMovie.stop();
+ _planetMovie.stopDisplaying();
+ _planetMovie.releaseMovie();
+
+ // Shameless reuse of a variable :P
+ initOneMovie(&_canyonChaseMovie, "Images/Mars/M98EAS.movie", kShuttleTractorBeamMovieOrder,
+ kShuttleWindowLeft, kShuttleWindowTop, true);
+ _canyonChaseMovie.redrawMovieWorld();
+ playMovieSegment(&_canyonChaseMovie, 0, _canyonChaseMovie.getDuration());
+
+ // wait here until any junk clears...
+ while (_junk.junkFlying()) {
+ _vm->checkCallBacks();
+ _vm->refreshDisplay();
+ _vm->_system->delayMillis(10);
+ }
+
+ _upperRightShuttleMovie.show();
+ _upperRightShuttleMovie.setTime(kShuttleUpperRightOverloadTime);
+ _upperRightShuttleMovie.redrawMovieWorld();
+
+ playSpotSoundSync(kShuttleOverloadedIn, kShuttleOverloadedOut);
+ _centerShuttleMovie.setTime(kShuttleCenterVerifyingTime);
+ _centerShuttleMovie.redrawMovieWorld();
+
+ playSpotSoundSync(kShuttleCoordinatesIn, kShuttleCoordinatesOut);
+ _centerShuttleMovie.setTime(kShuttleCenterScanningTime);
+ _centerShuttleMovie.redrawMovieWorld();
+
+ playSpotSoundSync(kShuttleScanningIn, kShuttleScanningOut);
+ _centerShuttleMovie.setTime(kShuttleCenterSafeTime);
+ _centerShuttleMovie.redrawMovieWorld();
+
+ playSpotSoundSync(kShuttleSafeIn, kShuttleSafeOut);
+ _lowerRightShuttleMovie.setTime(kShuttleLowerRightTransportTime);
+ _lowerRightShuttleMovie.redrawMovieWorld();
+ GameState.setMarsReadyForShuttleTransport(true);
+ break;
+ }
+ } else {
+ playSpotSoundSync(kShuttleTractorLimitedIn, kShuttleTractorLimitedOut);
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case kShuttleTransportSpotID:
+ _lowerRightShuttleMovie.setTime(kShuttleLowerRightTransportHiliteTime);
+ _lowerRightShuttleMovie.redrawMovieWorld();
+ _neighborhoodNotification.setNotificationFlags(kTimeToTransportFlag, kTimeToTransportFlag);
+ break;
+ }
+}
+
+void Mars::showBigExplosion(const Common::Rect &r, const DisplayOrder order) {
+ if (_explosions.isMovieValid()) {
+ _explosions.setDisplayOrder(order);
+
+ Common::Rect r2 = r;
+ int dx = r.width() / 2;
+ int dy = r.height() / 2;
+ r2.left -= dx;
+ r2.right += dx;
+ r2.top -= dy;
+ r2.bottom += dy;
+
+ _explosions.setBounds(r2);
+ _explosions.show();
+ _explosions.stop();
+ _explosions.setSegment(kBigExplosionStart, kBigExplosionStop);
+ _explosions.setTime(kBigExplosionStart);
+ _explosionCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ _explosions.start();
+ }
+}
+
+void Mars::showLittleExplosion(const Common::Rect &r, const DisplayOrder order) {
+ if (_explosions.isMovieValid()) {
+ _explosions.setDisplayOrder(order);
+
+ Common::Rect r2 = r;
+ int dx = r.width() / 2;
+ int dy = r.height() / 2;
+ r2.left -= dx;
+ r2.right += dx;
+ r2.top -= dy;
+ r2.bottom += dy;
+ _explosions.setBounds(r2);
+
+ _explosions.show();
+ _explosions.stop();
+ _explosions.setSegment(kLittleExplosionStart, kLittleExplosionStop);
+ _explosions.setTime(kLittleExplosionStart);
+ _explosionCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ _explosions.start();
+ }
+}
+
+void Mars::hitByJunk() {
+ _leftDamageShuttleMovie.setTime(_leftDamageShuttleMovie.getTime() - 40);
+ _leftDamageShuttleMovie.redrawMovieWorld();
+
+ playSpotSoundSync(kMarsJunkCollisionIn, kMarsJunkCollisionOut);
+
+ if (_leftDamageShuttleMovie.getTime() == 0) {
+ die(kDeathRanIntoSpaceJunk);
+ } else {
+ TimeValue t = _leftDamageShuttleMovie.getTime() / 40;
+
+ if (t == 1)
+ playSpotSoundSync(kShuttleHullBreachIn, kShuttleHullBreachOut);
+
+ t = _leftShuttleMovie.getTime();
+ _leftShuttleMovie.setTime(kShuttleLeftDamagedTime);
+ _leftShuttleMovie.redrawMovieWorld();
+ _vm->delayShell(1, 3);
+ _leftShuttleMovie.setTime(t);
+ _leftShuttleMovie.redrawMovieWorld();
+ }
+}
+
+void Mars::setUpNextDropTime() {
+ _robotShip.setUpNextDropTime();
+}
+
+void Mars::decreaseRobotShuttleEnergy(const int delta, Common::Point impactPoint) {
+ _rightDamageShuttleMovie.setTime(_rightDamageShuttleMovie.getTime() - 40 * delta);
+ _rightDamageShuttleMovie.redrawMovieWorld();
+
+ if (_rightDamageShuttleMovie.getTime() == 0) {
+ Common::Rect r;
+ _robotShip.getShuttleBounds(r);
+ int size = MAX(r.width(), r.height());
+ r = Common::Rect::center(impactPoint.x, impactPoint.y, size, size);
+ _robotShip.killRobotShip();
+ showBigExplosion(r, kShuttleRobotShipOrder);
+ } else if (delta > 1) {
+ Common::Rect r;
+ _robotShip.getShuttleBounds(r);
+ int size = MIN(r.width(), r.height());
+ r = Common::Rect::center(impactPoint.x, impactPoint.y, size, size);
+ showLittleExplosion(r, kShuttleWeaponBackOrder);
+ TimeValue t = _rightShuttleMovie.getTime();
+ _rightShuttleMovie.setTime(kShuttleRightDamagedTime);
+ _rightShuttleMovie.redrawMovieWorld();
+ _vm->delayShell(1, 3);
+ _rightShuttleMovie.setTime(t);
+ _rightShuttleMovie.redrawMovieWorld();
+ }
+
+ if (_rightDamageShuttleMovie.getTime() <= 40) {
+ GameState.setScoringStoppedRobotsShuttle();
+ if (!GameState.getMarsHitRobotWithCannon())
+ GameState.setScoringMarsGandhi();
+ }
+}
+
+void Mars::updateCursor(const Common::Point cursorLocation, const Hotspot *cursorSpot) {
+ if (cursorSpot && cursorSpot->getObjectID() == kShuttleViewSpotID) {
+ if (_weaponSelection != kNoWeapon)
+ _vm->_cursor->setCurrentFrameIndex(6);
+ else
+ _vm->_cursor->setCurrentFrameIndex(0);
+ } else {
+ Neighborhood::updateCursor(cursorLocation, cursorSpot);
+ }
+}
+
+AirQuality Mars::getAirQuality(const RoomID room) {
+ if ((room >= kMars36 && room <= kMars39) || (room >= kMarsMaze004 && room <= kMarsMaze200))
+ return kAirQualityVacuum;
+ if (room == kMars35 && !GameState.getMarsAirlockOpen())
+ return kAirQualityVacuum;
+ if (room == kMars60 && !GameState.getMarsAirlockOpen())
+ return kAirQualityVacuum;
+
+ return Neighborhood::getAirQuality(room);
+}
+
+// Start up panting sound if necessary.
+
+void Mars::checkAirMask() {
+ Neighborhood::checkAirMask();
+
+ if (getAirQuality(GameState.getCurrentRoom()) == kAirQualityVacuum) {
+ if (g_airMask->isAirMaskOn()) {
+ if (_noAirFuse.isFuseLit()) {
+ _noAirFuse.stopFuse();
+ loadLoopSound2("");
+ loadAmbientLoops();
+ playSpotSoundSync(kMarsOxyMaskOnIn, kMarsOxyMaskOnOut);
+ }
+ } else {
+ if (!_noAirFuse.isFuseLit()) {
+ loadLoopSound2("Sounds/Mars/SukWind1.22K.AIFF");
+ _noAirFuse.primeFuse(kVacuumSurvivalTimeLimit);
+ _noAirFuse.lightFuse();
+ }
+ }
+ } else {
+ if (_noAirFuse.isFuseLit()) {
+ _noAirFuse.stopFuse();
+ loadLoopSound2("");
+ loadAmbientLoops();
+ }
+ }
+}
+
+void Mars::airStageExpired() {
+ if (((PegasusEngine *)g_engine)->playerHasItemID(kAirMask))
+ die(kDeathNoAirInMaze);
+ else
+ die(kDeathNoMaskInMaze);
+}
+
+void Mars::lockThawed() {
+ startExtraSequence(kMars57ThawLock, kExtraCompletedFlag, kFilterNoInput);
+}
+
+void Mars::setUpReactorLevel1() {
+ _reactorStage = 1;
+ makeColorSequence();
+ _guessObject.initReactorGuess();
+ _undoPict.initFromPICTResource(_vm->_resFork, kReactorUndoHilitePICTID);
+ _undoPict.setDisplayOrder(kMonitorLayer);
+ _undoPict.moveElementTo(kUndoHiliteLeft, kUndoHiliteTop);
+ _undoPict.startDisplaying();
+ _guessHistory.initReactorHistory();
+ _choiceHighlight.initReactorChoiceHighlight();
+ setCurrentActivation(kActivateReactorInGame);
+ _bombFuse.primeFuse(kColorMatchingTimeLimit);
+ _bombFuse.setFunctor(new Common::Functor0Mem<void, Mars>(this, &Mars::bombExplodesInGame));
+ _bombFuse.lightFuse();
+}
+
+void Mars::setUpNextReactorLevel() {
+ _guessObject.show();
+ _guessHistory.show();
+ _guessHistory.clearHistory();
+ _choiceHighlight.show();
+ _reactorStage++;
+ makeColorSequence();
+}
+
+void Mars::makeColorSequence() {
+ int32 code[5];
+ int32 highest = _reactorStage + 2;
+
+ for (int32 i = 0; i < highest; i++)
+ code[i] = i;
+
+ _vm->shuffleArray(code, highest);
+ _currentGuess[0] = -1;
+ _currentGuess[1] = -1;
+ _currentGuess[2] = -1;
+ _nextGuess = 0;
+ _guessObject.setGuess(-1, -1, -1);
+ _guessHistory.setAnswer(code[0], code[1], code[2]);
+}
+
+void Mars::doUndoOneGuess() {
+ if (_nextGuess > 0) {
+ _undoPict.show();
+ _vm->delayShell(1, 2);
+ _undoPict.hide();
+ _nextGuess--;
+ _currentGuess[_nextGuess] = -1;
+ _guessObject.setGuess(_currentGuess[0], _currentGuess[1], _currentGuess[2]);
+ _choiceHighlight.resetHighlight();
+
+ if (_currentGuess[0] != -1) {
+ _choiceHighlight.highlightChoice(_currentGuess[0]);
+
+ if (_currentGuess[1] != -1) {
+ _choiceHighlight.highlightChoice(_currentGuess[1]);
+
+ if (_currentGuess[2] != -1)
+ _choiceHighlight.highlightChoice(_currentGuess[2]);
+ }
+ }
+ }
+}
+
+void Mars::doReactorGuess(int32 guess) {
+ _choiceHighlight.highlightChoice(guess);
+ _currentGuess[_nextGuess] = guess;
+ _guessObject.setGuess(_currentGuess[0], _currentGuess[1], _currentGuess[2]);
+
+ switch (guess) {
+ case 0:
+ playSpotSoundSync(kColorMatchRedIn, kColorMatchRedOut);
+ break;
+ case 1:
+ playSpotSoundSync(kColorMatchYellowIn, kColorMatchYellowOut);
+ break;
+ case 2:
+ playSpotSoundSync(kColorMatchGreenIn, kColorMatchGreenOut);
+ break;
+ case 3:
+ playSpotSoundSync(kColorMatchBlueIn, kColorMatchBlueOut);
+ break;
+ case 4:
+ playSpotSoundSync(kColorMatchPurpleIn, kColorMatchPurpleOut);
+ break;
+ }
+
+ _nextGuess++;
+
+ if (_nextGuess == 3) {
+ _vm->delayShell(1, 2);
+ _nextGuess = 0;
+ _guessHistory.addGuess(_currentGuess[0], _currentGuess[1], _currentGuess[2]);
+
+ switch (_guessHistory.getCurrentNumCorrect()) {
+ case 0:
+ playSpotSoundSync(kColorMatchZeroNodesIn, kColorMatchZeroNodesOut);
+ break;
+ case 1:
+ playSpotSoundSync(kColorMatchOneNodeIn, kColorMatchOneNodeOut);
+ break;
+ case 2:
+ playSpotSoundSync(kColorMatchTwoNodesIn, kColorMatchTwoNodesOut);
+ break;
+ case 3:
+ playSpotSoundSync(kColorMatchThreeNodesIn, kColorMatchThreeNodesOut);
+ break;
+ }
+
+ _currentGuess[0] = -1;
+ _currentGuess[1] = -1;
+ _currentGuess[2] = -1;
+ _guessObject.setGuess(-1, -1, -1);
+ _choiceHighlight.resetHighlight();
+
+ if (_guessHistory.isSolved()) {
+ _guessHistory.showAnswer();
+ _vm->delayShell(1, 2);
+ _guessObject.hide();
+ _guessHistory.hide();
+ _choiceHighlight.hide();
+
+ switch (_reactorStage) {
+ case 1:
+ startExtraSequence(kMars57GameLevel2, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case 2:
+ startExtraSequence(kMars57GameLevel3, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case 3:
+ _bombFuse.stopFuse();
+ _guessObject.disposeReactorGuess();
+ _undoPict.deallocateSurface();
+ _guessHistory.disposeReactorHistory();
+ _choiceHighlight.disposeReactorChoiceHighlight();
+ GameState.setScoringDisarmedCardBomb();
+ startExtraSequence(kMars57GameSolved, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ }
+ } else if (_guessHistory.getNumGuesses() >= 5) {
+ _vm->delayShell(2, 1);
+ bombExplodesInGame();
+ }
+ }
+}
+
+void Mars::bombExplodesInGame() {
+ _guessObject.disposeReactorGuess();
+ _undoPict.deallocateSurface();
+ _guessHistory.disposeReactorHistory();
+ _choiceHighlight.disposeReactorChoiceHighlight();
+ startExtraSequence(kMars57BombExplodesInGame, kExtraCompletedFlag, kFilterNoInput);
+}
+
+void Mars::didntFindBomb() {
+ die(kDeathDidntFindMarsBomb);
+}
+
+Common::String Mars::getBriefingMovie() {
+ Common::String movieName = Neighborhood::getBriefingMovie();
+
+ if (!movieName.empty())
+ return movieName;
+
+ return "Images/AI/Mars/XM01";
+}
+
+Common::String Mars::getEnvScanMovie() {
+ Common::String movieName = Neighborhood::getEnvScanMovie();
+
+ if (movieName.empty()) {
+ RoomID room = GameState.getCurrentRoom();
+
+ if (room >= kMars0A && room <= kMars21)
+ return "Images/AI/Mars/XME1";
+ else if (room >= kMars22 && room <= kMars31South)
+ return "Images/AI/Mars/XME2";
+ else if (room >= kMars52 && room <= kMars58)
+ return "Images/AI/Mars/XMREACE";
+
+ return "Images/AI/Mars/XME3";
+ }
+
+ return movieName;
+}
+
+uint Mars::getNumHints() {
+ uint numHints = Neighborhood::getNumHints();
+
+ if (numHints == 0) {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kMars27, kNorth):
+ case MakeRoomView(kMars28, kNorth):
+ case MakeRoomView(kMars49, kSouth):
+ numHints = 1;
+ break;
+ case MakeRoomView(kMars31, kSouth):
+ case MakeRoomView(kMars31South, kSouth):
+ if (!GameState.isTakenItemID(kMarsCard))
+ numHints = 1;
+ break;
+ case MakeRoomView(kMars34, kNorth):
+ if (!GameState.isTakenItemID(kMarsCard))
+ numHints = 2;
+ break;
+ case MakeRoomView(kMars34, kSouth):
+ case MakeRoomView(kMars45, kNorth):
+ if (!GameState.isTakenItemID(kCrowbar))
+ numHints = 1;
+ break;
+ case MakeRoomView(kMars51, kEast):
+ if (GameState.isCurrentDoorOpen() && !GameState.getShieldOn()) {
+ if (GameState.isTakenItemID(kShieldBiochip))
+ numHints = 1;
+ else
+ numHints = 2;
+ }
+ break;
+ case MakeRoomView(kMars52, kNorth):
+ case MakeRoomView(kMars52, kSouth):
+ case MakeRoomView(kMars52, kEast):
+ case MakeRoomView(kMars52, kWest):
+ case MakeRoomView(kMars54, kNorth):
+ case MakeRoomView(kMars54, kSouth):
+ case MakeRoomView(kMars54, kEast):
+ case MakeRoomView(kMars54, kWest):
+ case MakeRoomView(kMars56, kNorth):
+ case MakeRoomView(kMars56, kSouth):
+ case MakeRoomView(kMars56, kWest):
+ case MakeRoomView(kMars58, kNorth):
+ case MakeRoomView(kMars58, kSouth):
+ case MakeRoomView(kMars58, kEast):
+ case MakeRoomView(kMars58, kWest):
+ if (!GameState.getShieldOn()) {
+ if (GameState.isTakenItemID(kShieldBiochip))
+ numHints = 1;
+ else
+ numHints = 2;
+ }
+ break;
+ case MakeRoomView(kMars56, kEast):
+ if (getCurrentActivation() == kActivateReactorReadyForNitrogen) {
+ if ((ExtraID)_lastExtra == kMars57LowerScreenClosed)
+ numHints = 3;
+ } else if (getCurrentActivation() == kActivateReactorPlatformOut) {
+ if (!GameState.getShieldOn()) {
+ if (GameState.isTakenItemID(kShieldBiochip))
+ numHints = 1;
+ else
+ numHints = 2;
+ }
+ }
+ break;
+ }
+ }
+
+ return numHints;
+}
+
+Common::String Mars::getHintMovie(uint hintNum) {
+ Common::String movieName = Neighborhood::getHintMovie(hintNum);
+
+ if (movieName.empty()) {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kMars27, kNorth):
+ case MakeRoomView(kMars28, kNorth):
+ return "Images/AI/Globals/XGLOB5C";
+ case MakeRoomView(kMars31, kSouth):
+ case MakeRoomView(kMars31South, kSouth):
+ case MakeRoomView(kMars34, kSouth):
+ case MakeRoomView(kMars45, kNorth):
+ return "Images/AI/Globals/XGLOB1C";
+ case MakeRoomView(kMars34, kNorth):
+ if (hintNum == 1)
+ return "Images/AI/Globals/XGLOB2C";
+
+ return "Images/AI/Globals/XGLOB3G";
+ case MakeRoomView(kMars49, kSouth):
+ if (GameState.isTakenItemID(kAirMask))
+ return "Images/AI/Globals/XGLOB3E";
+
+ return "Images/AI/Globals/XGLOB1C";
+ case MakeRoomView(kMars51, kEast):
+ if (GameState.isTakenItemID(kShieldBiochip))
+ return "Images/AI/Mars/XM52NW";
+
+ if (hintNum == 1)
+ return "Images/AI/Globals/XGLOB2D";
+
+ return "Images/AI/Globals/XGLOB3F";
+ case MakeRoomView(kMars52, kNorth):
+ case MakeRoomView(kMars52, kSouth):
+ case MakeRoomView(kMars52, kEast):
+ case MakeRoomView(kMars52, kWest):
+ case MakeRoomView(kMars54, kNorth):
+ case MakeRoomView(kMars54, kSouth):
+ case MakeRoomView(kMars54, kEast):
+ case MakeRoomView(kMars54, kWest):
+ case MakeRoomView(kMars56, kNorth):
+ case MakeRoomView(kMars56, kSouth):
+ case MakeRoomView(kMars56, kWest):
+ case MakeRoomView(kMars58, kNorth):
+ case MakeRoomView(kMars58, kSouth):
+ case MakeRoomView(kMars58, kEast):
+ case MakeRoomView(kMars58, kWest):
+ if (hintNum == 1) {
+ if (GameState.isTakenItemID(kShieldBiochip))
+ return "Images/AI/Mars/XM52NW";
+
+ return "Images/AI/Globals/XGLOB2D";
+ }
+
+ return "Images/AI/Globals/XGLOB3F";
+ case MakeRoomView(kMars56, kEast):
+ if (getCurrentActivation() == kActivateReactorReadyForNitrogen)
+ return Common::String::format("Images/AI/Mars/XM57SD%d", hintNum);
+
+ if (hintNum == 1) {
+ if (GameState.isTakenItemID(kShieldBiochip))
+ return "Images/AI/Mars/XM52NW";
+
+ return "Images/AI/Globals/XGLOB2D";
+ }
+
+ return "Images/AI/Globals/XGLOB3F";
+ }
+ }
+
+ return movieName;
+}
+
+bool Mars::inColorMatchingGame() {
+ return _guessObject.isDisplaying();
+}
+
+bool Mars::canSolve() {
+ return GameState.getCurrentRoomAndView() == MakeRoomView(kMars56, kEast) && (getCurrentActivation() == kActivateReactorReadyForNitrogen ||
+ getCurrentActivation() == kActivateReactorReadyForCrowBar || inColorMatchingGame());
+}
+
+void Mars::doSolve() {
+ if (getCurrentActivation() == kActivateReactorReadyForNitrogen || getCurrentActivation() == kActivateReactorReadyForCrowBar) {
+ _utilityFuse.stopFuse();
+ GameState.setMarsLockBroken(true);
+ GameState.setMarsLockFrozen(false);
+ startExtraLongSequence(kMars57OpenPanel, kMars57OpenPanelChoices, kExtraCompletedFlag, kFilterNoInput);
+ } else if (inColorMatchingGame()) {
+ _bombFuse.stopFuse();
+ _guessObject.disposeReactorGuess();
+ _undoPict.deallocateSurface();
+ _guessHistory.disposeReactorHistory();
+ _choiceHighlight.disposeReactorChoiceHighlight();
+ startExtraSequence(kMars57GameSolved, kExtraCompletedFlag, kFilterNoInput);
+ }
+}
+
+Common::String Mars::getSoundSpotsName() {
+ return "Sounds/Mars/Mars Spots";
+}
+
+Common::String Mars::getNavMovieName() {
+ return "Images/Mars/Mars.movie";
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/mars/mars.h b/engines/pegasus/neighborhood/mars/mars.h
new file mode 100644
index 0000000000..0859522890
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/mars.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_MARS_MARS_H
+#define PEGASUS_NEIGHBORHOOD_MARS_MARS_H
+
+#include "pegasus/neighborhood/neighborhood.h"
+#include "pegasus/neighborhood/mars/constants.h"
+#include "pegasus/neighborhood/mars/energybeam.h"
+#include "pegasus/neighborhood/mars/gravitoncannon.h"
+#include "pegasus/neighborhood/mars/planetmover.h"
+#include "pegasus/neighborhood/mars/reactor.h"
+#include "pegasus/neighborhood/mars/robotship.h"
+#include "pegasus/neighborhood/mars/shuttleenergymeter.h"
+#include "pegasus/neighborhood/mars/shuttlehud.h"
+#include "pegasus/neighborhood/mars/spacejunk.h"
+#include "pegasus/neighborhood/mars/tractorbeam.h"
+
+namespace Pegasus {
+
+class InventoryItem;
+class Mars;
+
+enum MarsTimerCode {
+ kMarsLaunchTubeReached,
+ kMarsCanyonChaseFinished,
+ kMarsSpaceChaseFinished // Player ran out of time...
+};
+
+struct MarsTimerEvent {
+ Mars *mars;
+ MarsTimerCode event;
+
+ void fire();
+};
+
+enum ShuttleWeaponSelection {
+ kNoWeapon,
+ kEnergyBeam,
+ kGravitonCannon,
+ kTractorBeam
+};
+
+class Mars : public Neighborhood {
+friend struct MarsTimerEvent;
+public:
+ Mars(InputHandler *, PegasusEngine *);
+ virtual ~Mars();
+
+ void flushGameState();
+
+ virtual uint16 getDateResID() const;
+
+ virtual AirQuality getAirQuality(const RoomID);
+
+ void checkAirMask();
+
+ void showBigExplosion(const Common::Rect &, const DisplayOrder);
+ void showLittleExplosion(const Common::Rect &, const DisplayOrder);
+ void hitByJunk();
+ void decreaseRobotShuttleEnergy(const int, Common::Point impactPoint);
+ void setUpNextDropTime();
+
+ Common::String getBriefingMovie();
+ Common::String getEnvScanMovie();
+ uint getNumHints();
+ Common::String getHintMovie(uint);
+
+ virtual void shieldOn();
+ virtual void shieldOff();
+
+ void checkContinuePoint(const RoomID, const DirectionConstant);
+
+ void setSoundFXLevel(const uint16);
+
+ bool canSolve();
+ void doSolve();
+
+ bool inColorMatchingGame();
+
+protected:
+ enum {
+ kMarsPrivatePodStorageOpenFlag,
+ kMarsPrivatePodTurnLeftFlag,
+ kMarsPrivatePodTurnRightFlag,
+ kMarsPrivateRobotTiredOfWaitingFlag,
+ kMarsPrivatePlatformZoomedInFlag,
+ kMarsPrivateBombExposedFlag,
+ kMarsPrivateDraggingBombFlag,
+ kMarsPrivateInSpaceChaseFlag,
+ kMarsPrivateGotMapChipFlag,
+ kMarsPrivateGotOpticalChipFlag,
+ kMarsPrivateGotShieldChipFlag,
+ kNumMarsPrivateFlags
+ };
+
+ void init();
+ void start();
+ void setUpAIRules();
+ void arriveAt(const RoomID, const DirectionConstant);
+ void takeItemFromRoom(Item *);
+ void dropItemIntoRoom(Item *, Hotspot *);
+ void activateHotspots();
+ void activateOneHotspot(HotspotInfoTable::Entry &, Hotspot *);
+ void clickInHotspot(const Input &, const Hotspot *);
+ InputBits getInputFilter();
+
+ TimeValue getViewTime(const RoomID, const DirectionConstant);
+ void getZoomEntry(const HotSpotID, ZoomTable::Entry &);
+ void findSpotEntry(const RoomID, const DirectionConstant, SpotFlags, SpotTable::Entry &);
+ CanOpenDoorReason canOpenDoor(DoorTable::Entry &);
+ void openDoor();
+ void closeDoorOffScreen(const RoomID, const DirectionConstant);
+ int16 getStaticCompassAngle(const RoomID, const DirectionConstant);
+ void getExitCompassMove(const ExitTable::Entry &, FaderMoveSpec &);
+ void getExtraCompassMove(const ExtraTable::Entry &, FaderMoveSpec &);
+ void turnTo(const DirectionConstant);
+ void receiveNotification(Notification *, const NotificationFlags);
+ void doorOpened();
+ void setUpReactorEnergyDrain();
+ Hotspot *getItemScreenSpot(Item *, DisplayElement *);
+ void lockThawed();
+ void robotTiredOfWaiting();
+
+ void setUpReactorLevel1();
+ void setUpNextReactorLevel();
+ void makeColorSequence();
+ void doUndoOneGuess();
+ void doReactorGuess(int32 guess);
+ void bombExplodesInGame();
+ void didntFindBomb();
+ CanMoveForwardReason canMoveForward(ExitTable::Entry &);
+ void cantMoveThatWay(CanMoveForwardReason);
+ void moveForward();
+ void bumpIntoWall();
+ void turnLeft();
+ void turnRight();
+ void airStageExpired();
+ void loadAmbientLoops();
+ void checkAirlockDoors();
+ void pickedUpItem(Item *item);
+ void cantOpenDoor(CanOpenDoorReason);
+ void launchMaze007Robot();
+ void launchMaze015Robot();
+ void launchMaze101Robot();
+ void launchMaze104Robot();
+ void launchMaze133Robot();
+ void launchMaze136Robot();
+ void launchMaze184Robot();
+ void timerExpired(const uint32);
+ void spotCompleted();
+
+ void doCanyonChase(void);
+ void startMarsTimer(TimeValue, TimeScale, MarsTimerCode);
+ void marsTimerExpired(MarsTimerEvent &);
+ void throwAwayMarsShuttle();
+ void startUpFromFinishedSpaceChase();
+ void startUpFromSpaceChase();
+ void transportToRobotShip();
+ void spaceChaseClick(const Input &, const HotSpotID);
+ void updateCursor(const Common::Point, const Hotspot *);
+
+ Common::String getSoundSpotsName();
+ Common::String getNavMovieName();
+
+ InventoryItem *_attackingItem;
+ FuseFunction _bombFuse;
+ FuseFunction _noAirFuse;
+ FuseFunction _utilityFuse;
+ FlagsArray<byte, kNumMarsPrivateFlags> _privateFlags;
+ uint _reactorStage, _nextGuess;
+ int32 _currentGuess[3];
+ ReactorGuess _guessObject;
+ Picture _undoPict;
+ ReactorHistory _guessHistory;
+ ReactorChoiceHighlight _choiceHighlight;
+
+ Picture _shuttleInterface1;
+ Picture _shuttleInterface2;
+ Picture _shuttleInterface3;
+ Picture _shuttleInterface4;
+ Movie _canyonChaseMovie;
+
+ MarsTimerEvent _marsEvent;
+
+ Movie _leftShuttleMovie;
+ Movie _rightShuttleMovie;
+ Movie _lowerLeftShuttleMovie;
+ Movie _lowerRightShuttleMovie;
+ Movie _centerShuttleMovie;
+ Movie _upperLeftShuttleMovie;
+ Movie _upperRightShuttleMovie;
+ Movie _leftDamageShuttleMovie;
+ Movie _rightDamageShuttleMovie;
+ ShuttleEnergyMeter _shuttleEnergyMeter;
+ Movie _planetMovie;
+ PlanetMover _planetMover;
+ RobotShip _robotShip;
+ ShuttleHUD _shuttleHUD;
+ TractorBeam _tractorBeam;
+ SpaceJunk _junk;
+ EnergyBeam _energyBeam;
+ GravitonCannon _gravitonCannon;
+ Hotspot _energyChoiceSpot;
+ Hotspot _gravitonChoiceSpot;
+ Hotspot _tractorChoiceSpot;
+ Hotspot _shuttleViewSpot;
+ Hotspot _shuttleTransportSpot;
+ ShuttleWeaponSelection _weaponSelection;
+ ScalingMovie _explosions;
+ NotificationCallBack _explosionCallBack;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/mars/planetmover.cpp b/engines/pegasus/neighborhood/mars/planetmover.cpp
new file mode 100644
index 0000000000..a340120c12
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/planetmover.cpp
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/movie.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/neighborhood/mars/constants.h"
+#include "pegasus/neighborhood/mars/hermite.h"
+#include "pegasus/neighborhood/mars/planetmover.h"
+#include "pegasus/neighborhood/mars/shuttleenergymeter.h"
+
+namespace Pegasus {
+
+static const TimeScale kRovingScale = kTractorBeamScale;
+static const TimeValue kRovingTime = kTenSeconds * kRovingScale;
+static const TimeValue kRovingSlop = kTwoSeconds * kRovingScale;
+
+static const CoordType kMaxVelocity = 20;
+
+PlanetMover::PlanetMover() {
+ setScale(kRovingScale);
+ _dropping = false;
+ _planetMovie = 0;
+}
+
+void PlanetMover::startMoving(Movie *planetMovie) {
+ _planetMovie = planetMovie;
+ _p4 = kPlanetStartTop;
+ _r4 = ((PegasusEngine *)g_engine)->getRandomNumber(kMaxVelocity - 1);
+ if (_r4 + _p4 < kPlanetStopTop)
+ _r4 = kPlanetStopTop - _p4;
+ newDestination();
+}
+
+void PlanetMover::stopMoving() {
+ stop();
+}
+
+void PlanetMover::dropPlanetOutOfSight() {
+ stop();
+ CoordType currentLoc = hermite(_p1, _p4, _r1, _r4, _lastTime, _duration);
+ CoordType currentV = dHermite(_p1, _p4, _r1, _r4, _lastTime, _duration);
+ _p1 = currentLoc;
+ _r1 = currentV;
+ _p4 = kPlanetStartTop;
+ _r4 = 0;
+ _duration = kTractorBeamTime - kTractorBeamScale;
+ _dropping = true;
+ setSegment(0, _duration);
+ setTime(0);
+ start();
+}
+
+void PlanetMover::newDestination() {
+ _p1 = _p4;
+ _r1 = _r4;
+
+ _p4 = kPlanetStopTop + ((PegasusEngine *)g_engine)->getRandomNumber(kPlanetStartTop - kPlanetStopTop - 1);
+ _r4 = ((PegasusEngine *)g_engine)->getRandomNumber(kMaxVelocity - 1);
+
+ if (_r4 + _p4 < kPlanetStopTop)
+ _r4 = kPlanetStopTop - _p4;
+
+ stop();
+ _duration = kRovingTime + ((PegasusEngine *)g_engine)->getRandomNumber(kRovingSlop - 1);
+ setSegment(0, _duration);
+ setTime(0);
+ start();
+}
+
+void PlanetMover::timeChanged(const TimeValue) {
+ if (_planetMovie) {
+ _planetMovie->moveElementTo(kPlanetStartLeft, hermite(_p1, _p4, _r1, _r4, _lastTime, _duration));
+ if (_lastTime == _duration) {
+ if (_dropping)
+ stop();
+ else
+ newDestination();
+ }
+ }
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/mars/planetmover.h b/engines/pegasus/neighborhood/mars/planetmover.h
new file mode 100644
index 0000000000..2c195387e8
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/planetmover.h
@@ -0,0 +1,57 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_MARS_PLANETMOVER_H
+#define PEGASUS_NEIGHBORHOOD_MARS_PLANETMOVER_H
+
+#include "pegasus/timers.h"
+
+namespace Pegasus {
+
+class Movie;
+
+class PlanetMover : IdlerTimeBase {
+public:
+ PlanetMover();
+ virtual ~PlanetMover() {}
+
+ void startMoving(Movie *);
+ void stopMoving();
+
+ void dropPlanetOutOfSight();
+
+protected:
+ void newDestination();
+ virtual void timeChanged(const TimeValue);
+
+ Movie *_planetMovie;
+ CoordType _p1, _p4, _r1, _r4;
+ TimeValue _duration;
+ bool _dropping;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/mars/reactor.cpp b/engines/pegasus/neighborhood/mars/reactor.cpp
new file mode 100644
index 0000000000..334fb98879
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/reactor.cpp
@@ -0,0 +1,297 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * aint32 with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "pegasus/pegasus.h"
+#include "pegasus/neighborhood/mars/reactor.h"
+
+namespace Pegasus {
+
+static const CoordType kCurrentGuessWidth = 121;
+static const CoordType kCurrentGuessHeight = 23;
+
+static const CoordType kOneGuessWidth = 25;
+static const CoordType kOneGuessHeight = 23;
+
+static const ResIDType kReactorChoicesPICTID = 905;
+
+static const CoordType kCurrentGuessLeft = kNavAreaLeft + 146;
+static const CoordType kCurrentGuessTop = kNavAreaTop + 90;
+
+ReactorGuess::ReactorGuess(const DisplayElementID id) : DisplayElement(id) {
+ setBounds(kCurrentGuessLeft, kCurrentGuessTop, kCurrentGuessLeft + kCurrentGuessWidth,
+ kCurrentGuessTop + kCurrentGuessHeight);
+ setDisplayOrder(kMonitorLayer);
+ _currentGuess[0] = -1;
+ _currentGuess[1] = -1;
+ _currentGuess[2] = -1;
+}
+
+void ReactorGuess::initReactorGuess() {
+ _colors.getImageFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kReactorChoicesPICTID);
+ startDisplaying();
+ show();
+}
+
+void ReactorGuess::disposeReactorGuess() {
+ stopDisplaying();
+ _colors.deallocateSurface();
+}
+
+void ReactorGuess::setGuess(int32 a, int32 b, int32 c) {
+ _currentGuess[0] = a;
+ _currentGuess[1] = b;
+ _currentGuess[2] = c;
+ triggerRedraw();
+}
+
+void ReactorGuess::draw(const Common::Rect &) {
+ if (_colors.isSurfaceValid()) {
+ Common::Rect r1(0, 0, kOneGuessWidth, kOneGuessHeight);
+ Common::Rect r2 = r1;
+
+ for (int i = 0; i < 3; i++) {
+ if (_currentGuess[i] >= 0) {
+ r1.moveTo(kOneGuessWidth * _currentGuess[i], 0);
+ r2.moveTo(kCurrentGuessLeft + 48 * i, kCurrentGuessTop);
+ _colors.copyToCurrentPortTransparent(r1, r2);
+ }
+ }
+ }
+}
+
+static const CoordType kReactorChoiceHiliteWidth = 166;
+static const CoordType kReactorChoiceHiliteHeight = 26;
+
+static const CoordType kChoiceHiliteLefts[6] = {
+ 0,
+ 34,
+ 34 + 34,
+ 34 + 34 + 32,
+ 34 + 34 + 32 + 34,
+ 34 + 34 + 32 + 34 + 32
+};
+
+static const ResIDType kReactorChoiceHilitePICTID = 901;
+
+static const CoordType kReactorChoiceHiliteLeft = kNavAreaLeft + 116;
+static const CoordType kReactorChoiceHiliteTop = kNavAreaTop + 158;
+
+ReactorChoiceHighlight::ReactorChoiceHighlight(const DisplayElementID id) : DisplayElement(id) {
+ setBounds(kReactorChoiceHiliteLeft, kReactorChoiceHiliteTop, kReactorChoiceHiliteLeft + kReactorChoiceHiliteWidth,
+ kReactorChoiceHiliteTop + kReactorChoiceHiliteHeight);
+ setDisplayOrder(kMonitorLayer);
+}
+
+void ReactorChoiceHighlight::initReactorChoiceHighlight() {
+ _colors.getImageFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kReactorChoiceHilitePICTID);
+ startDisplaying();
+ show();
+}
+
+void ReactorChoiceHighlight::disposeReactorChoiceHighlight() {
+ stopDisplaying();
+ _colors.deallocateSurface();
+}
+
+void ReactorChoiceHighlight::draw(const Common::Rect &) {
+ if (_colors.isSurfaceValid()) {
+ for (int i = 0; i < 5; ++i) {
+ if (_choices.getFlag(i)) {
+ Common::Rect r1(0, 0, kChoiceHiliteLefts[i + 1] - kChoiceHiliteLefts[i], kReactorChoiceHiliteHeight);
+ Common::Rect r2 = r1;
+ r1.moveTo(kChoiceHiliteLefts[i], 0);
+ r2.moveTo(kReactorChoiceHiliteLeft + kChoiceHiliteLefts[i], kReactorChoiceHiliteTop);
+ _colors.copyToCurrentPort(r1, r2);
+ }
+ }
+ }
+}
+
+static const CoordType kReactorHistoryWidth = 128;
+static const CoordType kReactorHistoryHeight = 168;
+
+static const CoordType kColorWidths[5] = { 24, 25, 25, 26, 27 };
+static const CoordType kColorHeights[5] = { 14, 15, 17, 17, 19};
+
+static const CoordType kHistoryLefts[5][3] = {
+ { 302 + kNavAreaLeft, 329 + kNavAreaLeft, 357 + kNavAreaLeft },
+ { 302 + kNavAreaLeft, 331 + kNavAreaLeft, 360 + kNavAreaLeft },
+ { 303 + kNavAreaLeft, 333 + kNavAreaLeft, 363 + kNavAreaLeft },
+ { 304 + kNavAreaLeft, 335 + kNavAreaLeft, 366 + kNavAreaLeft },
+ { 305 + kNavAreaLeft, 337 + kNavAreaLeft, 369 + kNavAreaLeft }
+};
+
+static const CoordType kHistoryTops[5] = {
+ 39 + kNavAreaTop,
+ 61 + kNavAreaTop,
+ 84 + kNavAreaTop,
+ 110 + kNavAreaTop,
+ 137 + kNavAreaTop
+};
+
+static const CoordType kOneAnswerWidth = 35;
+static const CoordType kOneAnswerHeight = 27;
+
+static const CoordType kDigitWidth = 16;
+static const CoordType kDigitHeight = 12;
+
+static const CoordType kCorrectCountLefts[5] = {
+ 388 + kNavAreaLeft,
+ 392 + kNavAreaLeft,
+ 398 + kNavAreaLeft,
+ 402 + kNavAreaLeft,
+ 406 + kNavAreaLeft
+};
+
+static const CoordType kCorrectCountTops[5] = {
+ 40 + kNavAreaTop,
+ 62 + kNavAreaTop,
+ 86 + kNavAreaTop,
+ 112 + kNavAreaTop,
+ 140 + kNavAreaTop
+};
+
+static const ResIDType kReactorDigitsPICTID = 902;
+static const ResIDType kReactorHistoryPICTID = 903;
+static const ResIDType kReactorAnswerPICTID = 904;
+
+static const CoordType kReactorHistoryLeft = kNavAreaLeft + 302;
+static const CoordType kReactorHistoryTop = kNavAreaTop + 39;
+
+static const CoordType kAnswerLeft = kNavAreaLeft + 304;
+static const CoordType kAnswerTop = kNavAreaTop + 180;
+
+ReactorHistory::ReactorHistory(const DisplayElementID id) : DisplayElement(id) {
+ setBounds(kReactorHistoryLeft, kReactorHistoryTop, kReactorHistoryLeft + kReactorHistoryWidth,
+ kReactorHistoryTop + kReactorHistoryHeight);
+ setDisplayOrder(kMonitorLayer);
+ _numGuesses = 0;
+ _answer[0] = -1;
+ _answer[1] = -1;
+ _answer[2] = -1;
+ _showAnswer = false;
+}
+
+void ReactorHistory::initReactorHistory() {
+ _colors.getImageFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kReactorHistoryPICTID);
+ _digits.getImageFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kReactorDigitsPICTID);
+ _answerColors.getImageFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kReactorAnswerPICTID);
+ startDisplaying();
+ show();
+}
+
+void ReactorHistory::disposeReactorHistory() {
+ stopDisplaying();
+ _colors.deallocateSurface();
+}
+
+void ReactorHistory::addGuess(int32 a, int32 b, int32 c) {
+ _history[_numGuesses][0] = a;
+ _history[_numGuesses][1] = b;
+ _history[_numGuesses][2] = c;
+ _numGuesses++;
+ triggerRedraw();
+}
+
+void ReactorHistory::clearHistory() {
+ _numGuesses = 0;
+ _showAnswer = false;
+ triggerRedraw();
+}
+
+void ReactorHistory::setAnswer(int32 a, int32 b, int32 c) {
+ _answer[0] = a;
+ _answer[1] = b;
+ _answer[2] = c;
+}
+
+void ReactorHistory::showAnswer() {
+ _showAnswer = true;
+ triggerRedraw();
+}
+
+bool ReactorHistory::isSolved() {
+ for (int i = 0; i < _numGuesses; i++)
+ if (_history[i][0] == _answer[0] && _history[i][1] == _answer[1] && _history[i][2] == _answer[2])
+ return true;
+
+ return false;
+}
+
+void ReactorHistory::draw(const Common::Rect &) {
+ static const CoordType kColorTops[5] = {
+ 0,
+ kColorHeights[0],
+ kColorHeights[0] + kColorHeights[1],
+ kColorHeights[0] + kColorHeights[1] + kColorHeights[2],
+ kColorHeights[0] + kColorHeights[1] + kColorHeights[2] + kColorHeights[3],
+ };
+
+ if (_colors.isSurfaceValid() && _digits.isSurfaceValid()) {
+ for (int i = 0; i < _numGuesses; ++i) {
+ Common::Rect r1(0, 0, kColorWidths[i], kColorHeights[i]);
+ Common::Rect r2 = r1;
+ Common::Rect r3(0, 0, kDigitWidth, kDigitHeight);
+ Common::Rect r4 = r3;
+ int correct = 0;
+
+ for (int j = 0; j < 3; ++j) {
+ r1.moveTo(kColorWidths[i] * _history[i][j], kColorTops[i]);
+ r2.moveTo(kHistoryLefts[i][j], kHistoryTops[i]);
+ _colors.copyToCurrentPortTransparent(r1, r2);
+
+ if (_history[i][j] == _answer[j])
+ correct++;
+ }
+
+ r3.moveTo(kDigitWidth * correct, 0);
+ r4.moveTo(kCorrectCountLefts[i], kCorrectCountTops[i]);
+ _digits.copyToCurrentPort(r3, r4);
+ }
+
+ if (_showAnswer && _answerColors.isSurfaceValid()) {
+ Common::Rect r1(0, 0, kOneAnswerWidth, kOneAnswerHeight);
+ Common::Rect r2 = r1;
+
+ for (int i = 0; i < 3; i++) {
+ r1.moveTo(kOneAnswerWidth * _answer[i], 0);
+ r2.moveTo(kAnswerLeft + 34 * i, kAnswerTop);
+ _answerColors.copyToCurrentPortTransparent(r1, r2);
+ }
+ }
+ }
+}
+
+int32 ReactorHistory::getCurrentNumCorrect() {
+ int correct = 0;
+
+ for (int i = 0; i < 3; i++)
+ if (_history[_numGuesses - 1][i] == _answer[i])
+ correct++;
+
+ return correct;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/mars/reactor.h b/engines/pegasus/neighborhood/mars/reactor.h
new file mode 100644
index 0000000000..86338f8266
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/reactor.h
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_MARS_REACTOR_H
+#define PEGASUS_NEIGHBORHOOD_MARS_REACTOR_H
+
+#include "pegasus/elements.h"
+#include "pegasus/surface.h"
+#include "pegasus/util.h"
+
+namespace Pegasus {
+
+class ReactorGuess : public DisplayElement {
+public:
+ ReactorGuess(const DisplayElementID);
+ virtual ~ReactorGuess() {}
+
+ void initReactorGuess();
+ void disposeReactorGuess();
+
+ void setGuess(int32, int32, int32);
+
+ void draw(const Common::Rect &);
+
+protected:
+ int32 _currentGuess[3];
+
+ Surface _colors;
+};
+
+class ReactorChoiceHighlight : public DisplayElement {
+public:
+ ReactorChoiceHighlight(const DisplayElementID);
+ virtual ~ReactorChoiceHighlight() {}
+
+ void initReactorChoiceHighlight();
+ void disposeReactorChoiceHighlight();
+
+ void resetHighlight() {
+ _choices.clearAllFlags();
+ triggerRedraw();
+ }
+
+ bool choiceHighlighted(uint32 whichChoice) { return _choices.getFlag(whichChoice); }
+
+ void draw(const Common::Rect &);
+
+ void highlightChoice(uint32 whichChoice) {
+ _choices.setFlag(whichChoice);
+ triggerRedraw();
+ }
+
+protected:
+ Surface _colors;
+ FlagsArray<byte, 5> _choices;
+};
+
+class ReactorHistory : public DisplayElement {
+public:
+ ReactorHistory(const DisplayElementID);
+ virtual ~ReactorHistory() {}
+
+ void initReactorHistory();
+ void disposeReactorHistory();
+
+ void draw(const Common::Rect &);
+
+ void addGuess(int32, int32, int32);
+ int32 getNumGuesses() { return _numGuesses; }
+ void clearHistory();
+ void setAnswer(int32, int32, int32);
+ void showAnswer();
+ bool isSolved();
+ int32 getCurrentNumCorrect();
+
+protected:
+ Surface _colors, _digits, _answerColors;
+ int32 _answer[3];
+ int32 _history[5][3];
+ int32 _numGuesses;
+ bool _showAnswer;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/mars/robotship.cpp b/engines/pegasus/neighborhood/mars/robotship.cpp
new file mode 100644
index 0000000000..1f4bbc1779
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/robotship.cpp
@@ -0,0 +1,267 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/neighborhood/mars/hermite.h"
+#include "pegasus/neighborhood/mars/mars.h"
+#include "pegasus/neighborhood/mars/robotship.h"
+#include "pegasus/neighborhood/mars/spacechase3d.h"
+#include "pegasus/neighborhood/mars/spacejunk.h"
+
+namespace Pegasus {
+
+static const TimeScale kRovingScale = kTractorBeamScale;
+static const TimeValue kRovingTime = kSixSeconds * kRovingScale;
+static const TimeValue kRovingSlop = kThreeSeconds * kRovingScale;
+
+static const int kNumSpriteColumns = 15;
+static const int kNumSpriteRows = 16;
+
+static const CoordType kInitialLocationLeft = kShuttleWindowLeft - 50;
+static const CoordType kInitialLocationTop = kShuttleWindowTop - 50;
+static const CoordType kInitialLocationWidth = kShuttleWindowWidth + 100;
+static const CoordType kInitialLocationHeight = kShuttleWindowHeight + 100;
+
+static const CoordType kVelocityVectorLength = 100;
+static const CoordType kVelocityVectorSlop = 50;
+
+static const CoordType kRovingLeft = kShuttleWindowLeft + 20;
+static const CoordType kRovingTop = kShuttleWindowTop + 20;
+static const CoordType kRovingWidth = kShuttleWindowMidH - kRovingLeft;
+static const CoordType kRovingHeight = kShuttleWindowMidV - kRovingTop;
+
+RobotShip *g_robotShip = 0;
+
+RobotShip::RobotShip() : _spritesMovie(kNoDisplayElement) {
+ g_robotShip = this;
+ _shipRange = Common::Rect(kShuttleWindowLeft, kShuttleWindowTop, kShuttleWindowLeft + kShuttleWindowWidth,
+ kShuttleWindowTop + kShuttleWindowHeight);
+ setScale(kRovingScale);
+ _currentLocation.x = 0;
+ _currentLocation.y = 0;
+ _snaring = false;
+ _dropJunkFuse.setFunctor(new Common::Functor0Mem<void, RobotShip>(this, &RobotShip::timeToDropJunk));
+ _duration = 0xFFFFFFFF;
+}
+
+RobotShip::~RobotShip() {
+ g_robotShip = 0;
+}
+
+void RobotShip::initRobotShip() {
+ _spritesMovie.initFromMovieFile("Images/Mars/Ship.movie", true);
+ _spritesMovie.setDisplayOrder(kShuttleRobotShipOrder);
+ _spritesMovie.moveElementTo(kPlanetStartLeft, kPlanetStartTop);
+ _spritesMovie.startDisplaying();
+ _spritesMovie.show();
+
+ Common::Rect r;
+ _spritesMovie.getBounds(r);
+ _shipWidth = r.width();
+ _shipHeight = r.height();
+ _dead = false;
+}
+
+void RobotShip::cleanUpRobotShip() {
+ _dropJunkFuse.stopFuse();
+ _spritesMovie.stopDisplaying();
+ _spritesMovie.releaseMovie();
+}
+
+void RobotShip::startMoving() {
+ if (((PegasusEngine *)g_engine)->getRandomBit()) {
+ _p4.x = kInitialLocationLeft + ((PegasusEngine *)g_engine)->getRandomNumber(kInitialLocationWidth - 1);
+ if (((PegasusEngine *)g_engine)->getRandomBit())
+ _p4.y = kInitialLocationTop;
+ else
+ _p4.y = kInitialLocationTop + kInitialLocationHeight;
+ } else {
+ _p4.y = kInitialLocationTop + ((PegasusEngine *)g_engine)->getRandomNumber(kInitialLocationHeight - 1);
+ if (((PegasusEngine *)g_engine)->getRandomBit())
+ _p4.x = kInitialLocationLeft;
+ else
+ _p4.x = kInitialLocationLeft + kInitialLocationWidth;
+ }
+
+ makeVelocityVector(_p4.x, _p4.y, kShuttleWindowLeft + kShuttleWindowWidth / 2,
+ kShuttleWindowTop + kShuttleWindowHeight / 2, _r4);
+ newDestination();
+ setUpNextDropTime();
+}
+
+void RobotShip::killRobotShip() {
+ cleanUpRobotShip();
+ _dead = true;
+}
+
+void RobotShip::setUpNextDropTime() {
+ if (!isSnared()) {
+ _dropJunkFuse.primeFuse(kJunkDropBaseTime + ((PegasusEngine *)g_engine)->getRandomNumber(kJunkDropSlopTime));
+ _dropJunkFuse.lightFuse();
+ }
+}
+
+void RobotShip::timeToDropJunk() {
+ if (g_spaceJunk) {
+ CoordType x, y;
+ _spritesMovie.getCenter(x, y);
+ g_spaceJunk->launchJunk(((PegasusEngine *)g_engine)->getRandomNumber(24), x, y);
+ }
+}
+
+void RobotShip::newDestination() {
+ _p1 = _p4;
+ _r1 = _r4;
+
+ _p4.x = kRovingLeft + ((PegasusEngine *)g_engine)->getRandomNumber(kRovingWidth - 1);
+ _p4.y = kRovingTop + ((PegasusEngine *)g_engine)->getRandomNumber(kRovingHeight - 1);
+
+ if (((PegasusEngine *)g_engine)->getRandomNumber(7) < 6) {
+ if (!sameSign(_p4.x - kShuttleWindowMidH, kShuttleWindowMidH - _p1.x)) {
+ if (sign(_p4.x - kShuttleWindowMidH) > 0)
+ _p4.x -= kRovingWidth;
+ else
+ _p4.x += kRovingWidth;
+ }
+ }
+
+ if (((PegasusEngine *)g_engine)->getRandomNumber(7) < 6) {
+ if (!sameSign(_p4.y - kShuttleWindowMidV, kShuttleWindowMidV - _p1.y)) {
+ if (sign(_p4.y - kShuttleWindowMidV) > 0)
+ _p4.y -= kRovingHeight;
+ else
+ _p4.y += kRovingHeight;
+ }
+ }
+
+ makeVelocityVector(_p4.x, _p4.y, kShuttleWindowLeft + kShuttleWindowWidth / 2,
+ kShuttleWindowTop + kShuttleWindowHeight / 2, _r4);
+ stop();
+ _duration = kRovingTime + ((PegasusEngine *)g_engine)->getRandomNumber(kRovingSlop - 1);
+ setSegment(0, _duration);
+ setTime(0);
+ start();
+}
+
+void RobotShip::moveRobotTo(CoordType x, CoordType y) {
+ _currentLocation.x = x;
+ _currentLocation.y = y;
+
+ if (_spritesMovie.isMovieValid()) {
+ _spritesMovie.moveElementTo(x - (_shipWidth >> 1), y - (_shipHeight >> 1));
+
+ if (x < _shipRange.left)
+ x = 0;
+ else if (x > _shipRange.right - 1)
+ x = _shipRange.width() - 1;
+ else
+ x -= _shipRange.left;
+
+ if (y < _shipRange.top)
+ y = 0;
+ else if (y > _shipRange.bottom - 1)
+ y = _shipRange.height() - 1;
+ else
+ y -= _shipRange.top;
+
+ x = kNumSpriteColumns * x / _shipRange.width();
+ y = kNumSpriteRows * y / _shipRange.height();
+
+ _spritesMovie.setTime(40 * (x + y * kNumSpriteColumns));
+ _spritesMovie.redrawMovieWorld();
+ }
+}
+
+bool RobotShip::pointInShuttle(Common::Point &pt) {
+ Common::Rect r;
+ _spritesMovie.getBounds(r);
+
+ int dx = r.width() / 4;
+ int dy = r.height() / 6;
+
+ r.left += dx;
+ r.right -= dx;
+ r.top += dy;
+ r.bottom -= dy;
+
+ return r.contains(pt);
+}
+
+void RobotShip::hitByEnergyBeam(Common::Point impactPoint) {
+ ((Mars *)g_neighborhood)->decreaseRobotShuttleEnergy(1, impactPoint);
+ setGlowing(true);
+ ((PegasusEngine *)g_engine)->delayShell(1, 3);
+ setGlowing(false);
+}
+
+void RobotShip::hitByGravitonCannon(Common::Point impactPoint) {
+ GameState.setMarsHitRobotWithCannon(true);
+ ((Mars *)g_neighborhood)->decreaseRobotShuttleEnergy(6, impactPoint);
+}
+
+void RobotShip::snareByTractorBeam() {
+ _dropJunkFuse.stopFuse();
+ stop();
+
+ Common::Point currentV;
+ dHermite(_p1, _p4, _r1, _r4, _lastTime, _duration, currentV);
+
+ _p1 = _currentLocation;
+ _r1 = currentV;
+ _p4.x = kShuttleWindowMidH;
+ _p4.y = kShuttleWindowMidV;
+ _r4.x = 0;
+ _r4.y = 0;
+ _duration = kTractorBeamTime;
+ _snaring = true;
+ setSegment(0, _duration);
+ setTime(0);
+ start();
+}
+
+void RobotShip::timeChanged(const TimeValue) {
+ Common::Point newLocation;
+ hermite(_p1, _p4, _r1, _r4, _lastTime, _duration, newLocation);
+ moveRobotTo(newLocation.x, newLocation.y);
+
+ if (_lastTime == _duration) {
+ if (_snaring)
+ stop();
+ else
+ newDestination();
+ }
+}
+
+void RobotShip::makeVelocityVector(CoordType x1, CoordType y1, CoordType x2, CoordType y2, Common::Point &vector) {
+ CoordType length = ((PegasusEngine *)g_engine)->getRandomNumber(kVelocityVectorSlop - 1) + kVelocityVectorLength;
+ vector.x = x2 - x1;
+ vector.y = y2 - y1;
+ float oldLength = sqrt((float)(vector.x * vector.x + vector.y * vector.y));
+ vector.x = (int)(vector.x * length / oldLength);
+ vector.y = (int)(vector.y * length / oldLength);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/mars/robotship.h b/engines/pegasus/neighborhood/mars/robotship.h
new file mode 100644
index 0000000000..04be3ea56e
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/robotship.h
@@ -0,0 +1,84 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_MARS_ROBOTSHIP_H
+#define PEGASUS_NEIGHBORHOOD_MARS_ROBOTSHIP_H
+
+#include "pegasus/movie.h"
+
+namespace Pegasus {
+
+static const CoordType kShuttleMovieWidth = 114;
+static const CoordType kShuttleMovieHeight = 42;
+
+class RobotShip : IdlerTimeBase {
+public:
+ RobotShip();
+ virtual ~RobotShip();
+
+ void initRobotShip();
+ void cleanUpRobotShip();
+
+ void startMoving();
+
+ void killRobotShip();
+
+ bool pointInShuttle(Common::Point&);
+
+ void hitByEnergyBeam(Common::Point impactPoint);
+ void hitByGravitonCannon(Common::Point impactPoint);
+
+ void getShuttleBounds(Common::Rect &r) { _spritesMovie.getBounds(r); }
+
+ void setGlowing(const bool glowing) { _spritesMovie.setGlowing(glowing); }
+
+ void snareByTractorBeam();
+ bool isSnared() { return _snaring && getTime() == _duration; }
+
+ bool isDead() { return _dead; }
+
+ void setUpNextDropTime();
+
+protected:
+ void newDestination();
+ void moveRobotTo(CoordType, CoordType);
+ void timeToDropJunk();
+ virtual void timeChanged(const TimeValue);
+ void makeVelocityVector(CoordType, CoordType, CoordType, CoordType, Common::Point &);
+
+ GlowingMovie _spritesMovie;
+ Common::Rect _shipRange;
+ int _shipWidth, _shipHeight;
+ Common::Point _p1, _p4, _r1, _r4, _currentLocation;
+ FuseFunction _dropJunkFuse;
+ TimeValue _duration;
+ bool _snaring, _dead;
+};
+
+extern RobotShip *g_robotShip;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/mars/shuttleenergymeter.cpp b/engines/pegasus/neighborhood/mars/shuttleenergymeter.cpp
new file mode 100644
index 0000000000..cd08dbae6a
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/shuttleenergymeter.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/neighborhood/mars/constants.h"
+#include "pegasus/neighborhood/mars/shuttleenergymeter.h"
+
+namespace Pegasus {
+
+ShuttleEnergyMeter::ShuttleEnergyMeter() : FaderAnimation(kNoDisplayElement) {
+ setBounds(kShuttleEnergyLeft, kShuttleEnergyTop, kShuttleEnergyLeft + kShuttleEnergyWidth,
+ kShuttleEnergyTop + kShuttleEnergyHeight);
+ setDisplayOrder(kShuttleStatusOrder);
+ setFaderValue(0);
+}
+
+void ShuttleEnergyMeter::initShuttleEnergyMeter() {
+ _meterImage.getImageFromPICTFile("Images/Mars/Shuttle Energy.pict");
+ _lowWarning.getImageFromPICTFile("Images/Mars/Shuttle Low Energy.pict");
+ startDisplaying();
+ show();
+}
+
+void ShuttleEnergyMeter::disposeShuttleEnergyMeter() {
+ stopFader();
+ hide();
+ stopDisplaying();
+ _meterImage.deallocateSurface();
+ _lowWarning.deallocateSurface();
+}
+
+void ShuttleEnergyMeter::draw(const Common::Rect &) {
+ int32 currentValue = getFaderValue();
+
+ Common::Rect r1, r2, bounds;
+ getBounds(bounds);
+
+ if (currentValue < kLowShuttleEnergy) {
+ _lowWarning.getSurfaceBounds(r1);
+ r2 = r1;
+ r2.moveTo(bounds.left, bounds.top);
+ _lowWarning.copyToCurrentPort(r1, r2);
+ }
+
+ _meterImage.getSurfaceBounds(r1);
+ r1.right = r1.left + r1.width() * currentValue / kFullShuttleEnergy;
+ r2 = r1;
+ r2.moveTo(bounds.left + 102, bounds.top + 6);
+ _meterImage.copyToCurrentPort(r1, r2);
+}
+
+void ShuttleEnergyMeter::powerUpMeter() {
+ FaderMoveSpec moveSpec;
+ moveSpec.makeTwoKnotFaderSpec(kThirtyTicksPerSecond, 0, 0, 45, kFullShuttleEnergy);
+ startFader(moveSpec);
+}
+
+void ShuttleEnergyMeter::setEnergyValue(const int32 value) {
+ stopFader();
+ FaderMoveSpec moveSpec;
+ moveSpec.makeTwoKnotFaderSpec(kFifteenTicksPerSecond, value * 3, value, kFullShuttleEnergy * 3, kFullShuttleEnergy);
+ startFader(moveSpec);
+}
+
+void ShuttleEnergyMeter::drainForTractorBeam() {
+ stopFader();
+ TimeValue startTime = 0, stopTime;
+ int32 startValue = getFaderValue(), stopValue;
+
+ if (startValue < kTractorBeamEnergy) {
+ stopTime = startValue * kTractorBeamTime / kTractorBeamEnergy;
+ stopValue = 0;
+ } else {
+ stopTime = kTractorBeamTime;
+ stopValue = startValue - kTractorBeamEnergy;
+ }
+
+ FaderMoveSpec moveSpec;
+ moveSpec.makeTwoKnotFaderSpec(kTractorBeamScale, startTime, startValue, stopTime, stopValue);
+ startFader(moveSpec);
+}
+
+int32 ShuttleEnergyMeter::getEnergyValue() const {
+ return getFaderValue();
+}
+
+void ShuttleEnergyMeter::dropEnergyValue(const int32 delta) {
+ setEnergyValue(getFaderValue() - delta);
+}
+
+bool ShuttleEnergyMeter::enoughEnergyForTractorBeam() const {
+ return getEnergyValue() >= kTractorBeamEnergy;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/mars/shuttleenergymeter.h b/engines/pegasus/neighborhood/mars/shuttleenergymeter.h
new file mode 100644
index 0000000000..51161e094e
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/shuttleenergymeter.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_MARS_SHUTTLEENERGYMETER_H
+#define PEGASUS_NEIGHBORHOOD_MARS_SHUTTLEENERGYMETER_H
+
+#include "pegasus/fader.h"
+#include "pegasus/surface.h"
+
+namespace Pegasus {
+
+static const int32 kFullShuttleEnergy = 100;
+// Low is 20 percent
+static const int32 kLowShuttleEnergy = kFullShuttleEnergy * 20 / 100;
+
+static const int32 kMinDampingEnergy = 15;
+static const int32 kMinGravitonEnergy = 63;
+
+static const TimeScale kTractorBeamScale = kFifteenTicksPerSecond;
+static const TimeValue kTractorBeamTime = kFiveSeconds * kTractorBeamScale;
+static const int32 kTractorBeamEnergy = kLowShuttleEnergy;
+
+class ShuttleEnergyMeter : public FaderAnimation {
+public:
+ ShuttleEnergyMeter();
+ ~ShuttleEnergyMeter() {}
+
+ void initShuttleEnergyMeter();
+ void disposeShuttleEnergyMeter();
+
+ void powerUpMeter();
+
+ void setEnergyValue(const int32);
+ int32 getEnergyValue() const;
+
+ void dropEnergyValue(const int32);
+
+ void drainForTractorBeam();
+
+ bool enoughEnergyForTractorBeam() const;
+
+ void draw(const Common::Rect &);
+
+protected:
+ Surface _meterImage;
+ Surface _lowWarning;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/mars/shuttlehud.cpp b/engines/pegasus/neighborhood/mars/shuttlehud.cpp
new file mode 100644
index 0000000000..11e826278b
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/shuttlehud.cpp
@@ -0,0 +1,246 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/pegasus.h"
+#include "pegasus/neighborhood/mars/constants.h"
+#include "pegasus/neighborhood/mars/robotship.h"
+#include "pegasus/neighborhood/mars/shuttlehud.h"
+
+namespace Pegasus {
+
+static const CoordType kHUDTargetGridLeft = kShuttleWindowLeft + 16;
+static const CoordType kHUDTargetGridTop = kShuttleWindowTop + 8;
+static const CoordType kHUDTargetGridWidth = 328;
+static const CoordType kHUDTargetGridHeight = 206;
+
+static const CoordType kHUDRS232Left = kHUDTargetGridLeft + 264;
+static const CoordType kHUDRS232Top = kHUDTargetGridTop + 2;
+
+static const CoordType kHUDLockLeft = kShuttleWindowLeft + 101;
+static const CoordType kHUDLockTop = kShuttleWindowTop + 49;
+static const CoordType kHUDLockWidth = 145;
+static const CoordType kHUDLockHeight = 124;
+
+static const CoordType kTractorLockWidth = 50;
+static const CoordType kTractorLockHeight = 30;
+
+static const CoordType kTractorLockLeft = kShuttleWindowMidH - kTractorLockWidth / 2;
+static const CoordType kTractorLockTop = kShuttleWindowMidV - kTractorLockHeight / 2;
+static const CoordType kTractorLockRight = kTractorLockLeft + kTractorLockWidth;
+static const CoordType kTractorLockBottom = kTractorLockTop + kTractorLockHeight;
+
+static const uint16 s_RS232Data[] = {
+ 0xF0E1, 0xCE70,
+ 0xF9E1, 0xEF78,
+ 0x4900, 0x2108,
+ 0x79C0, 0xE738,
+ 0x70E1, 0xC770,
+ 0x5821, 0x0140,
+ 0x4DE1, 0xEF78,
+ 0x45C1, 0xEE78
+};
+
+static const uint16 s_lockData[] = {
+ 0xE007, 0xFE1F, 0xF8E0, 0x7000,
+ 0xE00F, 0xFF3F, 0xFCE0, 0xE000,
+ 0xE00E, 0x0738, 0x1CE1, 0xC000,
+ 0xE00E, 0x0738, 0x00FF, 0x8000,
+ 0xE00E, 0x0738, 0x00FF, 0x0000,
+ 0xE00E, 0x0738, 0x00E3, 0x8000,
+ 0xE00E, 0x0738, 0x1CE1, 0xC000,
+ 0xFFCF, 0xFF3F, 0xFCE0, 0xE000,
+ 0xFFC7, 0xFE1F, 0xF8E0, 0x7000
+};
+
+#define drawHUDLockLine(x1, y1, x2, y2, penX, penY, color) \
+ screen->drawThickLine((x1) + kHUDLockLeft, (y1) + kHUDLockTop, \
+ (x2) + kHUDLockLeft, (y2) + kHUDLockTop, penX, penY, color)
+
+#define drawHUDLockArrows(offset, color) \
+ drawHUDLockLine(63, 0 + (offset), 68, 5 + (offset), 1, 3, color); \
+ drawHUDLockLine(71, 8 + (offset), 77, 14 + (offset), 1, 3, color); \
+ drawHUDLockLine(78, 14 + (offset), 84, 8 + (offset), 1, 3, color); \
+ drawHUDLockLine(87, 5 + (offset), 92, 0 + (offset), 1, 3, color); \
+ drawHUDLockLine(63, 121 - (offset), 68, 116 - (offset), 1, 3, color); \
+ drawHUDLockLine(71, 113 - (offset), 77, 107 - (offset), 1, 3, color); \
+ drawHUDLockLine(78, 107 - (offset), 84, 113 - (offset), 1, 3, color); \
+ drawHUDLockLine(87, 116 - (offset), 92, 121 - (offset), 1, 3, color); \
+\
+ drawHUDLockLine(13 + (offset), 47, 18 + (offset), 52, 3, 1, color); \
+ drawHUDLockLine(21 + (offset), 55, 27 + (offset), 61, 3, 1, color); \
+ drawHUDLockLine(27 + (offset), 62, 21 + (offset), 68, 3, 1, color); \
+ drawHUDLockLine(18 + (offset), 71, 13 + (offset), 76, 3, 1, color); \
+ drawHUDLockLine(142 - (offset), 47, 137 - (offset), 52, 3, 1, color); \
+ drawHUDLockLine(134 - (offset), 55, 128 - (offset), 61, 3, 1, color); \
+ drawHUDLockLine(128 - (offset), 62, 134 - (offset), 68, 3, 1, color); \
+ drawHUDLockLine(137 - (offset), 71, 142 - (offset), 76, 3, 1, color)
+
+ShuttleHUD::ShuttleHUD() : DisplayElement(kNoDisplayElement) {
+ _lightGreen = g_system->getScreenFormat().RGBToColor(0, 204, 0);
+ _gridDarkGreen = g_system->getScreenFormat().RGBToColor(0, 85, 0);
+ _lockDarkGreen1 = g_system->getScreenFormat().RGBToColor(0, 68, 0);
+ _lockDarkGreen2 = g_system->getScreenFormat().RGBToColor(0, 65, 0);
+
+ _targetLocked = false;
+ setBounds(kShuttleWindowLeft, kShuttleWindowTop, kShuttleWindowLeft + kShuttleWindowWidth,
+ kShuttleWindowTop + kShuttleWindowHeight);
+ setDisplayOrder(kShuttleHUDOrder);
+}
+
+void ShuttleHUD::initShuttleHUD() {
+ startDisplaying();
+ startIdling();
+}
+
+void ShuttleHUD::cleanUpShuttleHUD() {
+ stopIdling();
+ stopDisplaying();
+}
+
+void ShuttleHUD::showTargetGrid() {
+ show();
+}
+
+void ShuttleHUD::hideTargetGrid() {
+ hide();
+ unlockOnTarget();
+}
+
+void ShuttleHUD::useIdleTime() {
+ if (isVisible()) {
+ Common::Rect r;
+ g_robotShip->getShuttleBounds(r);
+ if (r.left < kTractorLockRight && r.right > kTractorLockLeft && r.top < kTractorLockBottom && r.bottom > kTractorLockTop)
+ lockOnTarget();
+ else
+ unlockOnTarget();
+ }
+}
+
+void ShuttleHUD::lockOnTarget() {
+ if (!_targetLocked) {
+ _targetLocked = true;
+ triggerRedraw();
+ }
+}
+
+void ShuttleHUD::unlockOnTarget() {
+ if (_targetLocked) {
+ _targetLocked = false;
+ triggerRedraw();
+ }
+}
+
+void ShuttleHUD::draw(const Common::Rect &) {
+ Graphics::Surface *screen = ((PegasusEngine *)g_engine)->_gfx->getWorkArea();
+
+ for (int y = 0; y < 35; y++) {
+ Common::Rect r;
+
+ if (y & 1) {
+ if (y == 17) {
+ r = Common::Rect(0, 0, 4, 2);
+ r.moveTo(kHUDTargetGridLeft + 8, y * 6 + kHUDTargetGridTop);
+ screen->fillRect(r, _gridDarkGreen);
+ r.moveTo(kHUDTargetGridLeft + kHUDTargetGridWidth - 12, y * 6 + kHUDTargetGridTop);
+ screen->fillRect(r, _gridDarkGreen);
+
+ r = Common::Rect(0, 0, 6, 2);
+ r.moveTo(kHUDTargetGridLeft + 2, y * 6 + kHUDTargetGridTop);
+ screen->fillRect(r, _lightGreen);
+ r.moveTo(kHUDTargetGridLeft + kHUDTargetGridWidth - 8, y * 6 + kHUDTargetGridTop);
+ screen->fillRect(r, _lightGreen);
+
+ r = Common::Rect(0, 0, 23, 2);
+ r.moveTo(kHUDTargetGridLeft + 12, y * 6 + kHUDTargetGridTop);
+ screen->fillRect(r, _lightGreen);
+ r.moveTo(kHUDTargetGridLeft + kHUDTargetGridWidth - 35, y * 6 + kHUDTargetGridTop);
+ screen->fillRect(r, _lightGreen);
+ } else if (y == 1 || y == 15 || y == 19 || y == 33) {
+ r = Common::Rect(0, 0, 4, 2);
+ r.moveTo(kHUDTargetGridLeft + 2, y * 6 + kHUDTargetGridTop);
+ screen->fillRect(r, _gridDarkGreen);
+ r.moveTo(kHUDTargetGridLeft + kHUDTargetGridWidth - 6, y * 6 + kHUDTargetGridTop);
+ screen->fillRect(r, _gridDarkGreen);
+
+ r = Common::Rect(0, 0, 15, 2);
+ r.moveTo(kHUDTargetGridLeft + 8, y * 6 + kHUDTargetGridTop);
+ screen->fillRect(r, _gridDarkGreen);
+ r.moveTo(kHUDTargetGridLeft + kHUDTargetGridWidth - 23, y * 6 + kHUDTargetGridTop);
+ screen->fillRect(r, _gridDarkGreen);
+ } else {
+ r = Common::Rect(0, 0, 4, 2);
+ r.moveTo(kHUDTargetGridLeft + 2, y * 6 + kHUDTargetGridTop);
+ screen->fillRect(r, _gridDarkGreen);
+ r.moveTo(kHUDTargetGridLeft + kHUDTargetGridWidth - 6, y * 6 + kHUDTargetGridTop);
+ screen->fillRect(r, _gridDarkGreen);
+
+ r = Common::Rect(0, 0, 10, 2);
+ r.moveTo(kHUDTargetGridLeft + 8, y * 6 + kHUDTargetGridTop);
+ screen->fillRect(r, _gridDarkGreen);
+ r.moveTo(kHUDTargetGridLeft + kHUDTargetGridWidth - 18, y * 6 + kHUDTargetGridTop);
+ screen->fillRect(r, _gridDarkGreen);
+ }
+ } else {
+ r = Common::Rect(0, 0, 2, 2);
+ r.moveTo(kHUDTargetGridLeft, y * 6 + kHUDTargetGridTop);
+ screen->fillRect(r, _gridDarkGreen);
+ r.moveTo(kHUDTargetGridLeft + kHUDTargetGridWidth - 2, y * 6 + kHUDTargetGridTop);
+ screen->fillRect(r, _gridDarkGreen);
+
+ r = Common::Rect(0, 0, 4, 2);
+ r.moveTo(kHUDTargetGridLeft + 8, y * 6 + kHUDTargetGridTop);
+ screen->fillRect(r, _gridDarkGreen);
+ r.moveTo(kHUDTargetGridLeft + kHUDTargetGridWidth - 12, y * 6 + kHUDTargetGridTop);
+ screen->fillRect(r, _gridDarkGreen);
+ }
+ }
+
+ drawOneBitImageOr(screen, s_RS232Data, 2, Common::Rect(kHUDRS232Left, kHUDRS232Top,
+ kHUDRS232Left + 29, kHUDRS232Top + 8), _gridDarkGreen);
+
+ if (_targetLocked) {
+ drawHUDLockArrows(0, _lockDarkGreen2);
+ drawHUDLockArrows(12, _lockDarkGreen1);
+ drawHUDLockArrows(24, _lightGreen);
+ drawOneBitImageOr(screen, s_lockData, 4, Common::Rect(kHUDLockLeft, kHUDLockTop + 115,
+ kHUDLockLeft + 52, kHUDLockTop + 115 + 9), _lightGreen);
+ }
+}
+
+void ShuttleHUD::drawOneBitImageOr(Graphics::Surface *screen, const uint16 *data, int pitch, const Common::Rect &bounds, uint32 color) {
+ for (int y = 0; y < bounds.height(); y++) {
+ for (int x = 0; x < bounds.width(); x++) {
+ if ((data[y * pitch + x / 16] & (1 << (15 - (x % 16)))) != 0) {
+ if (screen->format.bytesPerPixel == 2)
+ WRITE_UINT16((byte *)screen->getBasePtr(x + bounds.left, y + bounds.top), color);
+ else
+ WRITE_UINT32((byte *)screen->getBasePtr(x + bounds.left, y + bounds.top), color);
+ }
+ }
+ }
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/mars/shuttlehud.h b/engines/pegasus/neighborhood/mars/shuttlehud.h
new file mode 100644
index 0000000000..f7dbbaeae8
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/shuttlehud.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_MARS_SHUTTLEHUD_H
+#define PEGASUS_NEIGHBORHOOD_MARS_SHUTTLEHUD_H
+
+#include "pegasus/elements.h"
+#include "pegasus/timers.h"
+
+namespace Pegasus {
+
+class ShuttleHUD : public DisplayElement, public Idler {
+public:
+ ShuttleHUD();
+
+ void showTargetGrid();
+ void hideTargetGrid();
+
+ void initShuttleHUD();
+ void cleanUpShuttleHUD();
+
+ bool isTargetLocked() { return _targetLocked; }
+
+ void draw(const Common::Rect &);
+
+protected:
+ void useIdleTime();
+ void lockOnTarget();
+ void unlockOnTarget();
+ void drawOneBitImageOr(Graphics::Surface *, const uint16 *, int, const Common::Rect &, uint32);
+
+ bool _targetLocked;
+ uint32 _lightGreen, _gridDarkGreen, _lockDarkGreen1, _lockDarkGreen2;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/mars/shuttleweapon.cpp b/engines/pegasus/neighborhood/mars/shuttleweapon.cpp
new file mode 100644
index 0000000000..b4c360b280
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/shuttleweapon.cpp
@@ -0,0 +1,129 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/neighborhood/mars/constants.h"
+#include "pegasus/neighborhood/mars/robotship.h"
+#include "pegasus/neighborhood/mars/shuttleweapon.h"
+#include "pegasus/neighborhood/mars/spacejunk.h"
+
+namespace Pegasus {
+
+ShuttleWeapon::ShuttleWeapon() : IdlerAnimation(kNoDisplayElement) {
+ setScale(kShuttleWeaponScale);
+ _weaponDuration = kShuttleWeaponScale * 2;
+ setSegment(0, _weaponDuration);
+ setBounds(kShuttleWindowLeft, kShuttleWindowTop, kShuttleWindowLeft + kShuttleWindowWidth,
+ kShuttleWindowTop + kShuttleWindowHeight);
+ setDisplayOrder(kShuttleWeaponFrontOrder);
+}
+
+void ShuttleWeapon::initShuttleWeapon() {
+ startDisplaying();
+}
+
+void ShuttleWeapon::cleanUpShuttleWeapon() {
+ stop();
+ hide();
+ stopDisplaying();
+}
+
+bool ShuttleWeapon::canFireWeapon() {
+ return !isRunning();
+}
+
+void ShuttleWeapon::fireWeapon(const CoordType hStop, const CoordType vStop) {
+ if (!isRunning()) {
+ stop();
+ setTime(0);
+ show();
+
+ Common::Point pt2D(hStop, vStop);
+ project2DTo3D(pt2D, kShuttleDistance, _weaponTarget);
+ _weaponTime = 0;
+ setDisplayOrder(kShuttleWeaponFrontOrder);
+ start();
+ }
+}
+
+void ShuttleWeapon::updateWeaponPosition() {
+ _weaponTime = (float)_lastTime / _weaponDuration;
+ linearInterp(_weaponOrigin, _weaponTarget, _weaponTime, _weaponLocation);
+
+ if (_weaponTime == 1.0) {
+ stop();
+ hide();
+ } else {
+ triggerRedraw();
+ }
+}
+
+void ShuttleWeapon::timeChanged(const TimeValue) {
+ updateWeaponPosition();
+
+ bool hit = false;
+ Common::Point impactPoint;
+
+ if (g_spaceJunk->isJunkFlying()) {
+ hit = collisionWithJunk(impactPoint);
+ if (hit) {
+ stop();
+ hide();
+ hitJunk(impactPoint);
+ }
+ }
+
+ if (!hit && _weaponTime == 1.0 && collisionWithShuttle(impactPoint))
+ hitShuttle(impactPoint);
+}
+
+bool ShuttleWeapon::collisionWithJunk(Common::Point &impactPoint) {
+ if (getDisplayOrder() == kShuttleWeaponFrontOrder) {
+ Point3D junkPosition;
+ g_spaceJunk->getJunkPosition(junkPosition);
+
+ if (junkPosition.z < _weaponLocation.z) {
+ setDisplayOrder(kShuttleWeaponBackOrder);
+ project3DTo2D(_weaponLocation, impactPoint);
+ return g_spaceJunk->pointInJunk(impactPoint);
+ }
+ }
+
+ return false;
+}
+
+bool ShuttleWeapon::collisionWithShuttle(Common::Point &impactPoint) {
+ project3DTo2D(_weaponLocation, impactPoint);
+ return g_robotShip->pointInShuttle(impactPoint);
+}
+
+void ShuttleWeapon::hitJunk(Common::Point impactPoint) {
+ g_spaceJunk->hitByEnergyBeam(impactPoint);
+}
+
+void ShuttleWeapon::hitShuttle(Common::Point impactPoint) {
+ g_robotShip->hitByEnergyBeam(impactPoint);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/mars/shuttleweapon.h b/engines/pegasus/neighborhood/mars/shuttleweapon.h
new file mode 100644
index 0000000000..38529c8919
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/shuttleweapon.h
@@ -0,0 +1,68 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_MARS_SHUTTLEWEAPON_H
+#define PEGASUS_NEIGHBORHOOD_MARS_SHUTTLEWEAPON_H
+
+#include "pegasus/elements.h"
+#include "pegasus/neighborhood/mars/spacechase3d.h"
+
+namespace Pegasus {
+
+// Can fire multiple times?
+// For now, no...
+// clone2727 adds: And now forever
+
+static const TimeScale kShuttleWeaponScale = kFifteenTicksPerSecond;
+
+class ShuttleWeapon : public IdlerAnimation {
+public:
+ ShuttleWeapon();
+ virtual ~ShuttleWeapon() {}
+
+ virtual void initShuttleWeapon();
+ virtual void cleanUpShuttleWeapon();
+
+ virtual void fireWeapon(const CoordType, const CoordType);
+
+ bool canFireWeapon();
+
+protected:
+ void timeChanged(const TimeValue);
+ virtual void updateWeaponPosition();
+ virtual bool collisionWithJunk(Common::Point &impactPoint);
+ bool collisionWithShuttle(Common::Point &impactPoint);
+ virtual void hitJunk(Common::Point impactPoint);
+ virtual void hitShuttle(Common::Point impactPoint);
+
+ Point3D _weaponOrigin, _weaponTarget;
+ Point3D _weaponLocation;
+ float _weaponTime;
+ TimeValue _weaponDuration;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/mars/spacechase3d.cpp b/engines/pegasus/neighborhood/mars/spacechase3d.cpp
new file mode 100644
index 0000000000..05f8233763
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/spacechase3d.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/neighborhood/mars/spacechase3d.h"
+
+namespace Pegasus {
+
+void project3DTo2D(const Point3D &pt3D, Common::Point &pt2D) {
+ pt2D.x = (int)convertSpaceXToScreenH(pt3D.x, pt3D.z);
+ pt2D.y = (int)convertSpaceYToScreenV(pt3D.y, pt3D.z);
+}
+
+void project2DTo3D(const Common::Point &pt2D, const float screenDistance, Point3D &pt3D) {
+ pt3D.x = convertScreenHToSpaceX(pt2D.x, screenDistance);
+ pt3D.y = convertScreenVToSpaceY(pt2D.y, screenDistance);
+ pt3D.z = screenDistance;
+}
+
+void linearInterp(const Point3D &pt1, const Point3D &pt2, const float t, Point3D &pt3) {
+ pt3.x = pt1.x + (pt2.x - pt1.x) * t;
+ pt3.y = pt1.y + (pt2.y - pt1.y) * t;
+ pt3.z = pt1.z + (pt2.z - pt1.z) * t;
+}
+
+void linearInterp(const Point3D &pt1, const float x2, const float y2, const float z2, const float t, Point3D &pt3) {
+ pt3.x = pt1.x + (x2 - pt1.x) * t;
+ pt3.y = pt1.y + (y2 - pt1.y) * t;
+ pt3.z = pt1.z + (z2 - pt1.z) * t;
+}
+
+void linearInterp(const float x1, const float y1, const float z1, const Point3D &pt2, const float t, Point3D &pt3) {
+ pt3.x = x1 + (pt2.x - x1) * t;
+ pt3.y = y1 + (pt2.y - y1) * t;
+ pt3.z = z1 + (pt2.z - z1) * t;
+}
+
+void linearInterp(const float x1, const float y1, const float z1, const float x2, const float y2, const float z2,
+ const float t, Point3D &pt3) {
+ pt3.x = x1 + (x2 - x1) * t;
+ pt3.y = y1 + (y2 - y1) * t;
+ pt3.z = z1 + (z2 - z1) * t;
+}
+
+void linearInterp(const Common::Point &pt1, const Common::Point &pt2, const float t, Common::Point &pt3) {
+ pt3.x = (int)(pt1.x + (pt2.x - pt1.x) * t);
+ pt3.y = (int)(pt1.y + (pt2.y - pt1.y) * t);
+}
+
+void linearInterp(const Common::Point &pt1, const float h2, const float v2, const float t, Common::Point &pt3) {
+ pt3.x = (int)(pt1.x + (h2 - pt1.x) * t);
+ pt3.y = (int)(pt1.y + (v2 - pt1.y) * t);
+}
+
+void linearInterp(const float h1, const float v1, const Common::Point &pt2, const float t, Common::Point &pt3) {
+ pt3.x = (int)(h1 + (pt2.x - h1) * t);
+ pt3.y = (int)(v1 + (pt2.y - v1) * t);
+}
+
+void linearInterp(const float h1, const float v1, const float h2, const float v2, const float t, Common::Point &pt3) {
+ pt3.x = (int)(h1 + (h2 - h1) * t);
+ pt3.y = (int)(v1 + (v2 - v1) * t);
+}
+
+float linearInterp(const float arg1, const float arg2, const float t) {
+ return arg1 + (arg2 - arg1) * t;
+}
+
+bool isNegative(int a) {
+ return a < 0;
+}
+
+bool isPositive(int a) {
+ return a > 0;
+}
+
+int sign(int a) {
+ return isNegative(a) ? -1 : isPositive(a) ? 1 : 0;
+}
+
+bool sameSign(int a, int b) {
+ return sign(a) == sign(b);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/mars/spacechase3d.h b/engines/pegasus/neighborhood/mars/spacechase3d.h
new file mode 100644
index 0000000000..f6815e69bd
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/spacechase3d.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_MARS_SPACECHASE3D_H
+#define PEGASUS_NEIGHBORHOOD_MARS_SPACECHASE3D_H
+
+#include "pegasus/neighborhood/mars/constants.h"
+
+namespace Pegasus {
+
+// This is approximately right for a field of view of 72 degrees
+// (Should be set to the tangent of FOV).
+//static const float kTangentFOV = 0.76254;
+static const float kTangentFOV = 1.0;
+
+// Define these as macros and they can be used to define constants...
+#define convertSpaceXToScreenH(x, z) \
+ ((x) / (z) * (kScreenWidth / (2 * kTangentFOV)) + kShuttleWindowMidH)
+
+#define convertSpaceYToScreenV(y, z) \
+ (kShuttleWindowMidV - (y) / (z) * (kScreenWidth / (2 * kTangentFOV)))
+
+#define convertScreenHToSpaceX(x, d) \
+ (((2.0 * kTangentFOV) / kScreenWidth) * ((float)(x) - kShuttleWindowMidH) * (d))
+
+#define convertScreenVToSpaceY(y, d) \
+ (((2.0 * kTangentFOV) / kScreenWidth) * ((float)kShuttleWindowMidV - (y)) * (d))
+
+struct Point3D {
+ float x, y, z;
+
+ Point3D() : x(0), y(0), z(0) {}
+ Point3D(float x1, float y1, float z1) : x(x1), y(y1), z(z1) {}
+ bool operator==(const Point3D &p) const { return x == p.x && y == p.y && z == p.z; }
+ bool operator!=(const Point3D &p) const { return x != p.x || y != p.y || z != p.z; }
+
+ void translate(float dx, float dy, float dz) {
+ x += dx;
+ y += dy;
+ z += dz;
+ }
+};
+
+static const int kScreenWidth = kShuttleWindowWidth;
+
+bool isNegative(int a);
+bool isPositive(int a);
+int sign(int a);
+bool sameSign(int a, int b);
+
+void project3DTo2D(const Point3D &pt3D, Common::Point &pt2D);
+void project2DTo3D(const Common::Point &pt2D, const float screenDistance, Point3D &pt3D);
+
+void linearInterp(const Point3D &pt1, const Point3D &pt2, const float t, Point3D &pt3);
+void linearInterp(const Point3D &pt1, const float x2, const float y2, const float z2, const float t, Point3D &pt3);
+void linearInterp(const float x1, const float y1, const float z1, const Point3D &pt2, const float t, Point3D &pt3);
+void linearInterp(const float x1, const float y1, const float z1, const float x2,
+ const float y2, const float z2, const float t, Point3D &pt3);
+
+void linearInterp(const Common::Point &pt1, const Common::Point &pt2, const float t, Common::Point &pt3);
+void linearInterp(const Common::Point &pt1, const float h2, const float v2, const float t, Common::Point &pt3);
+void linearInterp(const float h1, const float v1, const Common::Point &pt2, const float t, Common::Point &pt3);
+void linearInterp(const float h1, const float v1, const float h2, const float v2, const float t, Common::Point &pt3);
+
+float linearInterp(const float arg1, const float arg2, const float t);
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/mars/spacejunk.cpp b/engines/pegasus/neighborhood/mars/spacejunk.cpp
new file mode 100644
index 0000000000..3912e659c2
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/spacejunk.cpp
@@ -0,0 +1,212 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/pegasus.h"
+#include "pegasus/neighborhood/mars/mars.h"
+#include "pegasus/neighborhood/mars/spacejunk.h"
+
+namespace Pegasus {
+
+static const CoordType kMaxBounceSize = 90;
+static const CoordType kBounceTargetHRange = 640 - kMaxBounceSize - 2;
+static const CoordType kBounceTargetVRange = 480 - kMaxBounceSize - 2;
+
+static const float kJunkXTarget = 0;
+static const float kJunkYTarget = 0;
+static const float kJunkZTarget = kJunkMinDistance;
+
+SpaceJunk *g_spaceJunk = 0;
+
+SpaceJunk::SpaceJunk(const DisplayElementID id) : ScalingMovie(id) {
+ _timer.setScale(kJunkTimeScale);
+ _bouncing = false;
+ g_spaceJunk = this;
+}
+
+SpaceJunk::~SpaceJunk() {
+ g_spaceJunk = 0;
+}
+
+void SpaceJunk::launchJunk(int16 whichJunk, CoordType xOrigin, CoordType yOrigin) {
+ _bouncing = false;
+ TimeValue startTime = whichJunk * 16 * 40;
+ TimeValue stopTime = startTime + 16 * 40;
+
+ _launchPoint = Point3D(convertScreenHToSpaceX(xOrigin, kJunkMaxDistance),
+ convertScreenVToSpaceY(yOrigin, kJunkMaxDistance), kJunkMaxDistance);
+ startIdling();
+ stop();
+ setFlags(0);
+ setSegment(startTime, stopTime);
+ setFlags(kLoopTimeBase);
+ setTime(startTime);
+ start();
+ show();
+ _timer.stop();
+ _timer.setSegment(0, kJunkTravelTime);
+ _timer.setTime(0);
+
+ // Force it to set up correctly from the get-go
+ useIdleTime();
+
+ _timer.start();
+}
+
+void SpaceJunk::setCenter(const CoordType centerX, const CoordType centerY) {
+ _center.x = centerX;
+ _center.y = centerY;
+
+ Common::Rect r;
+ getBounds(r);
+ r.moveTo(CLIP<int>(centerX - (r.width() >> 1), 0, 640 - r.width()), CLIP<int>(centerY - (r.height() >> 1), 0, 480 - r.height()));
+ setBounds(r);
+}
+
+void SpaceJunk::setScaleSize(const CoordType size) {
+ Common::Rect r;
+ r.left = _center.x - (size >> 1);
+ r.top = _center.y - (size >> 1);
+ r.right = r.left + size;
+ r.bottom = r.top + size;
+ setBounds(r);
+}
+
+void SpaceJunk::useIdleTime() {
+ if (_bouncing) {
+ TimeValue time = _timer.getTime();
+ Common::Point pt;
+ pt.x = linearInterp(0, _bounceTime, time, _bounceStart.x, _bounceStop.x);
+ pt.y = linearInterp(0, _bounceTime, time, _bounceStart.y, _bounceStop.y);
+ CoordType size = linearInterp(0, _bounceTime, time, _bounceSizeStart, _bounceSizeStop);
+ setCenter(pt.x, pt.y);
+ setScaleSize(size);
+
+ if (time == _bounceTime) {
+ stop();
+ stopIdling();
+ hide();
+ ((Mars *)g_neighborhood)->setUpNextDropTime();
+ }
+ } else {
+ float t = (float)_timer.getTime() / kJunkTravelTime;
+ linearInterp(_launchPoint, kJunkXTarget, kJunkYTarget, kJunkZTarget, t, _junkPosition);
+
+ Common::Point pt2D;
+ project3DTo2D(_junkPosition, pt2D);
+ setCenter(pt2D.x, pt2D.y);
+ setScaleSize((int)(convertSpaceYToScreenV(_junkPosition.y - kJunkSize / 2, _junkPosition.z) -
+ convertSpaceYToScreenV(_junkPosition.y + kJunkSize / 2, _junkPosition.z)));
+
+ if (t == 1.0) {
+ rebound(kCollisionReboundTime);
+ ((Mars *)g_neighborhood)->hitByJunk();
+ }
+ }
+}
+
+bool SpaceJunk::pointInJunk(const Common::Point &pt) {
+ Common::Rect r;
+ getBounds(r);
+
+ int dx = r.width() / 4;
+ int dy = r.height() / 4;
+
+ r.left += dx;
+ r.right -= dx;
+ r.top += dy;
+ r.top -= dy;
+
+ return r.contains(pt);
+}
+
+void SpaceJunk::rebound(const TimeValue reboundTime) {
+ Common::Rect bounds;
+ getBounds(bounds);
+
+ _bounceStart.x = (bounds.left + bounds.right) >> 1;
+ _bounceStart.y = (bounds.top + bounds.bottom) >> 1;
+
+ PegasusEngine *vm = (PegasusEngine *)g_engine;
+
+ switch (vm->getRandomNumber(3)) {
+ case 0:
+ _bounceStop.x = kMaxBounceSize / 2 + 1 + vm->getRandomNumber(kBounceTargetHRange - 1);
+ _bounceStop.y = kMaxBounceSize / 2 + 1;
+ break;
+ case 1:
+ _bounceStop.x = kMaxBounceSize / 2 + 1 + vm->getRandomNumber(kBounceTargetHRange - 1);
+ _bounceStop.y = 480 - kMaxBounceSize / 2 + 1;
+ break;
+ case 2:
+ _bounceStop.x = kMaxBounceSize / 2 + 1;
+ _bounceStop.y = kMaxBounceSize / 2 + 1 + vm->getRandomNumber(kBounceTargetVRange - 1);
+ break;
+ case 3:
+ _bounceStop.x = 640 - kMaxBounceSize / 2 + 1;
+ _bounceStop.y = kMaxBounceSize / 2 + 1 + vm->getRandomNumber(kBounceTargetVRange - 1);
+ break;
+ }
+
+ _bounceSizeStart = bounds.width();
+ _bounceSizeStop = MIN(_bounceSizeStart, kMaxBounceSize);
+
+ _timer.stop();
+ _timer.setSegment(0, reboundTime);
+ _bounceTime = reboundTime;
+ _timer.setTime(0);
+ _timer.start();
+
+ _bouncing = true;
+}
+
+void SpaceJunk::hitByEnergyBeam(Common::Point) {
+ rebound(kWeaponReboundTime);
+ setGlowing(true);
+ ((PegasusEngine *)g_engine)->delayShell(1, 3);
+ setGlowing(false);
+}
+
+void SpaceJunk::hitByGravitonCannon(Common::Point impactPoint) {
+ stop();
+ stopIdling();
+ hide();
+
+ Common::Rect r;
+ getBounds(r);
+ r = Common::Rect::center(impactPoint.x, impactPoint.y, r.width(), r.height());
+
+ ((Mars *)g_neighborhood)->showBigExplosion(r, kShuttleJunkOrder);
+ ((Mars *)g_neighborhood)->setUpNextDropTime();
+}
+
+void SpaceJunk::getJunkPosition(Point3D &position) {
+ position = _junkPosition;
+}
+
+bool SpaceJunk::isJunkFlying() {
+ return isIdling();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/mars/spacejunk.h b/engines/pegasus/neighborhood/mars/spacejunk.h
new file mode 100644
index 0000000000..2ec9192513
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/spacejunk.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_MARS_SPACEJUNK_H
+#define PEGASUS_NEIGHBORHOOD_MARS_SPACEJUNK_H
+
+#include "pegasus/movie.h"
+#include "pegasus/neighborhood/mars/constants.h"
+#include "pegasus/neighborhood/mars/spacechase3d.h"
+
+namespace Pegasus {
+
+static const CoordType kJunkMaxScreenSize = 250;
+
+static const float kJunkSize = convertScreenVToSpaceY(kShuttleWindowMidV - kJunkMaxScreenSize / 2, kJunkMinDistance) -
+ convertScreenVToSpaceY(kShuttleWindowMidV + kJunkMaxScreenSize / 2, kJunkMinDistance);
+
+class SpaceJunk : public ScalingMovie, public Idler {
+public:
+ SpaceJunk(const DisplayElementID);
+ virtual ~SpaceJunk();
+
+ void setCenter(const CoordType, const CoordType);
+ void setScaleSize(const CoordType);
+
+ void useIdleTime();
+
+ void launchJunk(int16, CoordType, CoordType);
+
+ void getJunkPosition(Point3D &);
+ bool isJunkFlying();
+
+ bool pointInJunk(const Common::Point &);
+
+ void hitByEnergyBeam(Common::Point impactPoint);
+ void hitByGravitonCannon(Common::Point impactPoint);
+
+ bool junkFlying() { return _timer.isRunning(); }
+
+protected:
+ void rebound(const TimeValue);
+
+ TimeBase _timer;
+ Point3D _launchPoint, _junkPosition;
+ Common::Point _center;
+ bool _bouncing;
+ Common::Point _bounceStart, _bounceStop;
+ CoordType _bounceSizeStart, _bounceSizeStop;
+ TimeValue _bounceTime;
+};
+
+extern SpaceJunk *g_spaceJunk;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/mars/tractorbeam.cpp b/engines/pegasus/neighborhood/mars/tractorbeam.cpp
new file mode 100644
index 0000000000..d3f9c94328
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/tractorbeam.cpp
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/pegasus.h"
+#include "pegasus/neighborhood/mars/constants.h"
+#include "pegasus/neighborhood/mars/tractorbeam.h"
+
+namespace Pegasus {
+
+TractorBeam::TractorBeam() : DisplayElement(kNoDisplayElement) {
+ setBounds(kShuttleTractorLeft, kShuttleTractorTop, kShuttleTractorLeft + kShuttleTractorWidth,
+ kShuttleTractorTop + kShuttleTractorHeight);
+ setDisplayOrder(kShuttleTractorBeamOrder);
+
+}
+
+static const int kHalfWidth = kShuttleTractorWidth >> 1;
+static const int kHalfHeight = kShuttleTractorHeight >> 1;
+
+static const int kW3Vert = kHalfHeight * kHalfHeight * kHalfHeight;
+static const int kW3Div2Vert = kW3Vert >> 1;
+
+static const int kW3Horiz = kHalfWidth * kHalfWidth * kHalfWidth;
+static const int kW3Div2Horiz = kW3Horiz >> 1;
+
+static const int kMaxLevel = 50;
+
+static const int kAVert = -2 * kMaxLevel;
+static const int kBVert = 3 * kMaxLevel * kHalfHeight;
+
+#define READ_PIXEL(ptr) \
+ if (screen->format.bytesPerPixel == 2) \
+ color = READ_UINT16(ptr); \
+ else \
+ color = READ_UINT32(ptr); \
+ screen->format.colorToRGB(color, r, g, b)
+
+#define WRITE_PIXEL(ptr) \
+ color = screen->format.RGBToColor(r, g, b); \
+ if (screen->format.bytesPerPixel == 2) \
+ WRITE_UINT16(ptr, color); \
+ else \
+ WRITE_UINT32(ptr, color)
+
+#define DO_BLEND(ptr) \
+ READ_PIXEL(ptr); \
+ g += (((0xff - g) * blendHoriz) >> 8); \
+ b += (((0xff - b) * blendHoriz) >> 8); \
+ WRITE_PIXEL(ptr)
+
+void TractorBeam::draw(const Common::Rect &) {
+ Graphics::Surface *screen = ((PegasusEngine *)g_engine)->_gfx->getWorkArea();
+
+ // Set up vertical DDA.
+ int blendVert = 0;
+ int dVert = 0;
+ int d1Vert = kAVert + kBVert;
+ int d2Vert = 6 * kAVert + 2 * kBVert;
+ int d3Vert = 6 * kAVert;
+
+ byte *rowPtrTop = (byte *)screen->getBasePtr(_bounds.left, _bounds.top);
+ byte *rowPtrBottom = (byte *)screen->getBasePtr(_bounds.left, _bounds.top + ((kHalfHeight << 1) - 1));
+
+ for (int y = kHalfHeight; y > 0; y--) {
+ // Set up horizontal DDA
+ int A = -2 * blendVert;
+ int B = 3 * blendVert * kHalfWidth;
+ int blendHoriz = 0;
+ int dHoriz = 0;
+ int d1Horiz = A + B;
+ int d2Horiz = 6 * A + 2 * B;
+ int d3Horiz = 6 * A;
+
+ byte *pTopLeft = rowPtrTop;
+ byte *pTopRight = rowPtrTop + (kHalfWidth * 2 - 1) * screen->format.bytesPerPixel;
+ byte *pBottomLeft = rowPtrBottom;
+ byte *pBottomRight = rowPtrBottom + (kHalfWidth * 2 - 1) * screen->format.bytesPerPixel;
+
+ for (int x = kHalfWidth; x > 0; x--) {
+ byte r, g, b;
+ uint32 color;
+
+ DO_BLEND(pTopLeft);
+ DO_BLEND(pTopRight);
+ DO_BLEND(pBottomLeft);
+ DO_BLEND(pBottomRight);
+
+ pTopLeft += screen->format.bytesPerPixel;
+ pBottomLeft += screen->format.bytesPerPixel;
+ pTopRight -= screen->format.bytesPerPixel;
+ pBottomRight -= screen->format.bytesPerPixel;
+
+ while (dHoriz > kW3Div2Horiz) {
+ blendHoriz++;
+ dHoriz -= kW3Horiz;
+ }
+
+ dHoriz += d1Horiz;
+ d1Horiz += d2Horiz;
+ d2Horiz += d3Horiz;
+ }
+
+ rowPtrTop += screen->pitch;
+ rowPtrBottom -= screen->pitch;
+
+ while (dVert > kW3Div2Vert) {
+ blendVert++;
+ dVert -= kW3Vert;
+ }
+
+ dVert += d1Vert;
+ d1Vert += d2Vert;
+ d2Vert += d3Vert;
+ }
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/mars/tractorbeam.h b/engines/pegasus/neighborhood/mars/tractorbeam.h
new file mode 100644
index 0000000000..cd87992d11
--- /dev/null
+++ b/engines/pegasus/neighborhood/mars/tractorbeam.h
@@ -0,0 +1,43 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_MARS_TRACTORBEAM_H
+#define PEGASUS_NEIGHBORHOOD_MARS_TRACTORBEAM_H
+
+#include "pegasus/elements.h"
+
+namespace Pegasus {
+
+class TractorBeam : public DisplayElement {
+public:
+ TractorBeam();
+ virtual ~TractorBeam() {}
+
+ void draw(const Common::Rect &);
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/neighborhood.cpp b/engines/pegasus/neighborhood/neighborhood.cpp
new file mode 100644
index 0000000000..07be62c957
--- /dev/null
+++ b/engines/pegasus/neighborhood/neighborhood.cpp
@@ -0,0 +1,1774 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/compass.h"
+#include "pegasus/cursor.h"
+#include "pegasus/energymonitor.h"
+#include "pegasus/gamestate.h"
+#include "pegasus/graphics.h"
+#include "pegasus/input.h"
+#include "pegasus/interaction.h"
+#include "pegasus/interface.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/biochips/mapchip.h"
+#include "pegasus/neighborhood/neighborhood.h"
+#include "pegasus/neighborhood/tsa/fulltsa.h"
+#include "pegasus/neighborhood/tsa/tinytsa.h"
+
+namespace Pegasus {
+
+StriderCallBack::StriderCallBack(Neighborhood *neighborhood) {
+ _neighborhood = neighborhood;
+}
+
+void StriderCallBack::callBack() {
+ _neighborhood->checkStriding();
+}
+
+static const TimeValue kStridingSlop = 39;
+
+Neighborhood *g_neighborhood = 0;
+
+Neighborhood::Neighborhood(InputHandler *nextHandler, PegasusEngine *vm, const Common::String &resName, NeighborhoodID id)
+ : InputHandler(nextHandler), IDObject(id), _vm(vm), _resName(resName), _navMovie(kNavMovieID), _stridingCallBack(this),
+ _neighborhoodNotification(kNeighborhoodNotificationID, (NotificationManager *)vm), _pushIn(kNoDisplayElement),
+ _turnPush(kTurnPushID), _croppedMovie(kCroppedMovieID) {
+ GameState.setOpenDoorLocation(kNoRoomID, kNoDirection);
+ _currentAlternate = 0;
+ _currentActivation = kActivateHotSpotAlways;
+ _interruptionFilter = kFilterAllInput;
+ allowInput(true);
+ resetLastExtra();
+ g_neighborhood = this;
+ _currentInteraction = 0;
+ _doneWithInteraction = false;
+ _croppedMovie.setDisplayOrder(kCroppedMovieLayer);
+}
+
+Neighborhood::~Neighborhood() {
+ for (HotspotIterator it = _neighborhoodHotspots.begin(); it != _neighborhoodHotspots.end(); it++)
+ _vm->getAllHotspots().remove(*it);
+
+ _neighborhoodHotspots.deleteHotspots();
+ g_neighborhood = 0;
+
+ loadLoopSound1("");
+ loadLoopSound2("");
+ newInteraction(kNoInteractionID);
+
+ if (g_AIArea)
+ g_AIArea->removeAllRules();
+}
+
+void Neighborhood::init() {
+ _neighborhoodNotification.notifyMe(this, kNeighborhoodFlags, kNeighborhoodFlags);
+ _navMovieCallBack.setNotification(&_neighborhoodNotification);
+ _turnPushCallBack.setNotification(&_neighborhoodNotification);
+ _delayCallBack.setNotification(&_neighborhoodNotification);
+ _spotSoundCallBack.setNotification(&_neighborhoodNotification);
+
+ debug(0, "Loading '%s' neighborhood resources", _resName.c_str());
+
+ Common::SeekableReadStream *stream = _vm->_resFork->getResource(_doorTable.getResTag(), _resName);
+ if (!stream)
+ error("Failed to load doors");
+ _doorTable.loadFromStream(stream);
+ delete stream;
+
+ stream = _vm->_resFork->getResource(_exitTable.getResTag(), _resName);
+ if (!stream)
+ error("Failed to load exits");
+ _exitTable.loadFromStream(stream);
+ delete stream;
+
+ stream = _vm->_resFork->getResource(_extraTable.getResTag(), _resName);
+ if (!stream)
+ error("Failed to load extras");
+ _extraTable.loadFromStream(stream);
+ delete stream;
+
+ stream = _vm->_resFork->getResource(_hotspotInfoTable.getResTag(), _resName);
+ if (!stream)
+ error("Failed to load hotspot info");
+ _hotspotInfoTable.loadFromStream(stream);
+ delete stream;
+
+ stream = _vm->_resFork->getResource(_spotTable.getResTag(), _resName);
+ if (!stream)
+ error("Failed to load spots");
+ _spotTable.loadFromStream(stream);
+ delete stream;
+
+ stream = _vm->_resFork->getResource(_turnTable.getResTag(), _resName);
+ if (!stream)
+ error("Failed to load turns");
+ _turnTable.loadFromStream(stream);
+ delete stream;
+
+ stream = _vm->_resFork->getResource(_viewTable.getResTag(), _resName);
+ if (!stream)
+ error("Failed to load views");
+ _viewTable.loadFromStream(stream);
+ delete stream;
+
+ stream = _vm->_resFork->getResource(_zoomTable.getResTag(), _resName);
+ if (!stream)
+ error("Failed to load zooms");
+ _zoomTable.loadFromStream(stream);
+ delete stream;
+
+ createNeighborhoodSpots();
+
+ _navMovie.initFromMovieFile(getNavMovieName());
+ _navMovie.setVolume(_vm->getSoundFXLevel());
+
+ Common::String soundSpotsName = getSoundSpotsName();
+ if (soundSpotsName.empty()) {
+ _spotSounds.disposeSound();
+ } else {
+ _spotSounds.initFromQuickTime(getSoundSpotsName());
+ _spotSounds.setVolume(_vm->getSoundFXLevel());
+ }
+
+ _navMovie.setDisplayOrder(kNavMovieOrder);
+ _navMovie.startDisplaying();
+
+ Common::Rect bounds;
+ _navMovie.getBounds(bounds);
+ _pushIn.allocateSurface(bounds);
+
+ _turnPush.setInAndOutElements(&_pushIn, &_navMovie);
+ _turnPush.setDisplayOrder(kTurnPushOrder);
+ _turnPush.startDisplaying();
+ _navMovieCallBack.initCallBack(&_navMovie, kCallBackAtExtremes);
+ _stridingCallBack.initCallBack(&_navMovie, kCallBackAtTime);
+ _turnPushCallBack.initCallBack(&_turnPush, kCallBackAtExtremes);
+ _delayCallBack.initCallBack(&_delayTimer, kCallBackAtExtremes);
+ _spotSoundCallBack.initCallBack(&_spotSounds, kCallBackAtExtremes);
+
+ setUpAIRules();
+
+ if (g_compass)
+ g_compass->setFaderValue(getStaticCompassAngle(GameState.getCurrentRoom(), GameState.getCurrentDirection()));
+
+ _soundLoop1.attachFader(&_loop1Fader);
+ _soundLoop2.attachFader(&_loop2Fader);
+ startIdling();
+}
+
+void Neighborhood::start() {
+ GameState.setCurrentRoom(GameState.getLastRoom());
+ GameState.setCurrentDirection(GameState.getLastDirection());
+ arriveAt(GameState.getNextRoom(), GameState.getNextDirection());
+}
+
+void Neighborhood::receiveNotification(Notification *, const NotificationFlags flags) {
+ if ((flags & (kNeighborhoodMovieCompletedFlag | kTurnCompletedFlag)) != 0 && g_AIArea)
+ g_AIArea->unlockAI();
+ if (flags & kMoveForwardCompletedFlag)
+ arriveAt(GameState.getNextRoom(), GameState.getNextDirection());
+ if (flags & kTurnCompletedFlag)
+ turnTo(GameState.getNextDirection());
+ if (flags & kSpotCompletedFlag)
+ spotCompleted();
+ if (flags & kDoorOpenCompletedFlag)
+ doorOpened();
+ if (flags & kActionRequestCompletedFlag)
+ popActionQueue();
+ if (flags & kDeathExtraCompletedFlag)
+ die(_extraDeathReason);
+}
+
+void Neighborhood::arriveAt(const RoomID room, const DirectionConstant direction) {
+ if (g_map)
+ g_map->moveToMapLocation(GameState.getCurrentNeighborhood(), room, direction);
+
+ GameState.setCurrentNeighborhood(getObjectID());
+
+ _currentActivation = kActivateHotSpotAlways;
+ _interruptionFilter = kFilterAllInput;
+
+ if (room != GameState.getCurrentRoom() || direction != GameState.getCurrentDirection()) {
+ GameState.setCurrentRoom(room);
+ GameState.setCurrentDirection(direction);
+ loadAmbientLoops();
+ activateCurrentView(room, direction, kSpotOnArrivalMask);
+ } else {
+ loadAmbientLoops();
+ showViewFrame(getViewTime(GameState.getCurrentRoom(), GameState.getCurrentDirection()));
+ }
+
+ if (GameState.getOpenDoorRoom() != kNoRoomID) {
+ // Arriving always closes a door.
+ loadAmbientLoops();
+ closeDoorOffScreen(GameState.getOpenDoorRoom(), GameState.getOpenDoorDirection());
+ GameState.setOpenDoorLocation(kNoRoomID, kNoDirection);
+ }
+
+ if (g_compass)
+ g_compass->setFaderValue(getStaticCompassAngle(GameState.getCurrentRoom(), GameState.getCurrentDirection()));
+
+ if (g_AIArea)
+ g_AIArea->checkMiddleArea();
+
+ checkContinuePoint(room, direction);
+}
+
+// These functions can be overridden to tweak the exact frames used.
+
+void Neighborhood::getExitEntry(const RoomID room, const DirectionConstant direction, ExitTable::Entry &entry) {
+ entry = _exitTable.findEntry(room, direction, _currentAlternate);
+
+ if (entry.isEmpty())
+ entry = _exitTable.findEntry(room, direction, kNoAlternateID);
+}
+
+TimeValue Neighborhood::getViewTime(const RoomID room, const DirectionConstant direction) {
+ if (GameState.getOpenDoorRoom() == room && GameState.getOpenDoorDirection() == direction) {
+ // If we get here, the door entry for this location must exist.
+ DoorTable::Entry doorEntry = _doorTable.findEntry(room, direction, _currentAlternate);
+
+ if (doorEntry.isEmpty())
+ doorEntry = _doorTable.findEntry(room, direction, kNoAlternateID);
+
+ return doorEntry.movieEnd - 1;
+ }
+
+ ViewTable::Entry viewEntry = _viewTable.findEntry(room, direction, _currentAlternate);
+
+ if (viewEntry.isEmpty())
+ viewEntry = _viewTable.findEntry(room, direction, kNoAlternateID);
+
+ return viewEntry.time;
+}
+
+void Neighborhood::getDoorEntry(const RoomID room, const DirectionConstant direction, DoorTable::Entry &doorEntry) {
+ doorEntry = _doorTable.findEntry(room, direction, _currentAlternate);
+
+ if (doorEntry.isEmpty())
+ doorEntry = _doorTable.findEntry(room, direction, kNoAlternateID);
+}
+
+DirectionConstant Neighborhood::getTurnEntry(const RoomID room, const DirectionConstant direction, const TurnDirection turnDirection) {
+ TurnTable::Entry turnEntry = _turnTable.findEntry(room, direction, turnDirection, _currentAlternate);
+
+ if (turnEntry.isEmpty())
+ turnEntry = _turnTable.findEntry(room, direction, turnDirection, kNoAlternateID);
+
+ return turnEntry.endDirection;
+}
+
+void Neighborhood::findSpotEntry(const RoomID room, const DirectionConstant direction, SpotFlags flags, SpotTable::Entry &spotEntry) {
+ spotEntry = _spotTable.findEntry(room, direction, flags, _currentAlternate);
+
+ if (spotEntry.isEmpty())
+ spotEntry = _spotTable.findEntry(room, direction, flags, kNoAlternateID);
+}
+
+void Neighborhood::getZoomEntry(const HotSpotID id, ZoomTable::Entry &zoomEntry) {
+ zoomEntry = _zoomTable.findEntry(id);
+}
+
+void Neighborhood::getHotspotEntry(const HotSpotID id, HotspotInfoTable::Entry &hotspotEntry) {
+ hotspotEntry = _hotspotInfoTable.findEntry(id);
+}
+
+void Neighborhood::getExtraEntry(const uint32 id, ExtraTable::Entry &extraEntry) {
+ extraEntry = _extraTable.findEntry(id);
+}
+
+/////////////////////////////////////////////
+//
+// "Can" functions: Called to see whether or not a user is allowed to do something
+
+CanMoveForwardReason Neighborhood::canMoveForward(ExitTable::Entry &entry) {
+ DoorTable::Entry door;
+
+ getExitEntry(GameState.getCurrentRoom(), GameState.getCurrentDirection(), entry);
+ getDoorEntry(GameState.getCurrentRoom(), GameState.getCurrentDirection(), door);
+
+ // Fixed this so that doors that don't lead anywhere can be opened, but not walked
+ // through.
+ if (door.flags & kDoorPresentMask) {
+ if (GameState.isCurrentDoorOpen()) {
+ if (entry.exitRoom == kNoRoomID)
+ return kCantMoveBlocked;
+ else
+ return kCanMoveForward;
+ } else if (door.flags & kDoorLockedMask) {
+ return kCantMoveDoorLocked;
+ } else {
+ return kCantMoveDoorClosed;
+ }
+ } else if (entry.exitRoom == kNoRoomID) {
+ return kCantMoveBlocked;
+ }
+
+ return kCanMoveForward;
+}
+
+CanTurnReason Neighborhood::canTurn(TurnDirection turnDirection, DirectionConstant &nextDir) {
+ nextDir = getTurnEntry(GameState.getCurrentRoom(), GameState.getCurrentDirection(), turnDirection);
+
+ if (nextDir == kNoDirection)
+ return kCantTurnNoTurn;
+
+ return kCanTurn;
+}
+
+CanOpenDoorReason Neighborhood::canOpenDoor(DoorTable::Entry &entry) {
+ getDoorEntry(GameState.getCurrentRoom(), GameState.getCurrentDirection(), entry);
+
+ if (entry.flags & kDoorPresentMask) {
+ if (GameState.isCurrentDoorOpen())
+ return kCantOpenAlreadyOpen;
+
+ if (entry.flags & kDoorLockedMask)
+ return kCantOpenLocked;
+
+ return kCanOpenDoor;
+ }
+
+ return kCantOpenNoDoor;
+}
+
+void Neighborhood::createNeighborhoodSpots() {
+ Common::SeekableReadStream *hotspotList = _vm->_resFork->getResource(MKTAG('H', 'S', 'L', 's'), _resName);
+ if (!hotspotList)
+ error("Could not load neighborhood hotspots");
+
+ uint32 hotspotCount = hotspotList->readUint32BE();
+
+ while (hotspotCount--) {
+ uint16 id = hotspotList->readUint16BE();
+ uint32 flags = hotspotList->readUint32BE();
+ uint32 rgnSize = hotspotList->readUint32BE();
+
+ int32 startPos = hotspotList->pos();
+
+ debug(0, "Hotspot %d:", id);
+ Region region(hotspotList);
+
+ hotspotList->seek(startPos + rgnSize);
+
+ Hotspot *hotspot = new Hotspot(id);
+ hotspot->setHotspotFlags(flags);
+ hotspot->setArea(region);
+
+ _vm->getAllHotspots().push_back(hotspot);
+ _neighborhoodHotspots.push_back(hotspot);
+ }
+
+ delete hotspotList;
+}
+
+void Neighborhood::popActionQueue() {
+ if (!_actionQueue.empty()) {
+ QueueRequest topRequest = _actionQueue.pop();
+
+ switch (topRequest.requestType) {
+ case kNavExtraRequest:
+ _navMovie.stop();
+ break;
+ case kSpotSoundRequest:
+ _spotSounds.stopSound();
+ break;
+ case kDelayRequest:
+ _delayTimer.stop();
+ break;
+ }
+
+ serviceActionQueue();
+ }
+}
+
+void Neighborhood::serviceActionQueue() {
+ if (!_actionQueue.empty()) {
+ QueueRequest &topRequest = _actionQueue.front();
+
+ if (!topRequest.playing) {
+ topRequest.playing = true;
+ switch (topRequest.requestType) {
+ case kNavExtraRequest:
+ startExtraSequence(topRequest.extra, topRequest.flags, topRequest.interruptionFilter);
+ break;
+ case kSpotSoundRequest:
+ _spotSounds.stopSound();
+ _spotSounds.playSoundSegment(topRequest.start, topRequest.stop);
+ _interruptionFilter = topRequest.interruptionFilter;
+ _spotSoundCallBack.setCallBackFlag(topRequest.flags);
+ _spotSoundCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ break;
+ case kDelayRequest:
+ _delayTimer.stop();
+ _delayCallBack.setCallBackFlag(topRequest.flags);
+ _delayTimer.setSegment(0, topRequest.start, topRequest.stop);
+ _delayTimer.setTime(0);
+ _delayCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ _interruptionFilter = topRequest.interruptionFilter;
+ _delayTimer.start();
+ break;
+ }
+ }
+ } else {
+ _interruptionFilter = kFilterAllInput;
+ }
+}
+
+void Neighborhood::requestAction(const QueueRequestType requestType, const ExtraID extra, const TimeValue in, const TimeValue out,
+ const InputBits interruptionFilter, const NotificationFlags flags) {
+
+ QueueRequest request;
+
+ request.requestType = requestType;
+ request.extra = extra;
+ request.start = in;
+ request.stop = out;
+ request.interruptionFilter = interruptionFilter;
+ request.playing = false;
+ request.flags = flags | kActionRequestCompletedFlag;
+ request.notification = &_neighborhoodNotification;
+ _actionQueue.push(request);
+ if (_actionQueue.size() == 1)
+ serviceActionQueue();
+}
+
+void Neighborhood::requestExtraSequence(const ExtraID whichExtra, const NotificationFlags flags, const InputBits interruptionFilter) {
+ requestAction(kNavExtraRequest, whichExtra, 0, 0, interruptionFilter, flags);
+}
+
+void Neighborhood::requestSpotSound(const TimeValue in, const TimeValue out, const InputBits interruptionFilter, const NotificationFlags flags) {
+ requestAction(kSpotSoundRequest, 0xFFFFFFFF, in, out, interruptionFilter, flags);
+}
+
+void Neighborhood::playSpotSoundSync(const TimeValue in, const TimeValue out) {
+ // Let the action queue play out first...
+ while (!actionQueueEmpty()) {
+ _vm->checkCallBacks();
+ _vm->refreshDisplay();
+ _vm->checkNotifications();
+ _vm->_system->delayMillis(10);
+ }
+
+ _spotSounds.stopSound();
+ _spotSounds.playSoundSegment(in, out);
+
+ while (_spotSounds.isPlaying()) {
+ _vm->checkCallBacks();
+ _vm->refreshDisplay();
+ _vm->_system->delayMillis(10);
+ }
+}
+
+void Neighborhood::requestDelay(const TimeValue delayDuration, const TimeScale delayScale, const InputBits interruptionFilter, const NotificationFlags flags) {
+ requestAction(kDelayRequest, 0xFFFFFFFF, delayDuration, delayScale, interruptionFilter, flags);
+}
+
+bool operator==(const QueueRequest &arg1, const QueueRequest &arg2) {
+ return arg1.requestType == arg2.requestType && arg1.extra == arg2.extra &&
+ arg1.start == arg2.start && arg1.stop == arg2.stop;
+}
+
+bool operator!=(const QueueRequest &arg1, const QueueRequest &arg2) {
+ return !operator==(arg1, arg2);
+}
+
+Common::String Neighborhood::getBriefingMovie() {
+ if (_currentInteraction)
+ return _currentInteraction->getBriefingMovie();
+
+ return Common::String();
+}
+
+Common::String Neighborhood::getEnvScanMovie() {
+ if (_currentInteraction)
+ return _currentInteraction->getEnvScanMovie();
+
+ return Common::String();
+}
+
+uint Neighborhood::getNumHints() {
+ if (_currentInteraction)
+ return _currentInteraction->getNumHints();
+
+ return 0;
+}
+
+Common::String Neighborhood::getHintMovie(uint hintNum) {
+ if (_currentInteraction)
+ return _currentInteraction->getHintMovie(hintNum);
+
+ return Common::String();
+}
+
+bool Neighborhood::canSolve() {
+ if (_currentInteraction)
+ return _currentInteraction->canSolve();
+
+ return false;
+}
+
+void Neighborhood::doSolve() {
+ if (_currentInteraction)
+ _currentInteraction->doSolve();
+}
+
+bool Neighborhood::okayToJump() {
+ return !_vm->playerHasItemID(kGasCanister) && !_vm->playerHasItemID(kMachineGun);
+}
+
+AirQuality Neighborhood::getAirQuality(const RoomID) {
+ return kAirQualityGood;
+}
+
+void Neighborhood::checkStriding() {
+ if (stillMoveForward()) {
+ ExitTable::Entry nextExit;
+ getExitEntry(GameState.getNextRoom(), GameState.getNextDirection(), nextExit);
+ keepStriding(nextExit);
+ } else {
+ stopStriding();
+ }
+}
+
+bool Neighborhood::stillMoveForward() {
+ Input input;
+
+ InputHandler::readInputDevice(input);
+ return input.upButtonAnyDown();
+}
+
+void Neighborhood::keepStriding(ExitTable::Entry &nextExitEntry) {
+ FaderMoveSpec compassMove;
+
+ if (g_map)
+ g_map->moveToMapLocation(GameState.getCurrentNeighborhood(), GameState.getNextRoom(), GameState.getNextDirection());
+
+ if (g_compass)
+ getExitCompassMove(nextExitEntry, compassMove);
+
+ GameState.setCurrentRoom(GameState.getNextRoom());
+ GameState.setCurrentDirection(GameState.getNextDirection());
+ GameState.setNextRoom(nextExitEntry.exitRoom);
+ GameState.setNextDirection(nextExitEntry.exitDirection);
+
+ if (nextExitEntry.movieEnd == nextExitEntry.exitEnd)
+ scheduleNavCallBack(kNeighborhoodMovieCompletedFlag | kMoveForwardCompletedFlag);
+ else
+ scheduleStridingCallBack(nextExitEntry.movieEnd - kStridingSlop, kStrideCompletedFlag);
+
+ if (g_compass)
+ g_compass->startFader(compassMove);
+}
+
+void Neighborhood::stopStriding() {
+ _navMovie.stop();
+ _neighborhoodNotification.setNotificationFlags(kNeighborhoodMovieCompletedFlag |
+ kMoveForwardCompletedFlag, kNeighborhoodMovieCompletedFlag | kMoveForwardCompletedFlag);
+}
+
+// Compass support
+int16 Neighborhood::getStaticCompassAngle(const RoomID, const DirectionConstant dir) {
+ // North, south, east, west
+ static const int16 compassAngles[] = { 0, 180, 90, 270 };
+ return compassAngles[dir];
+}
+
+void Neighborhood::getExitCompassMove(const ExitTable::Entry &exitEntry, FaderMoveSpec &compassMove) {
+ int32 startAngle = getStaticCompassAngle(exitEntry.room, exitEntry.direction);
+ int32 stopAngle = getStaticCompassAngle(exitEntry.exitRoom, exitEntry.exitDirection);
+
+ if (startAngle > stopAngle) {
+ if (stopAngle + 180 < startAngle)
+ stopAngle += 360;
+ } else {
+ if (startAngle + 180 < stopAngle)
+ startAngle += 360;
+ }
+
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), exitEntry.movieStart, startAngle, exitEntry.movieEnd, stopAngle);
+}
+
+void Neighborhood::scheduleNavCallBack(NotificationFlags flags) {
+ _navMovieCallBack.cancelCallBack();
+
+ if (flags != 0) {
+ _navMovieCallBack.setCallBackFlag(flags);
+ _navMovieCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ }
+}
+
+void Neighborhood::scheduleStridingCallBack(const TimeValue strideStop, NotificationFlags flags) {
+ _stridingCallBack.cancelCallBack();
+
+ if (flags != 0)
+ _stridingCallBack.scheduleCallBack(kTriggerTimeFwd, strideStop, _navMovie.getScale());
+}
+
+void Neighborhood::moveNavTo(const CoordType h, const CoordType v) {
+ CoordType oldH, oldV;
+ _navMovie.getLocation(oldH, oldV);
+
+ CoordType offH = h - oldH;
+ CoordType offV = v - oldV;
+
+ _navMovie.moveElementTo(h, v);
+ _turnPush.moveElementTo(h, v);
+
+ if (offH != 0 || offV != 0)
+ for (HotspotList::iterator it = _neighborhoodHotspots.begin(); it != _neighborhoodHotspots.end(); it++)
+ if ((*it)->getHotspotFlags() & kNeighborhoodSpotFlag)
+ (*it)->moveSpot(offH, offV);
+}
+
+void Neighborhood::activateHotspots() {
+ InputHandler::activateHotspots();
+
+ for (HotspotInfoTable::iterator it = _hotspotInfoTable.begin(); it != _hotspotInfoTable.end(); it++) {
+ HotspotInfoTable::Entry entry = *it;
+
+ if (entry.hotspotRoom == GameState.getCurrentRoom() && entry.hotspotDirection == GameState.getCurrentDirection()
+ && (entry.hotspotActivation == _currentActivation || entry.hotspotActivation == kActivateHotSpotAlways)) {
+ Hotspot *hotspot = _vm->getAllHotspots().findHotspotByID(entry.hotspot);
+ if (hotspot)
+ activateOneHotspot(entry, hotspot);
+ }
+ }
+}
+
+void Neighborhood::clickInHotspot(const Input &input, const Hotspot *clickedSpot) {
+ HotSpotFlags flags = clickedSpot->getHotspotFlags();
+
+ if ((flags & (kPickUpItemSpotFlag | kPickUpBiochipSpotFlag)) != 0) {
+ ItemID itemID = kNoItemID;
+
+ for (HotspotInfoTable::iterator it = _hotspotInfoTable.begin(); it != _hotspotInfoTable.end(); it++) {
+ if (it->hotspot == clickedSpot->getObjectID()) {
+ itemID = it->hotspotItem;
+ break;
+ }
+ }
+
+ if (itemID != kNoItemID) {
+ Item *draggingItem = _vm->getAllItems().findItemByID(itemID);
+
+ if (draggingItem) {
+ takeItemFromRoom(draggingItem);
+
+ if ((flags & kPickUpItemSpotFlag) != 0)
+ _vm->dragItem(input, draggingItem, kDragInventoryPickup);
+ else
+ _vm->dragItem(input, draggingItem, kDragBiochipPickup);
+ }
+ }
+ } else {
+ // Check other flags here?
+ if ((flags & kZoomSpotFlags) != 0) {
+ zoomTo(clickedSpot);
+ } else if ((flags & kPlayExtraSpotFlag) != 0) {
+ HotspotInfoTable::Entry hotspotEntry;
+ getHotspotEntry(clickedSpot->getObjectID(), hotspotEntry);
+ startExtraSequence(hotspotEntry.hotspotExtra, kExtraCompletedFlag, kFilterNoInput);
+ } else if ((flags & kOpenDoorSpotFlag) != 0) {
+ openDoor();
+ } else {
+ InputHandler::clickInHotspot(input, clickedSpot);
+ }
+ }
+}
+
+void Neighborhood::cantMoveThatWay(CanMoveForwardReason reason) {
+ switch (reason) {
+ case kCantMoveDoorClosed:
+ case kCantMoveDoorLocked:
+ openDoor();
+ break;
+ case kCantMoveBlocked:
+ zoomUpOrBump();
+ break;
+ default:
+ bumpIntoWall();
+ break;
+ }
+}
+
+void Neighborhood::cantOpenDoor(CanOpenDoorReason) {
+ bumpIntoWall();
+}
+
+void Neighborhood::turnTo(const DirectionConstant direction) {
+ if (g_map)
+ g_map->moveToMapLocation(GameState.getCurrentNeighborhood(), GameState.getCurrentRoom(), direction);
+
+ // clone2727 says: Is this necessary?
+ _vm->_gfx->setCurSurface(_navMovie.getSurface());
+ _pushIn.copyToCurrentPort();
+ _vm->_gfx->setCurSurface(_vm->_gfx->getWorkArea());
+
+ // Added 2/10/97. Shouldn't this be here? Shouldn't we set the current activation to
+ // always when turning to a new view?
+ _currentActivation = kActivateHotSpotAlways;
+
+ _interruptionFilter = kFilterAllInput;
+
+ if (direction != GameState.getCurrentDirection()) {
+ GameState.setCurrentDirection(direction);
+ activateCurrentView(GameState.getCurrentRoom(), direction, kSpotOnTurnMask);
+ } else {
+ showViewFrame(getViewTime(GameState.getCurrentRoom(), GameState.getCurrentDirection()));
+ }
+
+ if (GameState.getOpenDoorRoom() != kNoRoomID) {
+ // Turning always closes a door.
+ loadAmbientLoops();
+ closeDoorOffScreen(GameState.getOpenDoorRoom(), GameState.getOpenDoorDirection());
+ GameState.setOpenDoorLocation(kNoRoomID, kNoDirection);
+ }
+
+ if (g_AIArea)
+ g_AIArea->checkMiddleArea();
+
+ checkContinuePoint(GameState.getCurrentRoom(), direction);
+
+ _vm->_cursor->hideUntilMoved();
+}
+
+void Neighborhood::spotCompleted() {
+ _interruptionFilter = kFilterAllInput;
+ showViewFrame(getViewTime(GameState.getCurrentRoom(), GameState.getCurrentDirection()));
+}
+
+void Neighborhood::doorOpened() {
+ _interruptionFilter = kFilterAllInput;
+
+ // 2/23/97
+ // Fixes funny bug with doors that are opened by dropping things on them...
+ setCurrentActivation(kActivateHotSpotAlways);
+
+ GameState.setOpenDoorLocation(GameState.getCurrentRoom(), GameState.getCurrentDirection());
+
+ SpotTable::Entry entry;
+ findSpotEntry(GameState.getCurrentRoom(), GameState.getCurrentDirection(), kSpotOnDoorOpenMask, entry);
+
+ if (entry.dstFlags & kSpotOnDoorOpenMask) {
+ startSpotOnceOnly(entry.movieStart, entry.movieEnd);
+ } else {
+ findSpotEntry(GameState.getCurrentRoom(), GameState.getCurrentDirection(), kSpotOnDoorOpenMask | kSpotLoopsMask, entry);
+
+ if (entry.dstFlags & kSpotOnDoorOpenMask)
+ startSpotLoop(entry.movieStart, entry.movieEnd);
+ }
+
+ loadAmbientLoops();
+
+ if (g_map)
+ g_map->moveToMapLocation(GameState.getCurrentNeighborhood(), GameState.getNextRoom(), GameState.getNextDirection());
+
+ if (g_AIArea)
+ g_AIArea->checkMiddleArea();
+}
+
+void Neighborhood::moveForward() {
+ ExitTable::Entry exitEntry;
+ CanMoveForwardReason moveReason = canMoveForward(exitEntry);
+
+ if (moveReason == kCanMoveForward)
+ startExitMovie(exitEntry);
+ else
+ cantMoveThatWay(moveReason);
+}
+
+void Neighborhood::turn(const TurnDirection turnDirection) {
+ DirectionConstant nextDir;
+ CanTurnReason turnReason = canTurn(turnDirection, nextDir);
+
+ if (turnReason == kCanTurn)
+ startTurnPush(turnDirection, getViewTime(GameState.getCurrentRoom(), nextDir), nextDir);
+ else
+ cantTurnThatWay(turnReason);
+}
+
+void Neighborhood::turnLeft() {
+ turn(kTurnLeft);
+}
+
+void Neighborhood::turnRight() {
+ turn(kTurnRight);
+}
+
+void Neighborhood::turnUp() {
+ turn(kTurnUp);
+}
+
+void Neighborhood::turnDown() {
+ turn(kTurnDown);
+}
+
+void Neighborhood::openDoor() {
+ DoorTable::Entry door;
+ CanOpenDoorReason doorReason = canOpenDoor(door);
+
+ if (doorReason == kCanOpenDoor)
+ startDoorOpenMovie(door.movieStart, door.movieEnd);
+ else
+ cantOpenDoor(doorReason);
+}
+
+void Neighborhood::zoomTo(const Hotspot *hotspot) {
+ ZoomTable::Entry zoomEntry;
+ getZoomEntry(hotspot->getObjectID(), zoomEntry);
+ if (!zoomEntry.isEmpty())
+ startZoomMovie(zoomEntry);
+}
+
+void Neighborhood::updateViewFrame() {
+ showViewFrame(getViewTime(GameState.getCurrentRoom(), GameState.getCurrentDirection()));
+}
+
+void Neighborhood::startSpotLoop(TimeValue startTime, TimeValue stopTime, NotificationFlags flags) {
+ _turnPush.hide();
+ startMovieSequence(startTime, stopTime, flags, true, kFilterAllInput);
+}
+
+void Neighborhood::showViewFrame(TimeValue viewTime) {
+ if ((int32)viewTime >= 0) {
+ _turnPush.hide();
+ _navMovie.stop();
+ _navMovie.setFlags(0);
+ _navMovie.setSegment(0, _navMovie.getDuration());
+ _navMovie.setTime(viewTime);
+
+ Common::Rect pushBounds;
+ _turnPush.getBounds(pushBounds);
+
+ _navMovie.moveElementTo(pushBounds.left, pushBounds.top);
+ _navMovie.show();
+ _navMovie.redrawMovieWorld();
+ }
+}
+
+void Neighborhood::startExtraSequence(const ExtraID extraID, const NotificationFlags flags, const InputBits interruptionFilter) {
+ ExtraTable::Entry entry;
+ getExtraEntry(extraID, entry);
+
+ if (entry.movieStart != 0xffffffff)
+ playExtraMovie(entry, flags, interruptionFilter);
+}
+
+bool Neighborhood::startExtraSequenceSync(const ExtraID extraID, const InputBits interruptionFilter) {
+ InputDevice.waitInput(interruptionFilter);
+ return prepareExtraSync(extraID) && waitMovieFinish(&_navMovie, interruptionFilter);
+}
+
+void Neighborhood::loopExtraSequence(const uint32 extraID, NotificationFlags flags) {
+ ExtraTable::Entry entry;
+ getExtraEntry(extraID, entry);
+
+ if (entry.movieStart != 0xffffffff) {
+ _lastExtra = extraID;
+ startSpotLoop(entry.movieStart, entry.movieEnd, flags);
+ }
+}
+
+bool Neighborhood::navMoviePlaying() {
+ return _navMovie.isRunning();
+}
+
+void Neighborhood::playDeathExtra(ExtraID extra, DeathReason deathReason) {
+ _extraDeathReason = deathReason;
+ startExtraSequence(extra, kDeathExtraCompletedFlag, kFilterNoInput);
+}
+
+void Neighborhood::die(const DeathReason deathReason) {
+ loadLoopSound1("");
+ loadLoopSound2("");
+ _vm->die(deathReason);
+}
+
+void Neighborhood::setSoundFXLevel(const uint16 fxLevel) {
+ if (_navMovie.isSurfaceValid())
+ _navMovie.setVolume(fxLevel);
+ if (_spotSounds.isSoundLoaded())
+ _spotSounds.setVolume(fxLevel);
+ if (_currentInteraction)
+ _currentInteraction->setSoundFXLevel(fxLevel);
+}
+
+void Neighborhood::setAmbienceLevel(const uint16 ambientLevel) {
+ if (_soundLoop1.isSoundLoaded())
+ _loop1Fader.setMasterVolume(_vm->getAmbienceLevel());
+ if (_soundLoop2.isSoundLoaded())
+ _loop2Fader.setMasterVolume(_vm->getAmbienceLevel());
+ if (_currentInteraction)
+ _currentInteraction->setAmbienceLevel(ambientLevel);
+}
+
+// Force the exit taken from (room, direction, alternate) to come to a stop.
+void Neighborhood::forceStridingStop(const RoomID room, const DirectionConstant direction, const AlternateID alternate) {
+ ExitTable::Entry entry = _exitTable.findEntry(room, direction, alternate);
+
+ if (entry.movieStart != 0xffffffff) {
+ TimeValue strideStop = entry.exitEnd;
+ TimeValue exitStop = entry.movieEnd;
+
+ if (strideStop != exitStop) {
+ for (ExitTable::iterator it = _exitTable.begin(); it != _exitTable.end(); it++) {
+ entry = *it;
+
+ if (entry.exitEnd == strideStop && entry.movieEnd <= exitStop) {
+ entry.exitEnd = exitStop;
+ *it = entry;
+ }
+ }
+ }
+ }
+}
+
+// Restore the exit taken from (room, direction, alternate) to stride.
+void Neighborhood::restoreStriding(const RoomID room, const DirectionConstant direction, const AlternateID alternate) {
+ ExitTable::Entry entry = _exitTable.findEntry(room, direction, alternate);
+
+ if (entry.movieStart != 0xffffffff) {
+ TimeValue strideStop = entry.exitEnd;
+ TimeValue exitStop = entry.movieEnd;
+
+ if (strideStop != entry.originalEnd) {
+ for (ExitTable::iterator it = _exitTable.begin(); it != _exitTable.end(); it++) {
+ entry = *it;
+
+ if (entry.exitEnd == strideStop && entry.movieEnd <= exitStop) {
+ entry.exitEnd = entry.originalEnd;
+ *it = entry;
+ }
+ }
+ }
+ }
+}
+
+HotspotInfoTable::Entry *Neighborhood::findHotspotEntry(const HotSpotID id) {
+ for (HotspotInfoTable::iterator it = _hotspotInfoTable.begin(); it != _hotspotInfoTable.end(); it++)
+ if (it->hotspot == id)
+ return &(*it);
+
+ return 0;
+}
+
+void Neighborhood::hideNav() {
+ _isRunning = _navMovie.isRunning();
+ _navMovie.stop();
+ _navMovie.hide();
+ _turnPush.stopFader();
+ _turnPush.hide();
+}
+
+void Neighborhood::showNav() {
+ _navMovie.show();
+ _turnPush.hide();
+ if (_isRunning)
+ _navMovie.start();
+}
+
+void Neighborhood::startExitMovie(const ExitTable::Entry &exitEntry) {
+ FaderMoveSpec compassMove;
+
+ if (g_compass)
+ getExitCompassMove(exitEntry, compassMove);
+
+ GameState.setNextRoom(exitEntry.exitRoom);
+ GameState.setNextDirection(exitEntry.exitDirection);
+
+ if (exitEntry.movieEnd == exitEntry.exitEnd) // Just a walk.
+ startMovieSequence(exitEntry.movieStart, exitEntry.movieEnd, kMoveForwardCompletedFlag, kFilterNoInput, false);
+ else // We're stridin'!
+ startMovieSequence(exitEntry.movieStart, exitEntry.exitEnd, kStrideCompletedFlag, kFilterNoInput, false, exitEntry.movieEnd);
+
+ if (g_compass)
+ g_compass->startFader(compassMove);
+}
+
+void Neighborhood::startZoomMovie(const ZoomTable::Entry &zoomEntry) {
+ FaderMoveSpec compassMove;
+
+ if (g_compass)
+ getZoomCompassMove(zoomEntry, compassMove);
+
+ GameState.setNextRoom(zoomEntry.room);
+ GameState.setNextDirection(zoomEntry.direction);
+
+ startMovieSequence(zoomEntry.movieStart, zoomEntry.movieEnd, kMoveForwardCompletedFlag, kFilterNoInput, false);
+
+ if (g_compass)
+ g_compass->startFader(compassMove);
+}
+
+void Neighborhood::startDoorOpenMovie(const TimeValue startTime, const TimeValue stopTime) {
+ startMovieSequence(startTime, stopTime, kDoorOpenCompletedFlag, kFilterNoInput, false);
+}
+
+void Neighborhood::startTurnPush(const TurnDirection turnDirection, const TimeValue newView, const DirectionConstant nextDir) {
+ if (g_AIArea)
+ g_AIArea->lockAIOut();
+
+ _vm->_cursor->hide();
+
+ GameState.setNextDirection(nextDir);
+
+ _interruptionFilter = kFilterNoInput;
+ _turnPush.stopFader();
+
+ // Set up callback.
+ _turnPushCallBack.setCallBackFlag(kTurnCompletedFlag);
+ _turnPushCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+
+ // Stop nav movie.
+ _navMovie.stop();
+ _navMovie.setFlags(0);
+
+ // Set segment of nav movie to whole movie, so that subsequent initFromMovieFrame
+ // will work.
+ _navMovie.setSegment(0, _navMovie.getDuration());
+
+ _pushIn.initFromMovieFrame(_navMovie.getMovie(), newView);
+
+ _navMovie.hide();
+
+ switch (turnDirection) {
+ case kTurnLeft:
+ _turnPush.setSlideDirection(kSlideRightMask);
+ break;
+ case kTurnRight:
+ _turnPush.setSlideDirection(kSlideLeftMask);
+ break;
+ case kTurnUp:
+ _turnPush.setSlideDirection(kSlideDownMask);
+ break;
+ case kTurnDown:
+ _turnPush.setSlideDirection(kSlideUpMask);
+ break;
+ }
+
+ _turnPush.show();
+
+ FaderMoveSpec moveSpec;
+ moveSpec.makeTwoKnotFaderSpec(60, 0, 0, 15, 1000);
+ _turnPush.startFader(moveSpec);
+
+ if (g_compass) {
+ _turnPush.pauseFader();
+
+ int32 startAngle = getStaticCompassAngle(GameState.getCurrentRoom(), GameState.getCurrentDirection());
+ int32 stopAngle = getStaticCompassAngle(GameState.getCurrentRoom(), nextDir);
+
+ if (turnDirection == kTurnLeft) {
+ if (startAngle < stopAngle)
+ startAngle += 360;
+ } else {
+ if (stopAngle < startAngle)
+ stopAngle += 360;
+ }
+
+ FaderMoveSpec turnSpec;
+ _turnPush.getCurrentFaderMove(turnSpec);
+
+ FaderMoveSpec compassMove;
+ compassMove.makeTwoKnotFaderSpec(turnSpec.getFaderScale(), turnSpec.getNthKnotTime(0), startAngle, turnSpec.getNthKnotTime(1), stopAngle);
+ g_compass->startFader(compassMove);
+ }
+
+ _turnPushCallBack.cancelCallBack();
+ _turnPush.continueFader();
+
+ do {
+ _vm->checkCallBacks();
+ _vm->refreshDisplay();
+ _vm->_system->delayMillis(10);
+ } while (_turnPush.isFading());
+
+ _turnPush.stopFader();
+ _neighborhoodNotification.setNotificationFlags(kTurnCompletedFlag, kTurnCompletedFlag);
+}
+
+void Neighborhood::playExtraMovie(const ExtraTable::Entry &extraEntry, const NotificationFlags flags, const InputBits interruptionInput) {
+ FaderMoveSpec compassMove;
+
+ if (g_compass)
+ getExtraCompassMove(extraEntry, compassMove);
+
+ _lastExtra = extraEntry.extra;
+ _turnPush.hide();
+ startMovieSequence(extraEntry.movieStart, extraEntry.movieEnd, flags, false, interruptionInput);
+
+ if (g_compass)
+ g_compass->startFader(compassMove);
+}
+
+void Neighborhood::activateCurrentView(const RoomID room, const DirectionConstant direction, SpotFlags flag) {
+ SpotTable::Entry entry;
+ findSpotEntry(room, direction, flag, entry);
+
+ if (entry.dstFlags & flag) {
+ startSpotOnceOnly(entry.movieStart, entry.movieEnd);
+ } else {
+ findSpotEntry(room, direction, flag | kSpotLoopsMask, entry);
+
+ if (entry.dstFlags & flag)
+ startSpotLoop(entry.movieStart, entry.movieEnd);
+ else
+ showViewFrame(getViewTime(room, direction));
+ }
+}
+
+void Neighborhood::activateOneHotspot(HotspotInfoTable::Entry &entry, Hotspot *hotspot) {
+ switch (_vm->getDragType()) {
+ case kDragInventoryUse:
+ if ((hotspot->getHotspotFlags() & kDropItemSpotFlag) != 0 &&
+ _vm->getDraggingItem()->getObjectID() == entry.hotspotItem)
+ hotspot->setActive();
+ break;
+ case kDragInventoryPickup:
+ case kDragBiochipPickup:
+ // Do nothing -- neighborhoods activate no hot spots in this case...
+ break;
+ default:
+ if ((hotspot->getHotspotFlags() & kPickUpBiochipSpotFlag) != 0) {
+ Item *item = _vm->getAllItems().findItemByID(entry.hotspotItem);
+ if (item && item->getItemNeighborhood() == getObjectID())
+ hotspot->setActive();
+ } else {
+ HotSpotFlags flags = hotspot->getHotspotFlags();
+
+ if ((flags & kNeighborhoodSpotFlag) != 0) {
+ if (flags & kOpenDoorSpotFlag) {
+ if (!GameState.isCurrentDoorOpen())
+ hotspot->setActive();
+ } else if ((flags & (kZoomSpotFlags | kClickSpotFlag | kPlayExtraSpotFlag)) != 0) {
+ hotspot->setActive();
+ } else if ((flags & kPickUpItemSpotFlag) != 0) {
+ // Changed this 2/19/96
+ // Should only light up this hot spot if the item's taken flag is not
+ // set. It's not based on neighborhood ID since that can be reset by the
+ // destroying process.
+
+ if (!GameState.isTakenItemID(entry.hotspotItem))
+ hotspot->setActive();
+ }
+ }
+ }
+ break;
+ }
+}
+
+void Neighborhood::startSpotOnceOnly(TimeValue startTime, TimeValue stopTime) {
+ _turnPush.hide();
+ startMovieSequence(startTime, stopTime, kSpotCompletedFlag, kFilterNoInput, false);
+}
+
+void Neighborhood::startMovieSequence(const TimeValue startTime, const TimeValue stopTime, NotificationFlags flags, bool loopSequence,
+ const InputBits interruptionInput, const TimeValue strideStop) {
+ if (!loopSequence && g_AIArea)
+ g_AIArea->lockAIOut();
+
+ _interruptionFilter = interruptionInput;
+
+ // Stop the movie before doing anything else
+ _navMovie.stop();
+
+ Common::Rect pushBounds;
+ _turnPush.getBounds(pushBounds);
+
+ _navMovie.moveElementTo(pushBounds.left, pushBounds.top);
+ _navMovie.show();
+ _navMovie.setFlags(0);
+ _navMovie.setSegment(startTime, stopTime);
+ _navMovie.setTime(startTime);
+
+ if (loopSequence)
+ _navMovie.setFlags(kLoopTimeBase);
+ else
+ flags |= kNeighborhoodMovieCompletedFlag;
+
+ if (strideStop != 0xffffffff)
+ // Subtract a little slop from the striding stop time to keep from "pumping" at the
+ // end of a walk.
+ // 40 is one frame (scale == 600, 15 fps).
+ scheduleStridingCallBack(strideStop - kStridingSlop, flags);
+ else
+ scheduleNavCallBack(flags);
+
+ _navMovie.start();
+}
+
+void Neighborhood::throwAwayInterface() {
+ _doorTable.clear();
+ _exitTable.clear();
+ _extraTable.clear();
+ _hotspotInfoTable.clear();
+ _spotTable.clear();
+ _turnTable.clear();
+ _viewTable.clear();
+ _zoomTable.clear();
+
+ _navMovie.stopDisplaying();
+ _navMovie.releaseMovie();
+ _pushIn.deallocateSurface();
+ _turnPush.stopDisplaying();
+ _turnPush.setInAndOutElements(0, 0);
+ _turnPush.disposeAllCallBacks();
+
+ for (HotspotList::iterator it = _neighborhoodHotspots.begin(); it != _neighborhoodHotspots.end(); it++)
+ _vm->getAllHotspots().remove(*it);
+
+ _neighborhoodHotspots.deleteHotspots();
+ _spotSounds.disposeSound();
+ _delayTimer.disposeAllCallBacks();
+
+ if (g_AIArea) {
+ g_AIArea->saveAIState();
+ g_AIArea->removeAllRules();
+ }
+
+ if (_currentInteraction)
+ newInteraction(kNoInteractionID);
+
+ _croppedMovie.releaseMovie();
+
+ loadLoopSound1("");
+ loadLoopSound2("");
+
+ if (g_energyMonitor) {
+ g_energyMonitor->stopEnergyDraining();
+ g_energyMonitor->saveCurrentEnergyValue();
+ }
+
+ delete g_interface;
+}
+
+bool Neighborhood::prepareExtraSync(const ExtraID extraID) {
+ ExtraTable::Entry extraEntry;
+ FaderMoveSpec compassMove;
+
+ if (g_compass) {
+ getExtraEntry(extraID, extraEntry);
+ getExtraCompassMove(extraEntry, compassMove);
+ }
+
+ ExtraTable::Entry entry;
+ getExtraEntry(extraID, entry);
+ bool result;
+
+ if (entry.movieStart != 0xffffffff) {
+ _turnPush.hide();
+
+ // Stop the movie before doing anything else
+ _navMovie.stop();
+
+ Common::Rect pushBounds;
+ _turnPush.getBounds(pushBounds);
+ _navMovie.moveElementTo(pushBounds.left, pushBounds.top);
+
+ _navMovie.show();
+ _navMovie.setFlags(0);
+ _navMovie.setSegment(entry.movieStart, entry.movieEnd);
+ _navMovie.setTime(entry.movieStart);
+ _navMovie.start();
+ result = true;
+ } else {
+ result = false;
+ }
+
+ if (result && g_compass)
+ g_compass->startFader(compassMove);
+
+ return result;
+}
+
+bool Neighborhood::waitMovieFinish(Movie *movie, const InputBits interruptionFilter) {
+ Input input;
+ bool result = true;
+ bool saveAllowed = _vm->swapSaveAllowed(false);
+ bool openAllowed = _vm->swapLoadAllowed(false);
+
+ while (movie->isRunning()) {
+ InputDevice.getInput(input, interruptionFilter);
+
+ if (input.anyInput() || _vm->shouldQuit()) {
+ result = false;
+ break;
+ }
+
+ _vm->checkCallBacks();
+ _vm->refreshDisplay();
+ _vm->_system->delayMillis(10);
+ }
+
+ movie->stop();
+ _vm->swapSaveAllowed(saveAllowed);
+ _vm->swapLoadAllowed(openAllowed);
+
+ return result;
+}
+
+InputBits Neighborhood::getInputFilter() {
+ return _interruptionFilter & InputHandler::getInputFilter();
+}
+
+void Neighborhood::getZoomCompassMove(const ZoomTable::Entry &zoomEntry, FaderMoveSpec &compassMove) {
+ int32 startAngle = getStaticCompassAngle(GameState.getCurrentRoom(), GameState.getCurrentDirection());
+ int32 stopAngle = getStaticCompassAngle(zoomEntry.room, zoomEntry.direction);
+
+ if (startAngle > stopAngle) {
+ if (stopAngle + 180 < startAngle)
+ stopAngle += 360;
+ } else {
+ if (startAngle + 180 < stopAngle)
+ startAngle += 360;
+ }
+
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), zoomEntry.movieStart, startAngle, zoomEntry.movieEnd, stopAngle);
+}
+
+void Neighborhood::getExtraCompassMove(const ExtraTable::Entry &, FaderMoveSpec &compassMove) {
+ compassMove.makeOneKnotFaderSpec(g_compass->getFaderValue());
+}
+
+void Neighborhood::setUpAIRules() {
+ // Set up default rules here:
+ // -- Energy warning rules.
+
+ if (g_AIArea) {
+ g_AIArea->forceAIUnlocked();
+
+ if (!_vm->isDemo() && (getObjectID() == kPrehistoricID || getObjectID() == kNoradAlphaID ||
+ getObjectID() == kNoradDeltaID || getObjectID() == kMarsID || getObjectID() == kWSCID)) {
+
+ AIEnergyMonitorCondition *condition50 = new AIEnergyMonitorCondition(kWorriedEnergy);
+ AIPlayMessageAction *message = new AIPlayMessageAction("Images/AI/Globals/XGLOB4A", false);
+ AIRule *rule50 = new AIRule(condition50, message);
+
+ AIEnergyMonitorCondition *condition25 = new AIEnergyMonitorCondition(kNervousEnergy);
+ AICompoundAction *compound = new AICompoundAction();
+ message = new AIPlayMessageAction("Images/AI/Globals/XGLOB4B", false);
+ compound->addAction(message);
+ AIDeactivateRuleAction *deactivate = new AIDeactivateRuleAction(rule50);
+ compound->addAction(deactivate);
+ AIRule *rule25 = new AIRule(condition25, compound);
+
+ AIEnergyMonitorCondition *condition5 = new AIEnergyMonitorCondition(kPanicStrickenEnergy);
+ compound = new AICompoundAction();
+ message = new AIPlayMessageAction("Images/AI/Globals/XGLOB4C", false);
+ compound->addAction(message);
+ deactivate = new AIDeactivateRuleAction(rule50);
+ compound->addAction(deactivate);
+ deactivate = new AIDeactivateRuleAction(rule25);
+ compound->addAction(deactivate);
+ AIRule *rule5 = new AIRule(condition5, compound);
+
+ g_AIArea->addAIRule(rule5);
+ g_AIArea->addAIRule(rule25);
+ g_AIArea->addAIRule(rule50);
+ }
+ }
+}
+
+GameInteraction *Neighborhood::makeInteraction(const InteractionID interactionID) {
+ if (interactionID == kNoInteractionID)
+ return 0;
+
+ return new GameInteraction(interactionID, this);
+}
+
+void Neighborhood::newInteraction(const InteractionID interactionID) {
+ GameInteraction *interaction = makeInteraction(interactionID);
+ _doneWithInteraction = false;
+
+ if (_currentInteraction) {
+ _currentInteraction->stopInteraction();
+ delete _currentInteraction;
+ }
+
+ _currentInteraction = interaction;
+
+ if (_currentInteraction)
+ _currentInteraction->startInteraction();
+
+ if (g_AIArea)
+ g_AIArea->checkMiddleArea();
+}
+
+void Neighborhood::bumpIntoWall() {
+ _vm->_gfx->shakeTheWorld(15, 30);
+}
+
+void Neighborhood::zoomUpOrBump() {
+ Hotspot *zoomSpot = 0;
+
+ for (HotspotList::iterator it = _vm->getAllHotspots().begin(); it != _vm->getAllHotspots().end(); it++) {
+ Hotspot *hotspot = *it;
+
+ if ((hotspot->getHotspotFlags() & (kNeighborhoodSpotFlag | kZoomInSpotFlag)) == (kNeighborhoodSpotFlag | kZoomInSpotFlag)) {
+ HotspotInfoTable::Entry *entry = findHotspotEntry(hotspot->getObjectID());
+
+ if (entry && entry->hotspotRoom == GameState.getCurrentRoom() && entry->hotspotDirection == GameState.getCurrentDirection()) {
+ if (zoomSpot) {
+ zoomSpot = 0;
+ break;
+ } else {
+ zoomSpot = hotspot;
+ }
+ }
+ }
+ }
+
+ if (zoomSpot)
+ zoomTo(zoomSpot);
+ else
+ bumpIntoWall();
+}
+
+void Neighborhood::loadLoopSound1(const Common::String &soundName, uint16 volume, TimeValue fadeOut, TimeValue fadeIn, TimeScale fadeScale) {
+ FaderMoveSpec faderMove;
+
+ if (!loop1Loaded(soundName)) {
+ _loop1SoundString = soundName;
+
+ if (_soundLoop1.isSoundLoaded()) {
+ faderMove.makeTwoKnotFaderSpec(fadeScale, 0, _loop1Fader.getFaderValue(), fadeOut, 0);
+ _loop1Fader.startFaderSync(faderMove);
+ }
+
+ if (!_loop1SoundString.empty()) {
+ _soundLoop1.initFromAIFFFile(_loop1SoundString);
+ _soundLoop1.loopSound();
+ _loop1Fader.setMasterVolume(_vm->getAmbienceLevel());
+ _loop1Fader.setFaderValue(0);
+ faderMove.makeTwoKnotFaderSpec(fadeScale, 0, 0, fadeIn, volume);
+ _loop1Fader.startFaderSync(faderMove);
+ } else {
+ _soundLoop1.disposeSound();
+ }
+ } else if (_loop1Fader.getFaderValue() != volume) {
+ faderMove.makeTwoKnotFaderSpec(fadeScale, 0, _loop1Fader.getFaderValue(), fadeIn, volume);
+ _loop1Fader.startFaderSync(faderMove);
+ }
+}
+
+void Neighborhood::loadLoopSound2(const Common::String &soundName, uint16 volume, TimeValue fadeOut, TimeValue fadeIn, TimeScale fadeScale) {
+ FaderMoveSpec faderMove;
+
+ if (!loop2Loaded(soundName)) {
+ _loop2SoundString = soundName;
+
+ if (_soundLoop2.isSoundLoaded()) {
+ faderMove.makeTwoKnotFaderSpec(fadeScale, 0, _loop2Fader.getFaderValue(), fadeOut, 0);
+ _loop2Fader.startFaderSync(faderMove);
+ }
+
+ if (!_loop2SoundString.empty()) {
+ _soundLoop2.initFromAIFFFile(_loop2SoundString);
+ _soundLoop2.loopSound();
+ _loop2Fader.setMasterVolume(_vm->getAmbienceLevel());
+ _loop2Fader.setFaderValue(0);
+ faderMove.makeTwoKnotFaderSpec(fadeScale, 0, 0, fadeIn, volume);
+ _loop2Fader.startFaderSync(faderMove);
+ } else {
+ _soundLoop2.disposeSound();
+ }
+ } else if (_loop2Fader.getFaderValue() != volume) {
+ faderMove.makeTwoKnotFaderSpec(fadeScale, 0, _loop2Fader.getFaderValue(), fadeIn, volume);
+ _loop2Fader.startFaderSync(faderMove);
+ }
+}
+
+void Neighborhood::takeItemFromRoom(Item *item) {
+ item->setItemRoom(kNoNeighborhoodID, kNoRoomID, kNoDirection);
+ // Also set the taken item flag. Do this before updating the view frame.
+ GameState.setTakenItem(item, true);
+ updateViewFrame();
+}
+
+void Neighborhood::dropItemIntoRoom(Item *item, Hotspot *) {
+ item->setItemRoom(getObjectID(), GameState.getCurrentRoom(), GameState.getCurrentDirection());
+ // Also set the taken item flag. Do this before updating the view frame.
+ GameState.setTakenItem(item, false);
+ updateViewFrame();
+}
+
+void Neighborhood::makeContinuePoint() {
+ _vm->makeContinuePoint();
+}
+
+void Neighborhood::startLoop1Fader(const FaderMoveSpec &faderMove) {
+ _loop1Fader.startFader(faderMove);
+}
+
+void Neighborhood::startLoop2Fader(const FaderMoveSpec &faderMove) {
+ _loop2Fader.startFader(faderMove);
+}
+
+// *** Revised 6/13/96 to use the last frame of the extra sequence.
+// Necessary for Cinepak buildup.
+void Neighborhood::showExtraView(uint32 extraID) {
+ ExtraTable::Entry entry;
+ getExtraEntry(extraID, entry);
+
+ if (entry.movieEnd != 0xffffffff)
+ showViewFrame(entry.movieEnd - 1);
+}
+
+void Neighborhood::startExtraLongSequence(const uint32 firstExtra, const uint32 lastExtra, NotificationFlags flags,
+ const InputBits interruptionFilter) {
+ ExtraTable::Entry firstEntry, lastEntry;
+ getExtraEntry(firstExtra, firstEntry);
+
+ if (firstEntry.movieStart != 0xffffffff) {
+ getExtraEntry(lastExtra, lastEntry);
+ _lastExtra = firstExtra;
+ _turnPush.hide();
+ startMovieSequence(firstEntry.movieStart, lastEntry.movieEnd, flags, kFilterNoInput, interruptionFilter);
+ }
+}
+
+void Neighborhood::openCroppedMovie(const Common::String &movieName, CoordType left, CoordType top) {
+ if (_croppedMovie.isMovieValid())
+ closeCroppedMovie();
+
+ _croppedMovie.initFromMovieFile(movieName);
+ _croppedMovie.moveElementTo(left, top);
+ _croppedMovie.startDisplaying();
+ _croppedMovie.show();
+}
+
+void Neighborhood::loopCroppedMovie(const Common::String &movieName, CoordType left, CoordType top) {
+ openCroppedMovie(movieName, left, top);
+ _croppedMovie.redrawMovieWorld();
+ _croppedMovie.setFlags(kLoopTimeBase);
+ _croppedMovie.start();
+}
+
+void Neighborhood::closeCroppedMovie() {
+ _croppedMovie.releaseMovie();
+}
+
+void Neighborhood::playCroppedMovieOnce(const Common::String &movieName, CoordType left, CoordType top, const InputBits interruptionFilter) {
+ openCroppedMovie(movieName, left, top);
+ _croppedMovie.redrawMovieWorld();
+ _croppedMovie.start();
+
+ InputBits oldInterruptionFilter = _interruptionFilter;
+ if (oldInterruptionFilter != kFilterNoInput)
+ _interruptionFilter = kFilterNoInput;
+
+ bool saveAllowed = _vm->swapSaveAllowed(false);
+ bool openAllowed = _vm->swapLoadAllowed(false);
+
+ Input input;
+ while (_croppedMovie.isRunning() && !_vm->shouldQuit()) {
+ _vm->processShell();
+ InputDevice.getInput(input, interruptionFilter);
+ if (input.anyInput() || _vm->saveRequested() || _vm->loadRequested() || _vm->shouldQuit())
+ break;
+ _vm->_system->delayMillis(10);
+ }
+
+ if (oldInterruptionFilter != kFilterNoInput)
+ _interruptionFilter = oldInterruptionFilter;
+
+ closeCroppedMovie();
+ _vm->swapSaveAllowed(saveAllowed);
+ _vm->swapLoadAllowed(openAllowed);
+}
+
+void Neighborhood::playMovieSegment(Movie *movie, TimeValue startTime, TimeValue stopTime) {
+ TimeValue oldStart, oldStop;
+ movie->getSegment(oldStart, oldStop);
+
+ if (stopTime == 0xffffffff)
+ stopTime = movie->getDuration();
+
+ movie->setSegment(startTime, stopTime);
+ movie->setTime(startTime);
+ movie->start();
+
+ while (movie->isRunning()) {
+ _vm->checkCallBacks();
+ _vm->refreshDisplay();
+ _vm->_system->delayMillis(10);
+ }
+
+ movie->stop();
+ movie->setSegment(oldStart, oldStop);
+}
+
+void Neighborhood::recallToTSASuccess() {
+ if (GameState.allTimeZonesFinished())
+ _vm->jumpToNewEnvironment(kFullTSAID, kTSA37, kNorth);
+ else
+ _vm->jumpToNewEnvironment(kTinyTSAID, kTinyTSA37, kNorth);
+}
+
+void Neighborhood::recallToTSAFailure() {
+ _vm->jumpToNewEnvironment(kTinyTSAID, kTinyTSA37, kNorth);
+}
+
+void Neighborhood::handleInput(const Input &input, const Hotspot *cursorSpot) {
+ if (_vm->getGameMode() == kModeNavigation) {
+ if (input.upButtonAnyDown())
+ upButton(input);
+ else if (input.downButtonAnyDown())
+ downButton(input);
+ else if (input.leftButtonAnyDown())
+ leftButton(input);
+ else if (input.rightButtonAnyDown())
+ rightButton(input);
+ }
+
+ InputHandler::handleInput(input, cursorSpot);
+}
+
+void Neighborhood::setHotspotFlags(const HotSpotID id, const HotSpotFlags flags) {
+ Hotspot *hotspot = _vm->getAllHotspots().findHotspotByID(id);
+ hotspot->setMaskedHotspotFlags(flags, flags);
+}
+
+void Neighborhood::setIsItemTaken(const ItemID id) {
+ GameState.setTakenItemID(id, _vm->playerHasItemID(id));
+}
+
+void Neighborhood::upButton(const Input &) {
+ moveForward();
+}
+
+void Neighborhood::leftButton(const Input &) {
+ turnLeft();
+}
+
+void Neighborhood::rightButton(const Input &) {
+ turnRight();
+}
+
+void Neighborhood::downButton(const Input &) {
+ if (_inputHandler->wantsCursor()) {
+ _vm->getAllHotspots().deactivateAllHotspots();
+ _inputHandler->activateHotspots();
+
+ for (HotspotList::iterator it = _vm->getAllHotspots().begin(); it != _vm->getAllHotspots().end(); it++) {
+ Hotspot *hotspot = *it;
+
+ if (hotspot->isSpotActive() && (hotspot->getHotspotFlags() & (kNeighborhoodSpotFlag | kZoomOutSpotFlag)) == (kNeighborhoodSpotFlag | kZoomOutSpotFlag)) {
+ HotspotInfoTable::Entry *entry = findHotspotEntry(hotspot->getObjectID());
+
+ if (entry && entry->hotspotRoom == GameState.getCurrentRoom() && entry->hotspotDirection == GameState.getCurrentDirection()) {
+ Input scratch;
+ _inputHandler->clickInHotspot(scratch, hotspot);
+ return;
+ }
+ }
+ }
+ }
+}
+
+void Neighborhood::initOnePicture(Picture *picture, const Common::String &pictureName, DisplayOrder order, CoordType left, CoordType top, bool show) {
+ picture->initFromPICTFile(pictureName);
+ picture->setDisplayOrder(order);
+ picture->moveElementTo(left, top);
+ picture->startDisplaying();
+ if (show)
+ picture->show();
+}
+
+void Neighborhood::initOneMovie(Movie *movie, const Common::String &movieName, DisplayOrder order, CoordType left, CoordType top, bool show) {
+ movie->initFromMovieFile(movieName);
+ movie->setDisplayOrder(order);
+ movie->moveElementTo(left, top);
+ movie->startDisplaying();
+
+ if (show)
+ movie->show();
+
+ movie->redrawMovieWorld();
+}
+
+void Neighborhood::reinstateMonocleInterface() {
+ _vm->_gfx->disableErase();
+
+ _vm->createInterface();
+
+ if (g_AIArea)
+ setNextHandler(g_AIArea);
+
+ init();
+
+ moveNavTo(kNavAreaLeft, kNavAreaTop);
+
+ if (g_interface)
+ g_interface->setDate(getDateResID());
+
+ if (g_AIArea)
+ g_AIArea->restoreAIState();
+}
+
+void Neighborhood::useIdleTime() {
+ if (_doneWithInteraction) {
+ newInteraction(kNoInteractionID);
+ loadAmbientLoops();
+ }
+}
+
+void Neighborhood::timerFunction() {
+ timerExpired(getTimerEvent());
+}
+
+void Neighborhood::scheduleEvent(const TimeValue time, const TimeScale scale, const uint32 eventType) {
+ _eventTimer.stopFuse();
+ _eventTimer.primeFuse(time, scale);
+ _timerEvent = eventType;
+ _eventTimer.setFunctor(new Common::Functor0Mem<void, Neighborhood>(this, &Neighborhood::timerFunction));
+ _eventTimer.lightFuse();
+}
+
+void Neighborhood::cancelEvent() {
+ _eventTimer.stopFuse();
+}
+
+void Neighborhood::pauseTimer() {
+ _eventTimer.pauseFuse();
+}
+
+void Neighborhood::resumeTimer() {
+ // NOTE: Yes, this function calls pauseFuse!
+ // Looks like an original game bug, will need
+ // to investigate how this affects gameplay.
+ _eventTimer.pauseFuse();
+}
+
+bool Neighborhood::timerPaused() {
+ return _eventTimer.isFusePaused();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/neighborhood.h b/engines/pegasus/neighborhood/neighborhood.h
new file mode 100644
index 0000000000..3c1c5eac92
--- /dev/null
+++ b/engines/pegasus/neighborhood/neighborhood.h
@@ -0,0 +1,408 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_H
+#define PEGASUS_NEIGHBORHOOD_H
+
+#include "common/queue.h"
+#include "common/str.h"
+
+#include "pegasus/fader.h"
+#include "pegasus/hotspot.h"
+#include "pegasus/input.h"
+#include "pegasus/movie.h"
+#include "pegasus/notification.h"
+#include "pegasus/sound.h"
+#include "pegasus/timers.h"
+#include "pegasus/transition.h"
+#include "pegasus/util.h"
+#include "pegasus/neighborhood/door.h"
+#include "pegasus/neighborhood/exit.h"
+#include "pegasus/neighborhood/extra.h"
+#include "pegasus/neighborhood/hotspotinfo.h"
+#include "pegasus/neighborhood/spot.h"
+#include "pegasus/neighborhood/turn.h"
+#include "pegasus/neighborhood/view.h"
+#include "pegasus/neighborhood/zoom.h"
+
+namespace Pegasus {
+
+class PegasusEngine;
+
+// Pegasus Prime neighborhood id's
+static const NeighborhoodID kCaldoriaID = 0;
+static const NeighborhoodID kFullTSAID = 1;
+static const NeighborhoodID kFinalTSAID = 2;
+static const NeighborhoodID kTinyTSAID = 3;
+static const NeighborhoodID kPrehistoricID = 4;
+static const NeighborhoodID kMarsID = 5;
+static const NeighborhoodID kWSCID = 6;
+static const NeighborhoodID kNoradAlphaID = 7;
+static const NeighborhoodID kNoradDeltaID = 8;
+// The sub chase is not really a neighborhood, but we define a constant that is used
+// to allow an easy transition out of Norad Alpha.
+static const NeighborhoodID kNoradSubChaseID = 1000;
+
+static const TimeScale kDefaultLoopFadeScale = kThirtyTicksPerSecond;
+static const TimeValue kDefaultLoopFadeOut = kHalfSecondPerThirtyTicks;
+static const TimeValue kDefaultLoopFadeIn = kHalfSecondPerThirtyTicks;
+
+enum QueueRequestType {
+ kNavExtraRequest,
+ kSpotSoundRequest,
+ kDelayRequest
+};
+
+// For delay requests, start is interpreted as the total delay and stop is interpreted
+// as the scale the delay is in.
+// For extra requests, start and stop are not used.
+struct QueueRequest {
+ QueueRequestType requestType;
+ ExtraID extra;
+ TimeValue start, stop;
+ InputBits interruptionFilter;
+ bool playing;
+ NotificationFlags flags;
+ Notification *notification;
+};
+
+bool operator==(const QueueRequest &arg1, const QueueRequest &arg2);
+bool operator!=(const QueueRequest &arg1, const QueueRequest &arg2);
+
+class GameInteraction;
+class Item;
+class Neighborhood;
+
+class StriderCallBack : public TimeBaseCallBack {
+public:
+ StriderCallBack(Neighborhood *);
+ virtual ~StriderCallBack() {}
+
+protected:
+ virtual void callBack();
+
+ Neighborhood *_neighborhood;
+};
+
+typedef Common::Queue<QueueRequest> NeighborhoodActionQueue;
+
+class Neighborhood : public IDObject, public NotificationReceiver, public InputHandler, public Idler {
+friend class StriderCallBack;
+
+public:
+ Neighborhood(InputHandler *nextHandler, PegasusEngine *vm, const Common::String &resName, NeighborhoodID id);
+ virtual ~Neighborhood();
+
+ virtual void init();
+ virtual void start();
+ virtual void moveNavTo(const CoordType, const CoordType);
+ virtual void checkContinuePoint(const RoomID, const DirectionConstant) = 0;
+ void makeContinuePoint();
+
+ virtual void activateHotspots();
+ virtual void clickInHotspot(const Input &, const Hotspot *);
+
+ virtual CanMoveForwardReason canMoveForward(ExitTable::Entry &entry);
+ virtual CanTurnReason canTurn(TurnDirection turn, DirectionConstant &nextDir);
+ virtual CanOpenDoorReason canOpenDoor(DoorTable::Entry &entry);
+
+ virtual void cantMoveThatWay(CanMoveForwardReason);
+ virtual void cantTurnThatWay(CanTurnReason) {}
+ virtual void cantOpenDoor(CanOpenDoorReason);
+ virtual void arriveAt(const RoomID room, const DirectionConstant direction);
+ virtual void turnTo(const DirectionConstant);
+ virtual void spotCompleted();
+ virtual void doorOpened();
+ virtual void closeDoorOffScreen(const RoomID, const DirectionConstant) {}
+
+ virtual void moveForward();
+ virtual void turn(const TurnDirection);
+ virtual void turnLeft();
+ virtual void turnRight();
+ virtual void turnUp();
+ virtual void turnDown();
+ virtual void openDoor();
+ virtual void zoomTo(const Hotspot *);
+
+ virtual void updateViewFrame();
+
+ void requestExtraSequence(const ExtraID, const NotificationFlags, const InputBits interruptionFilter);
+ void requestSpotSound(const TimeValue, const TimeValue, const InputBits interruptionFilter, const NotificationFlags);
+ void playSpotSoundSync(const TimeValue in, const TimeValue out);
+ void requestDelay(const TimeValue, const TimeScale, const InputBits interruptionFilter, const NotificationFlags);
+
+ Notification *getNeighborhoodNotification() { return &_neighborhoodNotification; }
+
+ virtual void getExtraEntry(const uint32 id, ExtraTable::Entry &extraEntry);
+ virtual void startSpotLoop(TimeValue, TimeValue, NotificationFlags = 0);
+ virtual bool actionQueueEmpty() { return _actionQueue.empty(); }
+ virtual void showViewFrame(TimeValue);
+ virtual void findSpotEntry(const RoomID room, const DirectionConstant direction, SpotFlags flags, SpotTable::Entry &spotEntry);
+ virtual void startExtraSequence(const ExtraID, const NotificationFlags, const InputBits interruptionFilter);
+ bool startExtraSequenceSync(const ExtraID, const InputBits);
+ virtual void loopExtraSequence(const uint32, NotificationFlags = 0);
+ int32 getLastExtra() const { return _lastExtra; }
+ virtual void scheduleNavCallBack(NotificationFlags);
+
+ Movie *getNavMovie() { return &_navMovie; }
+ bool navMoviePlaying();
+
+ void setCurrentAlternate(const AlternateID alt) { _currentAlternate = alt; }
+ AlternateID getCurrentAlternate() const { return _currentAlternate; }
+
+ void setCurrentActivation(const HotSpotActivationID a) { _currentActivation = a; }
+ HotSpotActivationID getCurrentActivation() { return _currentActivation; }
+
+ virtual void playDeathExtra(ExtraID, DeathReason);
+ virtual void die(const DeathReason);
+
+ virtual void setSoundFXLevel(const uint16);
+ virtual void setAmbienceLevel(const uint16);
+
+ void forceStridingStop(const RoomID, const DirectionConstant, const AlternateID);
+ void restoreStriding(const RoomID, const DirectionConstant, const AlternateID);
+
+ HotspotInfoTable::Entry *findHotspotEntry(const HotSpotID);
+
+ Push *getTurnPush() { return &_turnPush; }
+ Picture *getTurnPushPicture() { return &_pushIn; }
+
+ void hideNav();
+ void showNav();
+
+ virtual void loadAmbientLoops() {}
+
+ virtual void flushGameState() {}
+
+ virtual Common::String getBriefingMovie();
+ virtual Common::String getEnvScanMovie();
+ virtual uint getNumHints();
+ virtual Common::String getHintMovie(uint);
+ virtual bool canSolve();
+ virtual void prepareForAIHint(const Common::String &) {}
+ virtual void cleanUpAfterAIHint(const Common::String &) {}
+ virtual void doSolve();
+
+ virtual bool okayToJump();
+
+ virtual AirQuality getAirQuality(const RoomID);
+ virtual void checkAirMask() {}
+ virtual void checkFlashlight() {}
+ virtual void shieldOn() {}
+ virtual void shieldOff() {}
+
+ virtual void loadLoopSound1(const Common::String &, const uint16 volume = 0x100,
+ const TimeValue fadeOut = kDefaultLoopFadeOut, const TimeValue fadeIn = kDefaultLoopFadeIn,
+ const TimeScale fadeScale = kDefaultLoopFadeScale);
+ virtual void loadLoopSound2(const Common::String &, const uint16 volume = 0x100,
+ const TimeValue fadeOut = kDefaultLoopFadeOut, const TimeValue fadeIn = kDefaultLoopFadeIn,
+ const TimeScale fadeScale = kDefaultLoopFadeScale);
+ bool loop1Loaded(const Common::String &soundName) { return _loop1SoundString == soundName; }
+ bool loop2Loaded(const Common::String &soundName) { return _loop2SoundString == soundName; }
+ void startLoop1Fader(const FaderMoveSpec &);
+ void startLoop2Fader(const FaderMoveSpec &);
+
+ virtual void takeItemFromRoom(Item *);
+ virtual void dropItemIntoRoom(Item *, Hotspot *);
+ virtual Hotspot *getItemScreenSpot(Item *, DisplayElement *) { return 0; }
+
+ virtual GameInteraction *makeInteraction(const InteractionID);
+ virtual void requestDeleteCurrentInteraction() { _doneWithInteraction = true; }
+
+ virtual uint16 getDateResID() const = 0;
+
+ virtual void showExtraView(uint32);
+ virtual void startExtraLongSequence(const uint32, const uint32, NotificationFlags, const InputBits interruptionFilter);
+
+ void openCroppedMovie(const Common::String &, CoordType, CoordType);
+ void loopCroppedMovie(const Common::String &, CoordType, CoordType);
+ void closeCroppedMovie();
+ void playCroppedMovieOnce(const Common::String &, CoordType, CoordType, const InputBits interruptionFilter = kFilterNoInput);
+
+ void playMovieSegment(Movie *, TimeValue = 0, TimeValue = 0xffffffff);
+
+ virtual void recallToTSASuccess();
+ virtual void recallToTSAFailure();
+
+ virtual void pickedUpItem(Item *) {}
+
+ virtual void handleInput(const Input &, const Hotspot *);
+protected:
+ PegasusEngine *_vm;
+ Common::String _resName;
+
+ virtual Common::String getSoundSpotsName() = 0;
+ virtual Common::String getNavMovieName() = 0;
+
+ // Notification function.
+ virtual void receiveNotification(Notification *, const NotificationFlags);
+
+ // Map info functions.
+ virtual void getExitEntry(const RoomID room, const DirectionConstant direction, ExitTable::Entry &entry);
+ virtual TimeValue getViewTime(const RoomID room, const DirectionConstant direction);
+ virtual void getDoorEntry(const RoomID room, const DirectionConstant direction, DoorTable::Entry &doorEntry);
+ virtual DirectionConstant getTurnEntry(const RoomID room, const DirectionConstant direction, const TurnDirection turn);
+ virtual void getZoomEntry(const HotSpotID id, ZoomTable::Entry &zoomEntry);
+ virtual void getHotspotEntry(const HotSpotID id, HotspotInfoTable::Entry &hotspotEntry);
+
+ // Nav movie sequences.
+ virtual void startExitMovie(const ExitTable::Entry &);
+ virtual void keepStriding(ExitTable::Entry &);
+ virtual void stopStriding();
+ virtual void checkStriding();
+ virtual bool stillMoveForward();
+ virtual void scheduleStridingCallBack(const TimeValue, NotificationFlags flags);
+ virtual void startZoomMovie(const ZoomTable::Entry &);
+ virtual void startDoorOpenMovie(const TimeValue, const TimeValue);
+ virtual void startTurnPush(const TurnDirection, const TimeValue, const DirectionConstant);
+ virtual void playExtraMovie(const ExtraTable::Entry &, const NotificationFlags, const InputBits interruptionFilter);
+
+ virtual void activateCurrentView(const RoomID, const DirectionConstant, SpotFlags);
+
+ virtual void activateOneHotspot(HotspotInfoTable::Entry &, Hotspot *);
+
+ virtual void startSpotOnceOnly(TimeValue, TimeValue);
+
+ virtual void startMovieSequence(const TimeValue, const TimeValue, NotificationFlags,
+ bool loopSequence, const InputBits interruptionFilter, const TimeValue strideStop = 0xffffffff);
+
+ virtual void createNeighborhoodSpots();
+
+ void resetLastExtra() { _lastExtra = -1; }
+
+ virtual void throwAwayInterface();
+
+ // Action queue stuff
+ void popActionQueue();
+ void serviceActionQueue();
+ void requestAction(const QueueRequestType, const ExtraID, const TimeValue, const TimeValue, const InputBits, const NotificationFlags);
+
+ virtual bool prepareExtraSync(const ExtraID);
+ virtual bool waitMovieFinish(Movie *, const InputBits);
+
+ virtual InputBits getInputFilter();
+
+ // Misc.
+ virtual int16 getStaticCompassAngle(const RoomID, const DirectionConstant dir);
+ virtual void getExitCompassMove(const ExitTable::Entry &, FaderMoveSpec &);
+ virtual void getZoomCompassMove(const ZoomTable::Entry &, FaderMoveSpec&);
+ virtual void getExtraCompassMove(const ExtraTable::Entry &, FaderMoveSpec&);
+
+ virtual void setUpAIRules();
+ virtual void setHotspotFlags(const HotSpotID, const HotSpotFlags);
+ virtual void setIsItemTaken(const ItemID);
+
+ virtual void upButton(const Input &);
+ virtual void leftButton(const Input &);
+ virtual void rightButton(const Input &);
+ virtual void downButton(const Input &);
+
+ void initOnePicture(Picture *, const Common::String &, DisplayOrder, CoordType, CoordType, bool);
+ void initOneMovie(Movie *, const Common::String &, DisplayOrder, CoordType, CoordType, bool);
+
+ void reinstateMonocleInterface();
+
+ virtual void newInteraction(const InteractionID);
+ virtual void useIdleTime();
+ virtual void bumpIntoWall();
+ virtual void zoomUpOrBump();
+
+ void scheduleEvent(const TimeValue, const TimeScale, const uint32);
+ void cancelEvent();
+ virtual void timerExpired(const uint32) {}
+ bool isEventTimerRunning() { return _eventTimer.isFuseLit(); }
+ uint32 getTimerEvent() { return _timerEvent; }
+ void timerFunction();
+
+ void pauseTimer();
+ void resumeTimer();
+ bool timerPaused();
+
+ // Navigation Data
+ DoorTable _doorTable;
+ ExitTable _exitTable;
+ ExtraTable _extraTable;
+ HotspotInfoTable _hotspotInfoTable;
+ SpotTable _spotTable;
+ TurnTable _turnTable;
+ ViewTable _viewTable;
+ ZoomTable _zoomTable;
+ AlternateID _currentAlternate;
+ HotSpotActivationID _currentActivation;
+
+ int32 _lastExtra;
+ DeathReason _extraDeathReason;
+
+ // Graphics
+ Movie _navMovie;
+ Picture _pushIn;
+ Push _turnPush;
+
+ // Callbacks
+ Notification _neighborhoodNotification;
+ NotificationCallBack _navMovieCallBack;
+ StriderCallBack _stridingCallBack;
+ NotificationCallBack _turnPushCallBack;
+ NotificationCallBack _spotSoundCallBack;
+ NotificationCallBack _delayCallBack;
+
+ // Hotspots
+ HotspotList _neighborhoodHotspots;
+
+ // Sounds
+ SoundTimeBase _spotSounds;
+
+ // Action queue
+ NeighborhoodActionQueue _actionQueue;
+ TimeBase _delayTimer;
+
+ // Interruptibility...
+ InputBits _interruptionFilter;
+
+ // Nav hiding (for info support...)
+ bool _isRunning;
+
+ GameInteraction *_currentInteraction;
+ bool _doneWithInteraction;
+ Movie _croppedMovie;
+
+ Sound _soundLoop1;
+ Common::String _loop1SoundString;
+ SoundFader _loop1Fader;
+
+ Sound _soundLoop2;
+ Common::String _loop2SoundString;
+ SoundFader _loop2Fader;
+
+ // The event timer...
+ FuseFunction _eventTimer;
+ uint32 _timerEvent;
+};
+
+extern Neighborhood *g_neighborhood;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/norad/alpha/ecrmonitor.cpp b/engines/pegasus/neighborhood/norad/alpha/ecrmonitor.cpp
new file mode 100644
index 0000000000..e2a0267231
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/alpha/ecrmonitor.cpp
@@ -0,0 +1,219 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/pegasus.h"
+#include "pegasus/neighborhood/norad/constants.h"
+#include "pegasus/neighborhood/norad/norad.h"
+#include "pegasus/neighborhood/norad/alpha/ecrmonitor.h"
+
+namespace Pegasus {
+
+static const NotificationFlags kECRSection1FinishedFlag = 1;
+static const NotificationFlags kECRPanFinishedFlag = kECRSection1FinishedFlag << 1;
+static const NotificationFlags kECRSection2FinishedFlag = kECRPanFinishedFlag << 1;
+static const NotificationFlags kECRNotificationFlags = kECRSection1FinishedFlag |
+ kECRPanFinishedFlag |
+ kECRSection2FinishedFlag;
+
+static const TimeValue kSection1Start = 0;
+static const TimeValue kSection1Stop = 25;
+static const TimeValue kPanStart = 0;
+static const TimeValue kPanStop = 20;
+static const TimeValue kSection2Start = 26;
+static const TimeValue kSection2Stop = 1000;
+
+// Seems to be a good value for a 20 second pan.
+static const CoordType kPanPixelsPerFrame = 8;
+
+// Interesting times are in seconds.
+static const TimeValue s_ECRInterestingTimes[] = {
+ 0, 1, 2, 10, 25, 26, 56, 64, 72, 80, 88, 94, 102, 108, 116, 999
+};
+
+// Index into s_ECRInterestingTimes of interesting time before security pan.
+static const int kBeforePanTime = 3;
+
+// Index into s_ECRInterestingTimes of interesting time after security pan.
+static const int kAfterPanTime = 5;
+
+NoradAlphaECRMonitor::NoradAlphaECRMonitor(Neighborhood *nextHandler) : GameInteraction(kNoradECRMonitorInteractionID, nextHandler),
+ _ecrSlideShowNotification(kNoradECRNotificationID, (PegasusEngine *)g_engine), _ecrMovie(kECRSlideShowMovieID),
+ _ecrPan(kECRPanID) {
+}
+
+void NoradAlphaECRMonitor::receiveNotification(Notification *, const NotificationFlags flags) {
+ if (flags & kECRSection1FinishedFlag)
+ ecrSection1Finished();
+ else if (flags & kECRPanFinishedFlag)
+ ecrPanFinished();
+ else if (flags & kECRSection2FinishedFlag)
+ ecrSection2Finished();
+}
+
+int NoradAlphaECRMonitor::findCurrentInterestingTime() {
+ TimeValue time = _ecrMovie.getTime();
+ TimeScale scale = _ecrMovie.getScale();
+
+ for (int i = ARRAYSIZE(s_ECRInterestingTimes) - 1; i >= 0; i--)
+ if (time >= s_ECRInterestingTimes[i] * scale)
+ return i;
+
+ return 0;
+}
+
+void NoradAlphaECRMonitor::skipToNextInterestingTime() {
+ if (_ecrMovie.isRunning()) {
+ int interestingTime = findCurrentInterestingTime();
+ _ecrMovie.setTime(s_ECRInterestingTimes[interestingTime + 1] * _ecrMovie.getScale());
+ _ecrMovie.redrawMovieWorld();
+ } else if (_ecrPan.isRunning()) {
+ _ecrPanCallBack.cancelCallBack();
+ ecrPanFinished();
+ }
+}
+
+void NoradAlphaECRMonitor::skipToPreviousInterestingTime() {
+ if (_ecrPan.isRunning()) {
+ _ecrPan.stop();
+ _ecrPan.stopDisplaying();
+ _ecrPanCallBack.cancelCallBack();
+
+ _ecrMovieCallBack.setCallBackFlag(kECRSection1FinishedFlag);
+ _ecrMovieCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+
+ TimeScale scale = _ecrMovie.getScale();
+ _ecrMovie.setSegment(kSection1Start * scale, kSection1Stop * scale + 1);
+ _ecrMovie.setTime(s_ECRInterestingTimes[kBeforePanTime] * scale);
+ _ecrMovie.start();
+ } else {
+ int interestingTime = findCurrentInterestingTime();
+
+ if (interestingTime == kAfterPanTime) {
+ _ecrMovieCallBack.cancelCallBack();
+ TimeScale scale = _ecrMovie.getScale();
+ _ecrMovie.setSegment(kSection1Start * scale, kSection1Stop * scale + 1);
+ _ecrMovie.setTime(kSection1Stop * scale);
+ ecrSection1Finished();
+ } else if (interestingTime == 0) {
+ _ecrMovie.setTime(kSection1Start * _ecrMovie.getScale());
+ _ecrMovie.redrawMovieWorld();
+ } else {
+ _ecrMovie.setTime(s_ECRInterestingTimes[interestingTime - 1] * _ecrMovie.getScale());
+ _ecrMovie.redrawMovieWorld();
+ }
+ }
+}
+
+void NoradAlphaECRMonitor::handleInput(const Input &input, const Hotspot *cursorSpot) {
+ if (isInteracting()) {
+ if (input.rightButtonDown())
+ skipToNextInterestingTime();
+ else if (input.leftButtonDown())
+ skipToPreviousInterestingTime();
+ else
+ InputHandler::handleInput(input, cursorSpot);
+ } else {
+ InputHandler::handleInput(input, cursorSpot);
+ }
+}
+
+void NoradAlphaECRMonitor::ecrSection1Finished() {
+ _ecrMovie.stop();
+ _ecrPanCallBack.setNotification(&_ecrSlideShowNotification);
+ _ecrPanCallBack.initCallBack(&_ecrPan, kCallBackAtExtremes);
+ _ecrPanCallBack.setCallBackFlag(kECRPanFinishedFlag);
+ _ecrSlideShowNotification.notifyMe(this, kECRNotificationFlags, kECRNotificationFlags);
+ _ecrPanCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ _ecrPan.startDisplaying();
+ _ecrPan.show();
+
+ TimeScale scale = _ecrPan.getScale();
+ _ecrPan.setSegment(kPanStart * scale, kPanStop * scale);
+ _ecrPan.setTime(0);
+ _ecrPan.start();
+}
+
+void NoradAlphaECRMonitor::ecrPanFinished() {
+ _ecrPan.stop();
+ _ecrPan.stopDisplaying();
+ _ecrMovieCallBack.setCallBackFlag(kECRSection2FinishedFlag);
+ _ecrMovieCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+
+ TimeScale scale = _ecrMovie.getScale();
+ _ecrMovie.setSegment(kSection2Start * scale, kSection2Stop * scale);
+ _ecrMovie.start();
+}
+
+void NoradAlphaECRMonitor::ecrSection2Finished() {
+ _ecrMovie.stop();
+ _ecrMovie.stopDisplaying();
+}
+
+void NoradAlphaECRMonitor::openInteraction() {
+ // Initialize the security pan.
+ _ecrPan.initFromMovieFile("Images/Norad Alpha/Security Pan.pano");
+ _ecrPan.initMaskFromPICTFile("Images/Norad Alpha/Security Pan Mask");
+ _ecrPan.setBounds(Common::Rect(kECRPanLeft, kECRPanTop, kECRPanRight, kECRPanBottom));
+ _ecrPan.setDisplayOrder(kECRPanOrder);
+ _ecrPan.setScale(15); // 15 fps.
+
+ // Begin the lame ECR slide show.
+ // clone2727: I didn't say it :P
+ _ecrMovie.initFromMovieFile("Images/Norad Alpha/ECR Monitor Movie");
+
+ _ecrMovieCallBack.setNotification(&_ecrSlideShowNotification);
+ _ecrMovieCallBack.initCallBack(&_ecrMovie, kCallBackAtExtremes);
+ _ecrMovieCallBack.setCallBackFlag(kECRSection1FinishedFlag);
+
+ _ecrSlideShowNotification.notifyMe(this, kECRNotificationFlags, kECRNotificationFlags);
+ _ecrMovieCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+
+ _ecrMovie.moveElementTo(kECRSlideShowLeft, kECRSlideShowTop);
+ _ecrMovie.setDisplayOrder(kECRMonitorOrder);
+ _ecrMovie.startDisplaying();
+ _ecrMovie.show();
+ _ecrMovie.redrawMovieWorld();
+
+ TimeScale scale = _ecrMovie.getScale();
+ _ecrMovie.setSegment(kSection1Start * scale, kSection1Stop * scale + 1);
+
+ _ecrMovie.start();
+}
+
+void NoradAlphaECRMonitor::closeInteraction() {
+ _ecrMovieCallBack.releaseCallBack();
+ _ecrMovie.stop();
+ _ecrMovie.stopDisplaying();
+ _ecrMovie.releaseMovie();
+ _ecrMovieCallBack.releaseCallBack();
+
+ _ecrPanCallBack.releaseCallBack();
+ _ecrPan.stop();
+ _ecrPan.stopDisplaying();
+ _ecrPan.releasePanorama();
+ _ecrPanCallBack.releaseCallBack();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/norad/alpha/ecrmonitor.h b/engines/pegasus/neighborhood/norad/alpha/ecrmonitor.h
new file mode 100644
index 0000000000..9e286ed337
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/alpha/ecrmonitor.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_NORAD_ALPHA_ecrMONITOR_H
+#define PEGASUS_NEIGHBORHOOD_NORAD_ALPHA_ecrMONITOR_H
+
+#include "pegasus/interaction.h"
+#include "pegasus/notification.h"
+#include "pegasus/neighborhood/norad/alpha/panoramascroll.h"
+
+namespace Pegasus {
+
+class NoradAlphaECRMonitor : public GameInteraction, public NotificationReceiver {
+public:
+ NoradAlphaECRMonitor(Neighborhood *);
+ virtual ~NoradAlphaECRMonitor() {}
+
+ virtual void handleInput(const Input &, const Hotspot *);
+
+protected:
+ virtual void openInteraction();
+ virtual void closeInteraction();
+
+ virtual void receiveNotification(Notification *, const NotificationFlags);
+
+ void ecrSection1Finished();
+ void ecrPanFinished();
+ void ecrSection2Finished();
+
+ int findCurrentInterestingTime();
+ void skipToNextInterestingTime();
+ void skipToPreviousInterestingTime();
+
+ Notification _ecrSlideShowNotification;
+ Movie _ecrMovie;
+ NotificationCallBack _ecrMovieCallBack;
+ PanoramaScroll _ecrPan;
+ NotificationCallBack _ecrPanCallBack;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/norad/alpha/fillingstation.cpp b/engines/pegasus/neighborhood/norad/alpha/fillingstation.cpp
new file mode 100644
index 0000000000..169f75f7d2
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/alpha/fillingstation.cpp
@@ -0,0 +1,445 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/items/inventory/airmask.h"
+#include "pegasus/neighborhood/norad/constants.h"
+#include "pegasus/neighborhood/norad/alpha/fillingstation.h"
+#include "pegasus/neighborhood/norad/alpha/noradalpha.h"
+
+namespace Pegasus {
+
+static const NotificationFlags kFSPowerUpFinishedFlag = 1;
+static const NotificationFlags kFSSplashFinishedFlag = kFSPowerUpFinishedFlag << 1;
+static const NotificationFlags kFSIntakeWarningFinishedFlag = kFSSplashFinishedFlag << 1;
+static const NotificationFlags kFSIntakeHiliteFinishedFlag = kFSIntakeWarningFinishedFlag << 1;
+static const NotificationFlags kFSDispenseHiliteFinishedFlag = kFSIntakeHiliteFinishedFlag << 1;
+static const NotificationFlags kFSArHiliteFinishedFlag = kFSDispenseHiliteFinishedFlag << 1;
+static const NotificationFlags kFSCO2HiliteFinishedFlag = kFSArHiliteFinishedFlag << 1;
+static const NotificationFlags kFSHeHiliteFinishedFlag = kFSCO2HiliteFinishedFlag << 1;
+static const NotificationFlags kFSOHiliteFinishedFlag = kFSHeHiliteFinishedFlag << 1;
+static const NotificationFlags kFSNHiliteFinishedFlag = kFSOHiliteFinishedFlag << 1;
+
+static const NotificationFlags kFSNotificationFlags = kFSPowerUpFinishedFlag |
+ kFSSplashFinishedFlag |
+ kFSIntakeWarningFinishedFlag |
+ kFSIntakeHiliteFinishedFlag |
+ kFSDispenseHiliteFinishedFlag |
+ kFSArHiliteFinishedFlag |
+ kFSCO2HiliteFinishedFlag |
+ kFSHeHiliteFinishedFlag |
+ kFSOHiliteFinishedFlag |
+ kFSNHiliteFinishedFlag;
+
+static const int16 kNoState = 0;
+static const int16 kMainMenu = 1;
+static const int16 kWaitingForAttach = 2;
+static const int16 kDispenseMenu = 3;
+static const int16 kWaitingForDispense = 4;
+
+// Dummy itemIDs
+static const ItemID kCO2Item = 10000;
+static const ItemID kHeItem = 10001;
+
+// Interactive points.
+static const TimeValue kFSPowerUpStartStart = 0;
+static const TimeValue kFSPowerUpStartStop = 600;
+static const TimeValue kFSSplashStart = 600;
+static const TimeValue kFSSplashStop = 7800;
+static const TimeValue kFSSplashIntakeStart = 7800;
+static const TimeValue kFSSplashIntakeStop = 18600;
+
+static const TimeValue kFSMainMenu = 18600;
+static const TimeValue kFSIntakeHiliteStart = 19200;
+static const TimeValue kFSIntakeHiliteStop = 19800;
+static const TimeValue kFSDispenseHiliteStart = 19800;
+static const TimeValue kFSDispenseHiliteStop = 20400;
+
+static const TimeValue kFSDispenseMenu = 20400;
+
+static const TimeValue kFSArHiliteStart = 21000;
+static const TimeValue kFSArHiliteStop = 21600;
+static const TimeValue kFSArAttach = 21600;
+static const TimeValue kFSArFilledStart = 22200;
+static const TimeValue kFSArFilledStop = 25200;
+static const TimeValue kFSArIncompatibleStart = 25200;
+static const TimeValue kFSArIncompatibleStop = 30000;
+
+static const TimeValue kFSCO2HiliteStart = 30000;
+static const TimeValue kFSCO2HiliteStop = 30600;
+static const TimeValue kFSCO2Attach = 30600;
+static const TimeValue kFSCO2FilledStart = 31200;
+static const TimeValue kFSCO2FilledStop = 34200;
+static const TimeValue kFSCO2IncompatibleStart = 34200;
+static const TimeValue kFSCO2IncompatibleStop = 39000;
+
+static const TimeValue kFSHeHiliteStart = 39000;
+static const TimeValue kFSHeHiliteStop = 39600;
+static const TimeValue kFSHeAttach = 39600;
+static const TimeValue kFSHeFilledStart = 40200;
+static const TimeValue kFSHeFilledStop = 43200;
+static const TimeValue kFSHeIncompatibleStart = 43200;
+static const TimeValue kFSHeIncompatibleStop = 48000;
+
+static const TimeValue kFSOHiliteStart = 48000;
+static const TimeValue kFSOHiliteStop = 48600;
+static const TimeValue kFSOAttach = 48600;
+static const TimeValue kFSOFilledStart = 49200;
+static const TimeValue kFSOFilledStop = 52200;
+static const TimeValue kFSOIncompatibleStart = 52200;
+static const TimeValue kFSOIncompatibleStop = 57000;
+
+static const TimeValue kFSNHiliteStart = 57000;
+static const TimeValue kFSNHiliteStop = 57600;
+static const TimeValue kFSNAttach = 57600;
+static const TimeValue kFSNFilledStart = 58200;
+static const TimeValue kFSNFilledStop = 61200;
+static const TimeValue kFSNIncompatibleStart = 61200;
+static const TimeValue kFSNIncompatibleStop = 66000;
+
+static const TimeValue kFSIntakeMenu = 66000;
+static const TimeValue kFSIntakeInProgressStart = 66600;
+static const TimeValue kFSIntakeInProgressStop = 69600;
+
+NoradAlphaFillingStation::NoradAlphaFillingStation(Neighborhood *owner) : GameInteraction(kNoradFillingStationInteractionID, owner),
+ _rightSideMovie(kN01RightSideID), _rightSideNotification(kNoradFillingStationNotificationID, ((PegasusEngine *)g_engine)) {
+ _state = kNoState;
+}
+
+void NoradAlphaFillingStation::openInteraction() {
+ _rightSideMovie.initFromMovieFile("Images/Norad Alpha/N01W Right Side");
+ _rightSideMovie.moveElementTo(kNoradAlpha01RightSideLeft, kNoradAlpha01RightSideTop);
+ _rightSideMovie.setDisplayOrder(kN01RightSideOrder);
+ _rightSideMovie.startDisplaying();
+ _rightSideCallBack.setNotification(&_rightSideNotification);
+ _rightSideCallBack.initCallBack(&_rightSideMovie, kCallBackAtExtremes);
+ _rightSideCallBack.setCallBackFlag(kFSPowerUpFinishedFlag);
+ _rightSideNotification.notifyMe(this, kFSNotificationFlags, kFSNotificationFlags);
+ _rightSideCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ _rightSideMovie.show();
+ _rightSideMovie.redrawMovieWorld();
+ _rightSideMovie.setSegment(kFSPowerUpStartStart, kFSPowerUpStartStop);
+}
+
+void NoradAlphaFillingStation::initInteraction() {
+ allowInput(false);
+
+ _rightSideMovie.setRate(2);
+}
+
+void NoradAlphaFillingStation::closeInteraction() {
+ _rightSideMovie.stop();
+ _rightSideMovie.stopDisplaying();
+ _rightSideMovie.releaseMovie();
+ _rightSideCallBack.releaseCallBack();
+ ((NoradAlpha *)getOwner())->turnOffFillingStation();
+}
+
+void NoradAlphaFillingStation::setStaticState(TimeValue time, int16 state) {
+ _rightSideMovie.stop();
+ _rightSideMovie.setSegment(0, _rightSideMovie.getDuration());
+ _rightSideMovie.setTime(time);
+ _rightSideMovie.redrawMovieWorld();
+ _state = state;
+ allowInput(true);
+}
+
+void NoradAlphaFillingStation::setSegmentState(TimeValue start, TimeValue stop, NotificationFlags flag, int16 state) {
+ _rightSideMovie.stop();
+ _rightSideMovie.setSegment(start, stop);
+ _rightSideMovie.setTime(start);
+ _rightSideCallBack.setCallBackFlag(flag);
+ _rightSideCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ _state = state;
+ allowInput(false);
+ _rightSideMovie.setRate(2);
+}
+
+void NoradAlphaFillingStation::powerUpFinished() {
+ ((NoradAlpha *)getOwner())->turnOnFillingStation();
+ setSegmentState(kFSSplashStart, kFSSplashStop, kFSSplashFinishedFlag, kNoState);
+}
+
+void NoradAlphaFillingStation::splashFinished() {
+ if (GameState.getNoradGassed())
+ setSegmentState(kFSSplashIntakeStart, kFSSplashIntakeStop, kFSIntakeWarningFinishedFlag, kNoState);
+ else
+ intakeWarningFinished();
+}
+
+void NoradAlphaFillingStation::intakeWarningFinished() {
+ setStaticState(kFSMainMenu, kMainMenu);
+}
+
+void NoradAlphaFillingStation::showIntakeInProgress(uint16 numSeconds) {
+ if (numSeconds == 0) {
+ setSegmentState(kFSIntakeInProgressStart, kFSIntakeInProgressStop, kFSIntakeWarningFinishedFlag, kNoState);
+ Item *item = ((NoradAlpha *)getOwner())->getFillingItem();
+
+ if (item->getObjectID() == kGasCanister) {
+ GameState.setNoradGassed(true);
+ ((NoradAlpha *)getOwner())->loadAmbientLoops();
+ getOwner()->restoreStriding(kNorad03, kEast, kAltNoradAlphaNormal);
+ }
+ } else {
+ setSegmentState(kFSIntakeInProgressStart, kFSIntakeInProgressStart + _rightSideMovie.getScale() * numSeconds,
+ kFSIntakeWarningFinishedFlag, kNoState);
+ }
+}
+
+void NoradAlphaFillingStation::intakeHighlightFinished() {
+ _rightSideMovie.stop();
+
+ if (GameState.getNoradGassed()) {
+ showIntakeInProgress(2);
+ } else {
+ Item *item = ((NoradAlpha *)getOwner())->getFillingItem();
+ if (item)
+ showIntakeInProgress(0);
+ else
+ setStaticState(kFSIntakeMenu, kWaitingForAttach);
+ }
+}
+
+void NoradAlphaFillingStation::dispenseHighlightFinished() {
+ setStaticState(kFSDispenseMenu, kDispenseMenu);
+}
+
+void NoradAlphaFillingStation::dispenseGas() {
+ Item *item = ((NoradAlpha *)getOwner())->getFillingItem();
+
+ if (item) {
+ if (item->getObjectID() != _dispenseItemID)
+ switch (_dispenseItemID) {
+ case kArgonCanister:
+ setSegmentState(kFSArIncompatibleStart, kFSArIncompatibleStop,
+ kFSIntakeWarningFinishedFlag, kNoState);
+ break;
+ case kCO2Item:
+ setSegmentState(kFSCO2IncompatibleStart, kFSCO2IncompatibleStop,
+ kFSIntakeWarningFinishedFlag, kNoState);
+ break;
+ case kHeItem:
+ setSegmentState(kFSHeIncompatibleStart, kFSHeIncompatibleStop,
+ kFSIntakeWarningFinishedFlag, kNoState);
+ break;
+ case kAirMask:
+ setSegmentState(kFSOIncompatibleStart, kFSOIncompatibleStop,
+ kFSIntakeWarningFinishedFlag, kNoState);
+ break;
+ case kNitrogenCanister:
+ setSegmentState(kFSNIncompatibleStart, kFSNIncompatibleStop,
+ kFSIntakeWarningFinishedFlag, kNoState);
+ break;
+ }
+ else {
+ if (_dispenseItemID == kArgonCanister) {
+ setSegmentState(kFSArFilledStart, kFSArFilledStop, kFSIntakeWarningFinishedFlag, kNoState);
+ item->setItemState(kArgonFull);
+ GameState.setScoringFilledArgonCanister(true);
+ } else if (_dispenseItemID == kAirMask) {
+ setSegmentState(kFSOFilledStart, kFSOFilledStop, kFSIntakeWarningFinishedFlag, kNoState);
+ ((AirMask *)item)->refillAirMask();
+ GameState.setScoringFilledOxygenCanister(true);
+ } else if (_dispenseItemID == kNitrogenCanister) {
+ setSegmentState(kFSNFilledStart, kFSNFilledStop, kFSIntakeWarningFinishedFlag, kNoState);
+ item->setItemState(kNitrogenFull);
+ }
+ }
+ } else {
+ switch (_dispenseItemID) {
+ case kArgonCanister:
+ setStaticState(kFSArAttach, kWaitingForDispense);
+ break;
+ case kCO2Item:
+ setStaticState(kFSCO2Attach, kWaitingForDispense);
+ break;
+ case kHeItem:
+ setStaticState(kFSHeAttach, kWaitingForDispense);
+ break;
+ case kAirMask:
+ setStaticState(kFSOAttach, kWaitingForDispense);
+ break;
+ case kNitrogenCanister:
+ setStaticState(kFSNAttach, kWaitingForDispense);
+ break;
+ }
+ }
+}
+
+void NoradAlphaFillingStation::ArHighlightFinished() {
+ _dispenseItemID = kArgonCanister;
+ dispenseGas();
+}
+
+void NoradAlphaFillingStation::CO2HighlightFinished() {
+ _dispenseItemID = kCO2Item;
+ dispenseGas();
+}
+
+void NoradAlphaFillingStation::HeHighlightFinished() {
+ _dispenseItemID = kHeItem;
+ dispenseGas();
+}
+
+void NoradAlphaFillingStation::OHighlightFinished() {
+ _dispenseItemID = kAirMask;
+ dispenseGas();
+}
+
+void NoradAlphaFillingStation::NHighlightFinished() {
+ _dispenseItemID = kNitrogenCanister;
+ dispenseGas();
+}
+
+void NoradAlphaFillingStation::receiveNotification(Notification *, const NotificationFlags flags) {
+ switch (flags) {
+ case kFSPowerUpFinishedFlag:
+ powerUpFinished();
+ break;
+ case kFSSplashFinishedFlag:
+ splashFinished();
+ break;
+ case kFSIntakeWarningFinishedFlag:
+ intakeWarningFinished();
+ break;
+ case kFSIntakeHiliteFinishedFlag:
+ intakeHighlightFinished();
+ break;
+ case kFSDispenseHiliteFinishedFlag:
+ dispenseHighlightFinished();
+ break;
+ case kFSArHiliteFinishedFlag:
+ ArHighlightFinished();
+ break;
+ case kFSCO2HiliteFinishedFlag:
+ CO2HighlightFinished();
+ break;
+ case kFSHeHiliteFinishedFlag:
+ HeHighlightFinished();
+ break;
+ case kFSOHiliteFinishedFlag:
+ OHighlightFinished();
+ break;
+ case kFSNHiliteFinishedFlag:
+ NHighlightFinished();
+ break;
+ }
+}
+
+void NoradAlphaFillingStation::handleInput(const Input &input, const Hotspot *cursorSpot) {
+ InputHandler::handleInput(input, cursorSpot);
+}
+
+void NoradAlphaFillingStation::clickInIntake() {
+ setSegmentState(kFSIntakeHiliteStart, kFSIntakeHiliteStop, kFSIntakeHiliteFinishedFlag, kNoState);
+}
+
+void NoradAlphaFillingStation::clickInDispense() {
+ setSegmentState(kFSDispenseHiliteStart, kFSDispenseHiliteStop, kFSDispenseHiliteFinishedFlag, kNoState);
+}
+
+void NoradAlphaFillingStation::clickInAr() {
+ setSegmentState(kFSArHiliteStart, kFSArHiliteStop, kFSArHiliteFinishedFlag, kNoState);
+}
+
+void NoradAlphaFillingStation::clickInCO2() {
+ setSegmentState(kFSCO2HiliteStart, kFSCO2HiliteStop, kFSCO2HiliteFinishedFlag, kNoState);
+}
+
+void NoradAlphaFillingStation::clickInHe() {
+ setSegmentState(kFSHeHiliteStart, kFSHeHiliteStop, kFSHeHiliteFinishedFlag, kNoState);
+}
+
+void NoradAlphaFillingStation::clickInO() {
+ setSegmentState(kFSOHiliteStart, kFSOHiliteStop, kFSOHiliteFinishedFlag, kNoState);
+}
+
+void NoradAlphaFillingStation::clickInN() {
+ setSegmentState(kFSNHiliteStart, kFSNHiliteStop, kFSNHiliteFinishedFlag, kNoState);
+}
+
+void NoradAlphaFillingStation::clickInHotspot(const Input &input, const Hotspot *spot) {
+ GameInteraction::clickInHotspot(input, spot);
+
+ switch (spot->getObjectID()) {
+ case kNorad01IntakeSpotID:
+ clickInIntake();
+ break;
+ case kNorad01DispenseSpotID:
+ clickInDispense();
+ break;
+ case kNorad01ArSpotID:
+ clickInAr();
+ break;
+ case kNorad01CO2SpotID:
+ clickInCO2();
+ break;
+ case kNorad01HeSpotID:
+ clickInHe();
+ break;
+ case kNorad01OSpotID:
+ clickInO();
+ break;
+ case kNorad01NSpotID:
+ clickInN();
+ break;
+ }
+}
+
+void NoradAlphaFillingStation::activateHotspots() {
+ GameInteraction::activateHotspots();
+
+ switch (_state) {
+ case kMainMenu:
+ g_allHotspots.activateOneHotspot(kNorad01IntakeSpotID);
+ g_allHotspots.activateOneHotspot(kNorad01DispenseSpotID);
+ break;
+ case kDispenseMenu:
+ g_allHotspots.activateOneHotspot(kNorad01ArSpotID);
+ g_allHotspots.activateOneHotspot(kNorad01CO2SpotID);
+ g_allHotspots.activateOneHotspot(kNorad01HeSpotID);
+ g_allHotspots.activateOneHotspot(kNorad01OSpotID);
+ g_allHotspots.activateOneHotspot(kNorad01NSpotID);
+ break;
+ }
+}
+
+void NoradAlphaFillingStation::newFillingItem(Item *item) {
+ switch (_state) {
+ case kWaitingForAttach:
+ if (item)
+ showIntakeInProgress(0);
+ break;
+ case kWaitingForDispense:
+ dispenseGas();
+ break;
+ default:
+ break;
+ }
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/norad/alpha/fillingstation.h b/engines/pegasus/neighborhood/norad/alpha/fillingstation.h
new file mode 100644
index 0000000000..eb2088e373
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/alpha/fillingstation.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_NORAD_ALPHA_FILLINGSTATION_H
+#define PEGASUS_NEIGHBORHOOD_NORAD_ALPHA_FILLINGSTATION_H
+
+#include "pegasus/interaction.h"
+#include "pegasus/movie.h"
+#include "pegasus/notification.h"
+
+namespace Pegasus {
+
+class Item;
+
+class NoradAlphaFillingStation : public GameInteraction, public NotificationReceiver {
+public:
+ NoradAlphaFillingStation(Neighborhood *);
+ virtual ~NoradAlphaFillingStation() {}
+
+ virtual void handleInput(const Input &, const Hotspot *);
+
+ virtual void clickInHotspot(const Input &, const Hotspot *);
+ virtual void activateHotspots();
+
+ void newFillingItem(Item *);
+
+protected:
+ void receiveNotification(Notification *, const NotificationFlags);
+
+ virtual void openInteraction();
+ virtual void initInteraction();
+ virtual void closeInteraction();
+
+ void powerUpFinished();
+ void splashFinished();
+ void intakeWarningFinished();
+ void intakeHighlightFinished();
+ void dispenseHighlightFinished();
+ void ArHighlightFinished();
+ void CO2HighlightFinished();
+ void HeHighlightFinished();
+ void OHighlightFinished();
+ void NHighlightFinished();
+
+ void showIntakeInProgress(uint16);
+
+ void clickInIntake();
+ void clickInDispense();
+ void clickInAr();
+ void clickInCO2();
+ void clickInHe();
+ void clickInO();
+ void clickInN();
+
+ void dispenseGas();
+
+ void setStaticState(TimeValue, int16);
+ void setSegmentState(TimeValue, TimeValue, NotificationFlags, int16);
+
+ Movie _rightSideMovie;
+ Notification _rightSideNotification;
+ NotificationCallBack _rightSideCallBack;
+ int16 _state;
+ ItemID _dispenseItemID;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/norad/alpha/noradalpha.cpp b/engines/pegasus/neighborhood/norad/alpha/noradalpha.cpp
new file mode 100644
index 0000000000..e4a5e26473
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/alpha/noradalpha.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/energymonitor.h"
+#include "pegasus/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/inventory/airmask.h"
+#include "pegasus/neighborhood/norad/constants.h"
+#include "pegasus/neighborhood/norad/subcontrolroom.h"
+#include "pegasus/neighborhood/norad/alpha/ecrmonitor.h"
+#include "pegasus/neighborhood/norad/alpha/fillingstation.h"
+#include "pegasus/neighborhood/norad/alpha/noradalpha.h"
+
+namespace Pegasus {
+
+const uint32 NoradAlpha::_noradAlphaClawExtras[22] = {
+ kN22ClawFromAToB,
+ kN22ClawALoop,
+ kN22ClawAPinch,
+ kN22ClawACounterclockwise,
+ kN22ClawAClockwise,
+ kN22ClawFromBToA,
+ kN22ClawFromBToC,
+ kN22ClawFromBToD,
+ kN22ClawBLoop,
+ kN22ClawBPinch,
+ kN22ClawBCounterclockwise,
+ kN22ClawBClockwise,
+ kN22ClawFromCToB,
+ kN22ClawCLoop,
+ kN22ClawCPinch,
+ kN22ClawCCounterclockwise,
+ kN22ClawCClockwise,
+ kN22ClawFromDToB,
+ kN22ClawDLoop,
+ kN22ClawDPinch,
+ kN22ClawDCounterclockwise,
+ kN22ClawDClockwise
+};
+
+NoradAlpha::NoradAlpha(InputHandler *nextHandler, PegasusEngine *owner) : Norad(nextHandler, owner, "Norad Alpha", kNoradAlphaID) {
+ _elevatorUpRoomID = kNorad11South;
+ _elevatorDownRoomID = kNorad12South;
+ _elevatorUpSpotID = kNorad12ElevatorUpSpotID;
+ _elevatorDownSpotID = kNorad11ElevatorDownSpotID;
+
+ _subRoomEntryRoom1 = kNorad10;
+ _subRoomEntryDir1 = kEast;
+ _subRoomEntryRoom2 = kNorad21;
+ _subRoomEntryDir2 = kWest;
+ _upperPressureDoorRoom = kNorad10East;
+ _lowerPressureDoorRoom = kNorad21West;
+
+ _upperPressureDoorUpSpotID = kAlphaUpperPressureDoorUpSpotID;
+ _upperPressureDoorDownSpotID = kAlphaUpperPressureDoorDownSpotID;
+ _upperPressureDoorAbortSpotID = kNorad10EastOutSpotID;
+
+ _lowerPressureDoorUpSpotID = kAlphaLowerPressureDoorUpSpotID;
+ _lowerPressureDoorDownSpotID = kAlphaLowerPressureDoorDownSpotID;
+ _lowerPressureDoorAbortSpotID = kNorad21WestOutSpotID;
+
+ _pressureSoundIn = kPressureDoorIntro1In;
+ _pressureSoundOut = kPressureDoorIntro1Out;
+ _equalizeSoundIn = kPressureDoorIntro2In;
+ _equalizeSoundOut = kPressureDoorIntro2Out;
+ _accessDeniedIn = kAlphaAccessDeniedIn;
+ _accessDeniedOut = kAlphaAccessDeniedOut;
+
+ _platformRoom = kNorad19West;
+ _subControlRoom = kNorad22West;
+
+ _subPrepFailed = false;
+
+ setIsItemTaken(kGasCanister);
+}
+
+void NoradAlpha::init() {
+ Norad::init();
+
+ Hotspot *hotspot = _vm->getAllHotspots().findHotspotByID(kN01GasCanisterSpotID);
+ hotspot->setMaskedHotspotFlags(kPickUpItemSpotFlag, kPickUpItemSpotFlag);
+ HotspotInfoTable::Entry *hotspotEntry = findHotspotEntry(kN01GasCanisterSpotID);
+ hotspotEntry->hotspotItem = kGasCanister;
+
+ hotspot = _vm->getAllHotspots().findHotspotByID(kN01ArgonCanisterSpotID);
+ hotspot->setMaskedHotspotFlags(kPickUpItemSpotFlag, kPickUpItemSpotFlag);
+ hotspotEntry = findHotspotEntry(kN01ArgonCanisterSpotID);
+ hotspotEntry->hotspotItem = kArgonCanister;
+
+ hotspot = _vm->getAllHotspots().findHotspotByID(kN01NitrogenCanisterSpotID);
+ hotspot->setMaskedHotspotFlags(kPickUpItemSpotFlag, kPickUpItemSpotFlag);
+ hotspotEntry = findHotspotEntry(kN01NitrogenCanisterSpotID);
+ hotspotEntry->hotspotItem = kNitrogenCanister;
+
+ hotspot = _vm->getAllHotspots().findHotspotByID(kN01AirMaskSpotID);
+ hotspot->setMaskedHotspotFlags(kPickUpItemSpotFlag, kPickUpItemSpotFlag);
+ hotspotEntry = findHotspotEntry(kN01AirMaskSpotID);
+ hotspotEntry->hotspotItem = kAirMask;
+
+ hotspot = _vm->getAllHotspots().findHotspotByID(kN01GasOutletSpotID);
+ hotspot->setMaskedHotspotFlags(kDropItemSpotFlag, kDropItemSpotFlag);
+}
+
+void NoradAlpha::start() {
+ if (g_energyMonitor) {
+ g_energyMonitor->stopEnergyDraining();
+ g_energyMonitor->restoreLastEnergyValue();
+ _vm->resetEnergyDeathReason();
+ g_energyMonitor->startEnergyDraining();
+ }
+
+ NeighborhoodID itemNeighborhood;
+ RoomID itemRoom;
+ DirectionConstant itemDirection;
+
+ Item *item = (Item *)_vm->getAllItems().findItemByID(kGasCanister);
+ item->getItemRoom(itemNeighborhood, itemRoom, itemDirection);
+
+ if (itemNeighborhood == getObjectID()) {
+ _fillingStationItem = item;
+ } else {
+ item = (Item *)_vm->getAllItems().findItemByID(kAirMask);
+ item->getItemRoom(itemNeighborhood, itemRoom, itemDirection);
+
+ if (itemNeighborhood == getObjectID()) {
+ _fillingStationItem = item;
+ } else {
+ item = (Item *)_vm->getAllItems().findItemByID(kNitrogenCanister);
+ item->getItemRoom(itemNeighborhood, itemRoom, itemDirection);
+
+ if (itemNeighborhood == getObjectID()) {
+ _fillingStationItem = item;
+ } else {
+ item = (Item *)_vm->getAllItems().findItemByID(kArgonCanister);
+ item->getItemRoom(itemNeighborhood, itemRoom, itemDirection);
+ if (itemNeighborhood == getObjectID())
+ _fillingStationItem = item;
+ else
+ _fillingStationItem = 0;
+ }
+ }
+ }
+
+ if (!GameState.getNoradGassed())
+ forceStridingStop(kNorad03, kEast, kAltNoradAlphaNormal);
+
+ GameState.setNoradArrivedFromSub(false);
+ Norad::start();
+}
+
+void NoradAlpha::setUpAIRules() {
+ Neighborhood::setUpAIRules();
+
+ if (g_AIArea) {
+ AIPlayMessageAction *messageAction = new AIPlayMessageAction("Images/AI/Norad/XN01WD1", false);
+ AIHasItemCondition *hasGasCanisterCondition = new AIHasItemCondition(kGasCanister);
+ AIRule *rule = new AIRule(hasGasCanisterCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+ }
+}
+
+bool NoradAlpha::okayToJump() {
+ bool result = Neighborhood::okayToJump();
+
+ if (!result)
+ playSpotSoundSync(kAlphaCantTransportIn, kAlphaCantTransportOut);
+
+ return result;
+}
+
+void NoradAlpha::getExtraCompassMove(const ExtraTable::Entry &entry, FaderMoveSpec &compassMove) {
+ if (entry.extra == kNorad19ExitToSub) {
+ compassMove.makeTwoKnotFaderSpec(kNoradAlphaMovieScale, entry.movieStart, 270 + kSubPlatformCompassAngle,
+ entry.movieEnd, 90 + 20 + 360);
+ compassMove.insertFaderKnot(entry.movieStart + 10 * kNoradAlphaFrameDuration, 270 + kSubPlatformCompassAngle);
+ compassMove.insertFaderKnot(entry.movieStart + 29 * kNoradAlphaFrameDuration, 270 + kSubPlatformCompassAngle + 20);
+ compassMove.insertFaderKnot(entry.movieStart + 52 * kNoradAlphaFrameDuration, 270 + kSubPlatformCompassAngle + 20);
+ compassMove.insertFaderKnot(entry.movieStart + 84 * kNoradAlphaFrameDuration, 360 + 90);
+ compassMove.insertFaderKnot(entry.movieStart + 198 * kNoradAlphaFrameDuration, 360 + 90);
+ compassMove.insertFaderKnot(entry.movieStart + 270 * kNoradAlphaFrameDuration, 360 + 90 + 15);
+ compassMove.insertFaderKnot(entry.movieStart + 280 * kNoradAlphaFrameDuration, 360 + 90 + 20);
+ } else {
+ Norad::getExtraCompassMove(entry, compassMove);
+ }
+}
+
+void NoradAlpha::playClawMonitorIntro() {
+ playSpotSoundSync(kLoadClawIntroIn, kLoadClawIntroOut);
+}
+
+GameInteraction *NoradAlpha::makeInteraction(const InteractionID interactionID) {
+ switch (interactionID) {
+ case kNoradECRMonitorInteractionID:
+ return new NoradAlphaECRMonitor(this);
+ case kNoradFillingStationInteractionID:
+ return new NoradAlphaFillingStation(this);
+ }
+
+ return Norad::makeInteraction(interactionID);
+}
+
+void NoradAlpha::loadAmbientLoops() {
+ // clone2727 would like to point out that the following comment does not quite
+ // match the code logic below
+
+/*
+ Logic:
+
+ loop sound 1:
+ if gassed,
+ play warning loop of some sort
+ else
+ play nothing
+ loop sound 2:
+ if gassed and not wearing air mask
+ if in ECR
+ play breathing water loop
+ else
+ play breathing
+ else
+ if in ECR
+ play water loop
+ if at N07 north
+ play unmanned loop
+*/
+
+ if (!GameState.getNoradSeenTimeStream())
+ return;
+
+ RoomID room = GameState.getCurrentRoom();
+ if (GameState.getNoradGassed()) {
+ if (room >= kNorad11 && room <= kNorad19West)
+ loadLoopSound1("Sounds/Norad/NEW SUB AMB.22K.AIFF", kNoradWarningVolume * 3);
+ else if (room >= kNorad21 && room <= kNorad22West)
+ loadLoopSound1("Sounds/Norad/SUB CONTRL LOOP.22K.AIFF", kNoradWarningVolume * 3);
+ else
+ loadLoopSound1("Sounds/Norad/WARNING LOOP.22K.AIFF", kNoradWarningVolume);
+ } else {
+ loadLoopSound1("");
+ }
+
+ if (GameState.getNoradGassed() && !g_airMask->isAirFilterOn()) {
+ if (room >= kNorad01 && room <= kNorad01West) {
+ loadLoopSound2("Sounds/Norad/Breathing Water.22K.AIFF", kNoradSuckWindVolume);
+ } else if (room == kNorad02) {
+ if (GameState.isCurrentDoorOpen())
+ loadLoopSound2("Sounds/Norad/Breathing Water.22K.AIFF", kNoradSuckWindVolume);
+ else
+ loadLoopSound2("Sounds/Norad/SUCKING WIND.22K.AIFF", kNoradSuckWindVolume, 0, 0);
+ } else {
+ loadLoopSound2("Sounds/Norad/SUCKING WIND.22K.AIFF", kNoradSuckWindVolume, 0, 0);
+ }
+ } else {
+ if (room >= kNorad01 && room <= kNorad01West) {
+ loadLoopSound2("Sounds/Norad/WATER FLOWING.AIFF", 0x100 / 2);
+ } else if (room == kNorad02) {
+ if (GameState.isCurrentDoorOpen())
+ loadLoopSound2("Sounds/Norad/WATER FLOWING.AIFF", 0x100 / 2);
+ else
+ loadLoopSound2("");
+ } else {
+ loadLoopSound2("");
+ }
+ }
+
+}
+
+void NoradAlpha::checkContinuePoint(const RoomID room, const DirectionConstant direction) {
+ switch (MakeRoomView(room, direction)) {
+ case MakeRoomView(kNorad02, kEast):
+ case MakeRoomView(kNorad06, kEast):
+ case MakeRoomView(kNorad11, kEast):
+ case MakeRoomView(kNorad15, kEast):
+ case MakeRoomView(kNorad19, kWest):
+ case MakeRoomView(kNorad21, kSouth):
+ makeContinuePoint();
+ break;
+ }
+}
+
+void NoradAlpha::arriveAt(const RoomID room, const DirectionConstant direction) {
+ Norad::arriveAt(room, direction);
+
+ switch (GameState.getCurrentRoom()) {
+ case kNorad01:
+ arriveAtNorad01();
+ break;
+ case kNorad01East:
+ arriveAtNorad01East();
+ break;
+ case kNorad01West:
+ arriveAtNorad01West();
+ break;
+ case kNorad04:
+ arriveAtNorad04();
+ break;
+ case kNorad07North:
+ GameState.setScoringSawUnconsciousOperator(true);
+ break;
+ case kNorad11:
+ GameState.setScoringWentThroughPressureDoor(true);
+ break;
+ case kNorad22:
+ arriveAtNorad22();
+ break;
+ }
+}
+
+void NoradAlpha::arriveAtNorad01() {
+ if (!GameState.getNoradSeenTimeStream() && GameState.getCurrentDirection() == kSouth) {
+ GameState.setNoradN22MessagePlayed(false);
+ requestExtraSequence(kNoradArriveFromTSA, kExtraCompletedFlag, kFilterNoInput);
+ // You are no match for me, human.
+ requestExtraSequence(kNorad01RobotTaunt, kExtraCompletedFlag, kFilterNoInput);
+ }
+}
+
+void NoradAlpha::arriveAtNorad01East() {
+ GameState.setScoringSawSecurityMonitor(true);
+ newInteraction(kNoradECRMonitorInteractionID);
+}
+
+void NoradAlpha::arriveAtNorad01West() {
+ newInteraction(kNoradFillingStationInteractionID);
+}
+
+void NoradAlpha::arriveAtNorad04() {
+ if (GameState.getCurrentDirection() == kEast && !GameState.getNoradGassed())
+ playDeathExtra(kNorad04EastDeath, kDeathWokeUpNorad);
+}
+
+void NoradAlpha::arriveAtNorad22() {
+ if (!GameState.getNoradN22MessagePlayed() && GameState.getCurrentDirection() == kSouth) {
+ startExtraSequence(kNorad22SouthIntro, kExtraCompletedFlag, kFilterNoInput);
+ GameState.setNoradN22MessagePlayed(true);
+ }
+}
+
+void NoradAlpha::bumpIntoWall() {
+ requestSpotSound(kAlphaBumpIntoWallIn, kAlphaBumpIntoWallOut, kFilterNoInput, 0);
+ Neighborhood::bumpIntoWall();
+}
+
+void NoradAlpha::receiveNotification(Notification *notification, const NotificationFlags flags) {
+ if ((flags & kExtraCompletedFlag) != 0) {
+ switch (_lastExtra) {
+ case kNoradArriveFromTSA:
+ GameState.setNoradSeenTimeStream(true);
+ loadAmbientLoops();
+ break;
+ case kNorad01RobotTaunt:
+ g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/Norad/XN01SB", false, kWarningInterruption);
+ _interruptionFilter = kFilterAllInput;
+ makeContinuePoint();
+ break;
+ }
+ }
+
+ Norad::receiveNotification(notification, flags);
+
+ if ((flags & kExtraCompletedFlag) != 0) {
+ switch (_lastExtra) {
+ case kNorad22SouthIntro:
+ loopExtraSequence(kNorad22SouthReply);
+ playSpotSoundSync(kN22ReplyIn, kN22ReplyOut);
+ startExtraSequence(kNorad22SouthFinish, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kNorad22SouthFinish:
+ _interruptionFilter = kFilterAllInput;
+ // Force ArriveAt to do its thing...
+ GameState.setCurrentRoom(kNorad21);
+ arriveAt(kNorad22, kSouth);
+ break;
+ }
+ }
+
+ g_AIArea->checkMiddleArea();
+}
+
+void NoradAlpha::getZoomEntry(const HotSpotID spotID, ZoomTable::Entry &entry) {
+ Norad::getZoomEntry(spotID, entry);
+
+ ExtraTable::Entry extra;
+
+ if (spotID == kNorad01GasSpotID) {
+ if (_fillingStationItem) {
+ if (_fillingStationItem->getObjectID() == kGasCanister) {
+ getExtraEntry(kNorad01ZoomInWithGasCanister, extra);
+ entry.movieStart = extra.movieStart;
+ entry.movieEnd = extra.movieEnd;
+ } else {
+ entry.clear();
+ }
+ }
+ } else if (spotID == kNorad01GasOutSpotID) {
+ if (_fillingStationItem) {
+ if (_fillingStationItem->getObjectID() == kGasCanister) {
+ getExtraEntry(kNorad01ZoomOutWithGasCanister, extra);
+ entry.movieStart = extra.movieStart;
+ entry.movieEnd = extra.movieEnd;
+ } else {
+ entry.clear();
+ }
+ }
+ }
+}
+
+TimeValue NoradAlpha::getViewTime(const RoomID room, const DirectionConstant direction) {
+ ExtraTable::Entry entry;
+
+ if (room == kNorad01 && direction == kSouth && !GameState.getNoradSeenTimeStream()) {
+ getExtraEntry(kNoradArriveFromTSA, entry);
+ return entry.movieStart;
+ }
+
+ if (room == kNorad01 && direction == kWest) {
+ if (!_fillingStationItem) {
+ return Norad::getViewTime(room, direction);
+ } else {
+ getExtraEntry(kN01WGasCanister, entry);
+ return entry.movieStart;
+ }
+ } else if (room == kNorad01West && direction == kWest) {
+ uint32 extraID = 0xffffffff;
+ if (_fillingStationItem) {
+ switch (_fillingStationItem->getObjectID()) {
+ case kArgonCanister:
+ if (GameState.getNoradFillingStationOn())
+ extraID = kN01WZArgonCanisterLit;
+ else
+ extraID = kN01WZArgonCanisterDim;
+ break;
+ case kGasCanister:
+ if (GameState.getNoradFillingStationOn())
+ extraID = kN01WZGasCanisterLit;
+ else
+ extraID = kN01WZGasCanisterDim;
+ break;
+ case kAirMask:
+ if (GameState.getNoradFillingStationOn())
+ extraID = kN01WZAirMaskLit;
+ else
+ extraID = kN01WZAirMaskDim;
+ break;
+ case kNitrogenCanister:
+ if (GameState.getNoradFillingStationOn())
+ extraID = kN01WZNitrogenCanisterLit;
+ else
+ extraID = kN01WZNitrogenCanisterDim;
+ break;
+ default:
+ // Should never happen.
+ break;
+ }
+ } else if (GameState.getNoradFillingStationOn()) {
+ extraID = kN01WZEmptyLit;
+ }
+
+ if (extraID == 0xffffffff) {
+ return Norad::getViewTime(room, direction);
+ } else {
+ getExtraEntry(extraID, entry);
+ return entry.movieStart;
+ }
+ }
+
+ return Norad::getViewTime(room, direction);
+}
+
+void NoradAlpha::turnOnFillingStation() {
+ if (GameState.getCurrentRoom() == kNorad01West && !GameState.getNoradFillingStationOn()) {
+ GameState.setNoradFillingStationOn(true);
+ updateViewFrame();
+ }
+}
+
+void NoradAlpha::turnOffFillingStation() {
+ if (GameState.getCurrentRoom() == kNorad01West && GameState.getNoradFillingStationOn()) {
+ GameState.setNoradFillingStationOn(false);
+ updateViewFrame();
+ }
+}
+
+void NoradAlpha::activateHotspots() {
+ Norad::activateHotspots();
+
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kNorad01West, kWest):
+ if (_vm->getDragType() == kDragInventoryUse) {
+ if (!_fillingStationItem) {
+ ItemID itemID = _vm->getDraggingItem()->getObjectID();
+ if (itemID == kArgonCanister || itemID == kGasCanister || itemID == kAirMask ||
+ itemID == kNitrogenCanister)
+ _vm->getAllHotspots().activateOneHotspot(kN01GasOutletSpotID);
+ }
+ } else {
+ HotSpotID spotID;
+
+ if (_fillingStationItem) {
+ switch (_fillingStationItem->getObjectID()) {
+ case kArgonCanister:
+ spotID = kN01ArgonCanisterSpotID;
+ _vm->getAllHotspots().deactivateOneHotspot(kNorad01GasOutSpotID);
+ break;
+ case kGasCanister:
+ spotID = kN01GasCanisterSpotID;
+ break;
+ case kAirMask:
+ spotID = kN01AirMaskSpotID;
+ _vm->getAllHotspots().deactivateOneHotspot(kNorad01GasOutSpotID);
+ break;
+ case kNitrogenCanister:
+ spotID = kN01NitrogenCanisterSpotID;
+ _vm->getAllHotspots().deactivateOneHotspot(kNorad01GasOutSpotID);
+ break;
+ default:
+ // Should never happen.
+ spotID = kNoHotSpotID;
+ break;
+ }
+ _vm->getAllHotspots().activateOneHotspot(spotID);
+ }
+ }
+ break;
+ case MakeRoomView(kNorad10, kEast):
+ if (GameState.isCurrentDoorOpen())
+ _vm->getAllHotspots().deactivateOneHotspot(kNorad10DoorSpotID);
+ break;
+ case MakeRoomView(kNorad21, kWest):
+ if (GameState.isCurrentDoorOpen())
+ _vm->getAllHotspots().deactivateOneHotspot(kNorad21WestSpotID);
+ break;
+ }
+}
+
+void NoradAlpha::clickInHotspot(const Input &input, const Hotspot *cursorSpot) {
+ Norad::clickInHotspot(input, cursorSpot);
+
+ if (_vm->getDragType() == kDragInventoryUse) {
+ if (GameState.getCurrentRoomAndView() == MakeRoomView(kNorad01West, kWest)) {
+ Item *item = _vm->getDraggingItem();
+ if (item->getObjectID() == kAirMask || item->getObjectID() == kArgonCanister ||
+ item->getObjectID() == kNitrogenCanister || item->getObjectID() == kGasCanister) {
+ HotspotInfoTable::Entry *hotspotEntry = findHotspotEntry(kN01GasOutletSpotID);
+ hotspotEntry->hotspotItem = item->getObjectID();
+ }
+ }
+ }
+}
+
+void NoradAlpha::takeItemFromRoom(Item *item) {
+ if (GameState.getCurrentRoom() == kNorad01West) {
+ if (_fillingStationItem == item) {
+ _fillingStationItem = 0;
+ GameState.setNoradGassed(false);
+ loadAmbientLoops();
+ ((NoradAlphaFillingStation *)_currentInteraction)->newFillingItem(0);
+ forceStridingStop(kNorad03, kEast, kAltNoradAlphaNormal);
+ }
+ }
+
+ Norad::takeItemFromRoom(item);
+}
+
+void NoradAlpha::dropItemIntoRoom(Item *item, Hotspot *droppedSpot) {
+ if (GameState.getCurrentRoom() == kNorad01West) {
+ if (!_fillingStationItem) {
+ _fillingStationItem = item;
+ ((NoradAlphaFillingStation *)_currentInteraction)->newFillingItem(item);
+ }
+ }
+
+ Norad::dropItemIntoRoom(item, droppedSpot);
+}
+
+void NoradAlpha::getClawInfo(HotSpotID &outSpotID, HotSpotID &prepSpotID, HotSpotID &clawControlSpotID, HotSpotID &pinchClawSpotID,
+ HotSpotID &moveClawDownSpotID, HotSpotID &moveClawRightSpotID, HotSpotID &moveClawLeftSpotID, HotSpotID &moveClawUpSpotID,
+ HotSpotID &clawCCWSpotID, HotSpotID &clawCWSpotID, uint32 &clawPosition, const uint32 *&clawExtraIDs) {
+ outSpotID = kNorad22MonitorOutSpotID;
+ prepSpotID = kNorad22LaunchPrepSpotID;
+ clawControlSpotID = kNorad22ClawControlSpotID;
+ pinchClawSpotID = kNorad22ClawPinchSpotID;
+ moveClawDownSpotID = kNorad22ClawDownSpotID;
+ moveClawRightSpotID = kNorad22ClawRightSpotID;
+ moveClawLeftSpotID = kNorad22ClawLeftSpotID;
+ moveClawUpSpotID = kNorad22ClawUpSpotID;
+ clawCCWSpotID = kNorad22ClawCCWSpotID;
+ clawCWSpotID = kNorad22ClawCWSpotID;
+ clawPosition = kClawAtD;
+ clawExtraIDs = _noradAlphaClawExtras;
+}
+
+Hotspot *NoradAlpha::getItemScreenSpot(Item *item, DisplayElement *element) {
+ switch (item->getObjectID()) {
+ case kGasCanister:
+ return _vm->getAllHotspots().findHotspotByID(kN01GasCanisterSpotID);
+ case kAirMask:
+ return _vm->getAllHotspots().findHotspotByID(kN01AirMaskSpotID);
+ case kArgonCanister:
+ return _vm->getAllHotspots().findHotspotByID(kN01ArgonCanisterSpotID);
+ case kNitrogenCanister:
+ return _vm->getAllHotspots().findHotspotByID(kN01NitrogenCanisterSpotID);
+ }
+
+ return Norad::getItemScreenSpot(item, element);
+}
+
+Common::String NoradAlpha::getEnvScanMovie() {
+ Common::String movieName = Neighborhood::getEnvScanMovie();
+
+ if (movieName.empty()) {
+ RoomID room = GameState.getCurrentRoom();
+ if (room >= kNorad01 && room <= kNorad01West)
+ return "Images/AI/Norad/XNE1";
+ else if ((room >= kNorad02 && room <= kNorad19West))
+ return "Images/AI/Norad/XNE2";
+
+ return "Images/AI/Norad/XNE3";
+ }
+
+ return movieName;
+}
+
+uint NoradAlpha::getNumHints() {
+ uint numHints = Neighborhood::getNumHints();
+
+ if (numHints == 0) {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kNorad01, kNorth):
+ case MakeRoomView(kNorad01, kSouth):
+ case MakeRoomView(kNorad01, kEast):
+ case MakeRoomView(kNorad01, kWest):
+ case MakeRoomView(kNorad01East, kEast):
+ case MakeRoomView(kNorad01West, kWest):
+ if (GameState.getNoradGassed()) {
+ if (g_airMask->isAirFilterOn())
+ numHints = 0;
+ else
+ numHints = 3;
+ } else {
+ numHints = 2;
+ }
+ break;
+ case MakeRoomView(kNorad19West, kWest):
+ if (getSubPrepFailed() && GameState.getNoradSubPrepState() != kSubPrepped)
+ numHints = 1;
+ break;
+ case MakeRoomView(kNorad22, kWest):
+ numHints = 1;
+ break;
+ }
+ }
+
+ return numHints;
+}
+
+Common::String NoradAlpha::getHintMovie(uint hintNum) {
+ Common::String movieName = Neighborhood::getHintMovie(hintNum);
+
+ if (movieName.empty()) {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kNorad01, kNorth):
+ case MakeRoomView(kNorad01, kSouth):
+ case MakeRoomView(kNorad01, kEast):
+ case MakeRoomView(kNorad01, kWest):
+ case MakeRoomView(kNorad01East, kEast):
+ case MakeRoomView(kNorad01West, kWest):
+ switch (hintNum) {
+ case 1:
+ if (GameState.getNoradGassed())
+ return "Images/AI/Norad/XN01SW";
+
+ return "Images/AI/Norad/XN01WD2";
+ case 2:
+ if (GameState.getNoradGassed()) {
+ if (_vm->playerHasItemID(kAirMask))
+ // Mask must not be on if we get here...
+ return "Images/AI/Globals/XGLOB1A";
+
+ return "Images/AI/Globals/XGLOB3D";
+ }
+
+ return "Images/AI/Globals/XGLOB5C";
+ case 3:
+ return "Images/AI/Norad/XN01SH";
+ }
+ break;
+ case MakeRoomView(kNorad19West, kWest):
+ return "Images/AI/Norad/XN19NH";
+ case MakeRoomView(kNorad22, kWest):
+ return "Images/AI/Globals/XGLOB1C";
+ }
+ }
+
+ return movieName;
+}
+
+void NoradAlpha::closeDoorOffScreen(const RoomID room, const DirectionConstant) {
+ switch (room) {
+ case kNorad12:
+ case kNorad13:
+ case kNorad18:
+ case kNorad19:
+ playSpotSoundSync(kAlphaElevatorDoorCloseIn, kAlphaElevatorDoorCloseOut);
+ break;
+ default:
+ playSpotSoundSync(kAlphaRegDoorCloseIn, kAlphaRegDoorCloseOut);
+ break;
+ }
+}
+
+void NoradAlpha::findSpotEntry(const RoomID room, const DirectionConstant direction, SpotFlags flags, SpotTable::Entry &spotEntry) {
+ if (room == kNorad01 && direction == kSouth)
+ spotEntry.clear();
+ else
+ Norad::findSpotEntry(room, direction, flags, spotEntry);
+}
+
+bool NoradAlpha::canSolve() {
+ return Norad::canSolve() || getHintMovie(1) == "Images/AI/Norad/XN01SW";
+}
+
+void NoradAlpha::doSolve() {
+ Norad::doSolve();
+
+ if (getHintMovie(1) == "Images/AI/Norad/XN01SW") {
+ _vm->addItemToInventory(g_airMask);
+ g_airMask->putMaskOn();
+ }
+}
+
+Common::String NoradAlpha::getNavMovieName() {
+ return "Images/Norad Alpha/Norad Alpha.movie";
+}
+
+Common::String NoradAlpha::getSoundSpotsName() {
+ return "Sounds/Norad/Norad Alpha Spots";
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/norad/alpha/noradalpha.h b/engines/pegasus/neighborhood/norad/alpha/noradalpha.h
new file mode 100644
index 0000000000..582d6c2bb3
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/alpha/noradalpha.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_NORAD_ALPHA_NORADALPHA_H
+#define PEGASUS_NEIGHBORHOOD_NORAD_ALPHA_NORADALPHA_H
+
+#include "pegasus/neighborhood/norad/norad.h"
+
+namespace Pegasus {
+
+class Item;
+
+class NoradAlpha : public Norad {
+public:
+ NoradAlpha(InputHandler *, PegasusEngine *);
+ virtual ~NoradAlpha() {}
+
+ virtual void init();
+ void start();
+
+ virtual bool okayToJump();
+
+ void playClawMonitorIntro();
+
+ void getExtraCompassMove(const ExtraTable::Entry &, FaderMoveSpec &);
+
+ void turnOnFillingStation();
+ void turnOffFillingStation();
+ Item *getFillingItem() { return _fillingStationItem; }
+ bool gasCanisterIntake();
+
+ virtual void takeItemFromRoom(Item *);
+ virtual void dropItemIntoRoom(Item *, Hotspot *);
+
+ virtual GameInteraction *makeInteraction(const InteractionID);
+
+ virtual void getClawInfo(HotSpotID &outSpotID, HotSpotID &prepSpotID, HotSpotID &clawControlSpotID,
+ HotSpotID &pinchClawSpotID, HotSpotID &moveClawDownSpotID, HotSpotID &moveClawRightSpotID,
+ HotSpotID &moveClawLeftSpotID, HotSpotID &moveClawUpSpotID, HotSpotID &clawCCWSpotID,
+ HotSpotID &clawCWSpotID, uint32 &, const uint32 *&);
+
+ void loadAmbientLoops();
+
+ Common::String getEnvScanMovie();
+ uint getNumHints();
+ Common::String getHintMovie(uint);
+ void setUpAIRules();
+
+ void setSubPrepFailed(bool value) { _subPrepFailed = value; }
+ bool getSubPrepFailed() { return _subPrepFailed; }
+
+ void closeDoorOffScreen(const RoomID, const DirectionConstant);
+ void findSpotEntry(const RoomID, const DirectionConstant, SpotFlags, SpotTable::Entry &);
+ void clickInHotspot(const Input &, const Hotspot *);
+
+ void checkContinuePoint(const RoomID, const DirectionConstant);
+
+ bool canSolve();
+ void doSolve();
+
+protected:
+ static const uint32 _noradAlphaClawExtras[22];
+
+ virtual void arriveAtNorad01();
+ virtual void arriveAtNorad01East();
+ virtual void arriveAtNorad01West();
+ virtual void arriveAtNorad04();
+ virtual void arriveAtNorad22();
+
+ virtual void arriveAt(const RoomID, const DirectionConstant);
+
+ virtual void getZoomEntry(const HotSpotID, ZoomTable::Entry &);
+ virtual TimeValue getViewTime(const RoomID, const DirectionConstant);
+
+ virtual void receiveNotification(Notification *, const NotificationFlags);
+
+ virtual void activateHotspots();
+
+ Hotspot *getItemScreenSpot(Item *, DisplayElement *);
+
+ void bumpIntoWall();
+
+ Item *_fillingStationItem;
+
+ bool _subPrepFailed;
+
+ Common::String getSoundSpotsName();
+ Common::String getNavMovieName();
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/norad/alpha/panorama.cpp b/engines/pegasus/neighborhood/norad/alpha/panorama.cpp
new file mode 100644
index 0000000000..5a717a84e7
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/alpha/panorama.cpp
@@ -0,0 +1,239 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/macresman.h"
+#include "common/stream.h"
+#include "pegasus/neighborhood/norad/alpha/panorama.h"
+
+namespace Pegasus {
+
+Panorama::Panorama() : _panoramaMovie(kNoDisplayElement) {
+ blankFields();
+}
+
+Panorama::~Panorama() {
+ releasePanorama();
+}
+
+void Panorama::blankFields() {
+ _viewBounds = Common::Rect();
+ _drawBounds = Common::Rect();
+ _mask = 0;
+ _panoramaWidth = 0;
+ _panoramaHeight = 0;
+ _stripWidth = 0;
+ _stripLeft = -1;
+ _stripRight = -1;
+}
+
+void Panorama::releasePanorama() {
+ if (_panoramaMovie.isMovieValid()) {
+ _panoramaMovie.releaseMovie();
+ _panoramaWorld.deallocateSurface();
+ blankFields();
+ }
+}
+
+static const uint32 kPanoramaResType = MKTAG('P', 'a', 'n', 'I'); // Panorama Information.
+static const uint16 kPanoramaResID = 128;
+
+void Panorama::initFromMovieFile(const Common::String &fileName) {
+ // First, we need the resource fork for other reasons -- PanI resource
+ Common::MacResManager *resFork = new Common::MacResManager();
+ if (!resFork->open(fileName) || !resFork->hasResFork())
+ error("Could not open the resource fork of '%s'", fileName.c_str());
+
+ Common::SeekableReadStream *resource = resFork->getResource(kPanoramaResType, kPanoramaResID);
+ if (!resource)
+ error("No panorama information in the resource fork of '%s'", fileName.c_str());
+
+ _panoramaWidth = resource->readUint16BE();
+ _panoramaHeight = resource->readUint16BE();
+ _stripWidth = resource->readUint16BE();
+
+ delete resource;
+ delete resFork;
+
+ // Now we open the movie like normal
+ _panoramaMovie.initFromMovieFile(fileName);
+}
+
+void Panorama::setMask(Surface *mask) {
+ _mask = mask;
+}
+
+// If the panorama is not open, do nothing and return.
+// Otherwise, set up the view bounds.
+void Panorama::setViewBounds(const Common::Rect &newView) {
+ if (!isPanoramaOpen())
+ return;
+
+ if (newView.isEmpty())
+ return;
+
+ Common::Rect r = newView;
+
+ if (r.width() > _panoramaWidth) {
+ r.left = 0;
+ r.right = _panoramaWidth;
+ } else {
+ if (r.right > _panoramaWidth)
+ r.translate(_panoramaWidth - r.right, 0);
+
+ if (r.left < 0)
+ r.translate(-r.left, 0);
+ }
+
+ if (r.height() > _panoramaHeight) {
+ r.top = 0;
+ r.bottom = _panoramaHeight;
+ } else {
+ if (r.bottom > _panoramaHeight)
+ r.translate(0, _panoramaHeight - r.bottom);
+
+ if (r.top < 0)
+ r.translate(0, -r.top);
+ }
+
+ if (_viewBounds != r) {
+ CoordType stripLeft = 0;
+
+ if (r.width() != _viewBounds.width() || !_panoramaWorld.isSurfaceValid()) {
+ _panoramaWorld.deallocateSurface();
+ makeNewSurface(r);
+ } else {
+ CoordType stripRight;
+ calcStripRange(r, stripLeft, stripRight);
+ loadStrips(stripLeft, stripRight);
+ }
+
+ _viewBounds = r;
+ _drawBounds = r;
+ _drawBounds.translate(-stripLeft * _stripWidth, 0);
+ }
+}
+
+void Panorama::getViewBounds(Common::Rect &r) const {
+ r = _viewBounds;
+}
+
+void Panorama::getPanoramaBounds(Common::Rect &r) const {
+ r = Common::Rect(0, 0, _panoramaWidth, _panoramaHeight);
+}
+
+void Panorama::drawPanorama(const Common::Rect &destRect) {
+ if (_panoramaWorld.isSurfaceValid()) {
+ if (_mask)
+ _panoramaWorld.copyToCurrentPortMasked(_drawBounds, destRect, _mask);
+ else
+ _panoramaWorld.copyToCurrentPortTransparent(_drawBounds, destRect);
+ }
+}
+
+// Make a new Surface big enough to show r, which is assumed to be a valid view bounds.
+// Assumptions:
+// r is a valid view bounds.
+// _panoramaWorld is not allocated.
+// _panoramaHeight, _stripWidth is correct.
+// _panoramaMovie is allocated.
+void Panorama::makeNewSurface(const Common::Rect& view) {
+ CoordType stripLeft, stripRight;
+ calcStripRange(view, stripLeft, stripRight);
+
+ Common::Rect r(0, 0, (stripRight - stripLeft + 1) * _stripWidth, _panoramaHeight);
+ _panoramaWorld.allocateSurface(r);
+ _panoramaMovie.shareSurface(&_panoramaWorld);
+ loadStrips(stripLeft, stripRight);
+}
+
+// Assumes view is not empty.
+void Panorama::calcStripRange(const Common::Rect &view, CoordType &stripLeft, CoordType &stripRight) {
+ stripLeft = view.left / _stripWidth;
+ stripRight = (view.left - view.left % _stripWidth + _stripWidth - 1 + view.width()) / _stripWidth;
+}
+
+// Load in all needed strips to put range (stripLeft, stripRight) into the
+// panorama's Surface. Try to optimize by saving any pixels already in the Surface.
+// Assumptions:
+// Surface is allocated and is big enough for maximum range of
+// stripLeft and stripRight
+void Panorama::loadStrips(CoordType stripLeft, CoordType stripRight) {
+ if (_stripLeft == -1) {
+ // Surface has just been allocated.
+ // Load in all strips.
+ for (CoordType i = stripLeft; i <= stripRight; i++)
+ loadOneStrip(i, stripLeft);
+
+ _stripLeft = stripLeft;
+ _stripRight = stripRight;
+ } else if (stripLeft != _stripLeft) {
+ CoordType overlapLeft = MAX(stripLeft, _stripLeft);
+ CoordType overlapRight = MIN(stripRight, _stripRight);
+
+ if (overlapLeft <= overlapRight) {
+ Common::Rect r1((overlapLeft - _stripLeft) * _stripWidth, 0,
+ (overlapRight - _stripLeft + 1) * _stripWidth, _panoramaHeight);
+
+ if (stripLeft < _stripLeft) {
+ Common::Rect bounds;
+ _panoramaWorld.getSurfaceBounds(bounds);
+ _panoramaWorld.getSurface()->move(bounds.right - r1.right, 0, _panoramaHeight);
+
+ for (CoordType i = stripLeft; i < _stripLeft; i++)
+ loadOneStrip(i, stripLeft);
+ } else {
+ _panoramaWorld.getSurface()->move(-r1.left, 0, _panoramaHeight);
+
+ for (CoordType i = _stripRight + 1; i <= stripRight; i++)
+ loadOneStrip(i, stripLeft);
+ }
+ } else {
+ // No overlap.
+ // Load everything.
+ for (CoordType i = stripLeft; i <= stripRight; i++)
+ loadOneStrip(i, stripLeft);
+ }
+
+ _stripLeft = stripLeft;
+ _stripRight = stripRight;
+ } else if (stripRight > _stripRight) {
+ // Need to add one or more strips.
+ for (CoordType i = _stripRight + 1; i <= stripRight; i++)
+ loadOneStrip(i, _stripLeft);
+
+ _stripRight = stripRight;
+ } else if (stripRight < _stripRight) {
+ // Need to chop off one strip.
+ _stripRight = stripRight;
+ }
+}
+
+void Panorama::loadOneStrip(CoordType stripToLoad, CoordType leftStrip) {
+ _panoramaMovie.moveMovieBoxTo((stripToLoad - leftStrip) * _stripWidth, 0);
+ _panoramaMovie.setTime(stripToLoad, 1);
+ _panoramaMovie.redrawMovieWorld();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/norad/alpha/panorama.h b/engines/pegasus/neighborhood/norad/alpha/panorama.h
new file mode 100644
index 0000000000..87c7b3bd4e
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/alpha/panorama.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_NORAD_ALPHA_PANORAMA_H
+#define PEGASUS_NEIGHBORHOOD_NORAD_ALPHA_PANORAMA_H
+
+#include "pegasus/movie.h"
+
+namespace Pegasus {
+
+/*
+
+ Panorama implements a wide image using a specially constructed movie file.
+ The movie holds the image as a series of vertical strips, say 16 or 32 pixels wide.
+
+ The panorama bounds defines the entire panorama. The view bounds represents the
+ area on the panorama that is kept in memory.
+
+ The panorama bounds is also stored in the movie file; it cannot be changed. The
+ view bounds must always be a subset of the panorama bounds.
+
+ In actuality, the area kept in memory is at least as wide as the view bounds (but
+ may be wider to coincide with the width of the movies slices), and is as tall as
+ the panorama bounds. The view bounds is used by the drawPanorama function to draw
+ a piece of the panorama to the current screen.
+
+ The panorama movie is built at a time scale of 1, with each strip lasting for one
+ second, so that strip number corresponds exactly with the time value at which the
+ strip is stored.
+
+ TO USE:
+
+ Call one initFromMovieFile to open the movie. Then set up a view rect by
+ calling setViewBounds. Once these two functions have been called, drawPanorama
+ will draw the panorama.
+
+*/
+
+class Panorama {
+public:
+ Panorama();
+ virtual ~Panorama();
+
+ void initFromMovieFile(const Common::String &);
+ void releasePanorama();
+ bool isPanoramaOpen() { return _panoramaMovie.isMovieValid(); }
+
+ void setViewBounds(const Common::Rect &);
+ void getViewBounds(Common::Rect &) const;
+
+ void setMask(Surface *);
+
+ void getPanoramaBounds(Common::Rect &) const;
+
+ void drawPanorama(const Common::Rect &);
+
+protected:
+ void blankFields();
+ void makeNewSurface(const Common::Rect &);
+ void calcStripRange(const Common::Rect &, CoordType &, CoordType &);
+ void loadStrips(CoordType, CoordType);
+ void loadOneStrip(CoordType, CoordType);
+
+ Movie _panoramaMovie;
+ Surface _panoramaWorld, *_mask;
+ Common::Rect _viewBounds;
+ Common::Rect _drawBounds;
+ CoordType _panoramaWidth, _panoramaHeight;
+ CoordType _stripWidth; // Pixels per strip.
+ CoordType _numStrips;
+ CoordType _stripLeft, _stripRight;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/norad/alpha/panoramascroll.cpp b/engines/pegasus/neighborhood/norad/alpha/panoramascroll.cpp
new file mode 100644
index 0000000000..7865bbb442
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/alpha/panoramascroll.cpp
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/neighborhood/norad/alpha/panoramascroll.h"
+
+namespace Pegasus {
+
+PanoramaScroll::PanoramaScroll(const DisplayElementID id) : IdlerAnimation(id) {
+ _boundsWidth = 0;
+ _totalWidth = 0;
+}
+
+void PanoramaScroll::initFromMovieFile(const Common::String &fileName) {
+ _panorama.initFromMovieFile(fileName);
+
+ Common::Rect r;
+ _panorama.getPanoramaBounds(r);
+ _totalWidth = r.width();
+}
+
+void PanoramaScroll::initMaskFromPICTFile(const Common::String &fileName) {
+ if (!_panorama.isPanoramaOpen())
+ return;
+
+ _mask.getImageFromPICTFile(fileName);
+ _panorama.setMask(&_mask);
+}
+
+void PanoramaScroll::releasePanorama() {
+ if (_panorama.isPanoramaOpen())
+ _panorama.releasePanorama();
+
+ _mask.deallocateSurface();
+}
+
+void PanoramaScroll::setBounds(const Common::Rect &r) {
+ Animation::setBounds(r);
+
+ _boundsWidth = r.width();
+
+ Common::Rect r2;
+ _panorama.getViewBounds(r2);
+ r2.right = r2.left + _boundsWidth;
+ r2.bottom = r2.top + r.height();
+ _panorama.setViewBounds(r2);
+}
+
+void PanoramaScroll::draw(const Common::Rect &) {
+ _panorama.drawPanorama(_bounds);
+}
+
+void PanoramaScroll::timeChanged(const TimeValue newTime) {
+ CoordType leftPixel = (_totalWidth - _boundsWidth) * newTime / getDuration();
+
+ Common::Rect r;
+ _panorama.getViewBounds(r);
+ if (leftPixel != r.left) {
+ _panorama.getViewBounds(r);
+ r.moveTo(leftPixel, 0);
+ _panorama.setViewBounds(r);
+ triggerRedraw();
+ }
+}
+
+void PanoramaScroll::getPanoramaBounds(Common::Rect &r) const {
+ _panorama.getPanoramaBounds(r);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/norad/alpha/panoramascroll.h b/engines/pegasus/neighborhood/norad/alpha/panoramascroll.h
new file mode 100644
index 0000000000..6a3e1515e2
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/alpha/panoramascroll.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_NORAD_ALPHA_PANORAMASCROLL_H
+#define PEGASUS_NEIGHBORHOOD_NORAD_ALPHA_PANORAMASCROLL_H
+
+#include "pegasus/neighborhood/norad/alpha/panorama.h"
+
+namespace Pegasus {
+
+class PanoramaScroll : public IdlerAnimation {
+public:
+ PanoramaScroll(const DisplayElementID);
+ virtual ~PanoramaScroll() {}
+
+ void initFromMovieFile(const Common::String &);
+ void initMaskFromPICTFile(const Common::String &);
+
+ void releasePanorama();
+
+ bool isPanoramaOpen() { return _panorama.isPanoramaOpen(); }
+ void getPanoramaBounds(Common::Rect &) const;
+
+ void setBounds(const Common::Rect&);
+
+ void draw(const Common::Rect &);
+
+protected:
+ void timeChanged(const TimeValue);
+
+ Panorama _panorama;
+ Surface _mask;
+ CoordType _totalWidth, _boundsWidth;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/norad/constants.h b/engines/pegasus/neighborhood/norad/constants.h
new file mode 100644
index 0000000000..37c1769309
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/constants.h
@@ -0,0 +1,755 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_NORAD_CONSTANTS_H
+#define PEGASUS_NEIGHBORHOOD_NORAD_CONSTANTS_H
+
+#include "pegasus/constants.h"
+
+namespace Pegasus {
+
+// Norad Alpha spot constants
+
+static const TimeValue kAlphaBumpIntoWallIn = 0;
+static const TimeValue kAlphaBumpIntoWallOut = 303;
+
+static const TimeValue kAlphaAccessDeniedIn = 303;
+static const TimeValue kAlphaAccessDeniedOut = 3045;
+
+static const TimeValue kAlphaRegDoorCloseIn = 3045;
+static const TimeValue kAlphaRegDoorCloseOut = 4476;
+
+static const TimeValue kAlphaElevatorDoorCloseIn = 4476;
+static const TimeValue kAlphaElevatorDoorCloseOut = 5071;
+
+static const TimeValue kAlphaCantTransportIn = 5071;
+static const TimeValue kAlphaCantTransportOut = 9348;
+
+static const TimeValue kAlphaPressureDoorIntro1In = 9348;
+static const TimeValue kAlphaPressureDoorIntro1Out = 11061;
+
+static const TimeValue kAlphaPressureDoorIntro2In = 11061;
+static const TimeValue kAlphaPressureDoorIntro2Out = 14098;
+
+static const TimeValue kN22ReplyIn = 14098;
+static const TimeValue kN22ReplyOut = 18442;
+
+static const TimeValue kAlphaLoadClawIntroIn = 18442;
+static const TimeValue kAlphaLoadClawIntroOut = 20698;
+
+// Norad Delta spot constants
+
+static const TimeValue kDeltaBumpIntoWallIn = 0;
+static const TimeValue kDeltaBumpIntoWallOut = 303;
+
+static const TimeValue kDeltaAccessDeniedIn = 303;
+static const TimeValue kDeltaAccessDeniedOut = 3045;
+
+static const TimeValue kDeltaRegDoorCloseIn = 3045;
+static const TimeValue kDeltaRegDoorCloseOut = 4476;
+
+static const TimeValue kDeltaElevatorDoorCloseIn = 4476;
+static const TimeValue kDeltaElevatorDoorCloseOut = 5071;
+
+static const TimeValue kPressureDoorIntro1In = 5071;
+static const TimeValue kPressureDoorIntro1Out = 6784;
+
+static const TimeValue kPressureDoorIntro2In = 6784;
+static const TimeValue kPressureDoorIntro2Out = 9821;
+
+static const TimeValue kLoadClawIntroIn = 9821;
+static const TimeValue kLoadClawIntroOut = 12077;
+
+static const TimeValue kHoldForRetinalIn = 12077;
+static const TimeValue kHoldForRetinalOut = 14104;
+
+static const TimeValue kRetinalScanFailedIn = 14104;
+static const TimeValue kRetinalScanFailedOut = 17538;
+
+static const TimeValue kAddisAbabaIn = 17538;
+static const TimeValue kAddisAbabaOut = 19263;
+
+static const TimeValue kBangkokIn = 19263;
+static const TimeValue kBangkokOut = 20201;
+
+static const TimeValue kBonnIn = 20201;
+static const TimeValue kBonnOut = 20915;
+
+static const TimeValue kDublinIn = 20915;
+static const TimeValue kDublinOut = 21660;
+
+static const TimeValue kHonoluluIn = 21660;
+static const TimeValue kHonoluluOut = 22498;
+
+static const TimeValue kMadridIn = 22498;
+static const TimeValue kMadridOut = 23474;
+
+static const TimeValue kReykjavikIn = 23474;
+static const TimeValue kReykjavikOut = 24488;
+
+static const TimeValue kSanAntonioIn = 24488;
+static const TimeValue kSanAntonioOut = 25561;
+
+static const TimeValue kSeoulIn = 25561;
+static const TimeValue kSeoulOut = 26461;
+
+static const TimeValue kSvortalskIn = 26461;
+static const TimeValue kSvortalskOut = 27582;
+
+static const TimeValue kSiloBeepIn = 27582;
+static const TimeValue kSiloBeepOut = 27721;
+
+static const TimeValue kAllSilosDeactivatedIn = 27721;
+static const TimeValue kAllSilosDeactivatedOut = 28928;
+
+static const TimeValue kGlobalLaunchOverrideIn = 28928;
+static const TimeValue kGlobalLaunchOverrideOut = 30736;
+
+static const TimeValue kLaunchSiloSelectedIn = 30736;
+static const TimeValue kLaunchSiloSelectedOut = 31660;
+
+static const TimeValue kLaunchToProceedIn = 31660;
+static const TimeValue kLaunchToProceedOut = 32536;
+
+static const TimeValue kMaximumDeactivationIn = 32536;
+static const TimeValue kMaximumDeactivationOut = 34337;
+
+static const TimeValue kMissileLaunchedIn = 34337;
+static const TimeValue kMissileLaunchedOut = 35082;
+
+static const TimeValue kNewLaunchSiloIn = 35082;
+static const TimeValue kNewLaunchSiloOut = 36320;
+
+static const TimeValue kStrikeAuthorizedIn = 36320;
+static const TimeValue kStrikeAuthorizedOut = 37393;
+
+static const TimeValue kPrimaryTargetIn = 37393;
+static const TimeValue kPrimaryTargetOut = 38628;
+
+static const TimeValue kSiloDeactivatedIn = 38628;
+static const TimeValue kSiloDeactivatedOut = 39566;
+
+static const TimeValue kStrikeCodeRejectedIn = 39566;
+static const TimeValue kStrikeCodeRejectedOut = 41056;
+
+static const TimeValue kToDeactivateIn = 41056;
+static const TimeValue kToDeactivateOut = 46494;
+
+static const TimeValue kTwoMinutesIn = 46494;
+static const TimeValue kTwoMinutesOut = 47166;
+
+static const TimeValue kOneMinuteIn = 47166;
+static const TimeValue kOneMinuteOut = 47856;
+
+static const TimeValue kFiftySecondsIn = 47856;
+static const TimeValue kFiftySecondsOut = 48691;
+
+static const TimeValue kFortySecondsIn = 48691;
+static const TimeValue kFortySecondsOut = 49500;
+
+static const TimeValue kThirtySecondsIn = 49500;
+static const TimeValue kThirtySecondsOut = 50362;
+
+static const TimeValue kTwentySecondsIn = 50362;
+static const TimeValue kTwentySecondsOut = 51245;
+
+static const TimeValue kTenSecondsIn = 51245;
+static const TimeValue kTenSecondsOut = 52069;
+
+static const TimeValue kGiveUpHumanIn = 52069;
+static const TimeValue kGiveUpHumanOut = 55023;
+
+static const TimeValue kIJustBrokeIn = 55023;
+static const TimeValue kIJustBrokeOut = 59191;
+
+static const TimeValue kTheOnlyGoodHumanIn = 59191;
+static const TimeValue kTheOnlyGoodHumanOut = 62379;
+
+static const TimeValue kYouAreRunningIn = 62379;
+static const TimeValue kYouAreRunningOut = 64201;
+
+static const TimeValue kYouCannotPossiblyIn = 64201;
+static const TimeValue kYouCannotPossiblyOut = 65740;
+
+static const TimeValue kYouWillFailIn = 65740;
+static const TimeValue kYouWillFailOut = 67217;
+
+static const CanOpenDoorReason kCantOpenBadPressure = kCantOpenLastReason + 1;
+
+static const NotificationFlags kAirTimerExpiredFlag = kLastNeighborhoodNotificationFlag << 1;
+
+static const uint16 kNoradWarningVolume = 0x100 / 3;
+static const uint16 kNoradSuckWindVolume = 0x100 / 2;
+
+static const int16 kElevatorCompassAngle = -40;
+static const int16 kSubPlatformCompassAngle = 45;
+static const int16 kSubControlCompassAngle = -10;
+
+// Norad interactions.
+
+static const InteractionID kNoradGlobeGameInteractionID = 0;
+static const InteractionID kNoradECRMonitorInteractionID = 1;
+static const InteractionID kNoradFillingStationInteractionID = 2;
+static const InteractionID kNoradElevatorInteractionID = 3;
+static const InteractionID kNoradPressureDoorInteractionID = 4;
+static const InteractionID kNoradSubControlRoomInteractionID = 5;
+static const InteractionID kNoradSubPlatformInteractionID = 6;
+
+/////////////////////////////////////////////
+//
+// Norad Alpha
+
+static const CoordType kECRSlideShowLeft = kNavAreaLeft + 78;
+static const CoordType kECRSlideShowTop = kNavAreaTop + 1;
+
+static const CoordType kECRPanLeft = kNavAreaLeft + 78 + 5;
+static const CoordType kECRPanTop = kNavAreaTop + 1 + 4;
+static const CoordType kECRPanRight = kECRPanLeft + 213;
+static const CoordType kECRPanBottom = kECRPanTop + 241;
+
+static const CoordType kNoradAlphaElevatorControlsLeft = kNavAreaLeft + 332;
+static const CoordType kNoradAlphaElevatorControlsTop = kNavAreaTop + 127;
+
+static const CoordType kNoradAlpha01LeftSideLeft = kNavAreaLeft + 0;
+static const CoordType kNoradAlpha01LeftSideTop = kNavAreaTop + 0;
+
+static const CoordType kNoradAlpha01RightSideLeft = kNavAreaLeft + 240;
+static const CoordType kNoradAlpha01RightSideTop = kNavAreaTop + 12;
+
+static const CoordType kNoradUpperLevelsLeft = kNavAreaLeft + 98;
+static const CoordType kNoradUpperLevelsTop = kNavAreaTop + 31;
+
+static const CoordType kNoradUpperTypeLeft = kNoradUpperLevelsLeft + 114;
+static const CoordType kNoradUpperTypeTop = kNoradUpperLevelsTop + 8;
+
+static const CoordType kNoradUpperUpLeft = kNavAreaLeft + 361;
+static const CoordType kNoradUpperUpTop = kNavAreaTop + 32;
+
+static const CoordType kNoradUpperDownLeft = kNavAreaLeft + 367;
+static const CoordType kNoradUpperDownTop = kNavAreaTop + 66;
+
+static const CoordType kNoradLowerLevelsLeft = kNavAreaLeft + 74;
+static const CoordType kNoradLowerLevelsTop = kNavAreaTop + 157;
+
+static const CoordType kNoradLowerTypeLeft = kNoradLowerLevelsLeft + 144;
+static const CoordType kNoradLowerTypeTop = kNoradLowerLevelsTop + 9;
+
+static const CoordType kNoradLowerUpLeft = kNavAreaLeft + 380;
+static const CoordType kNoradLowerUpTop = kNavAreaTop + 164;
+
+static const CoordType kNoradLowerDownLeft = kNavAreaLeft + 388;
+static const CoordType kNoradLowerDownTop = kNavAreaTop + 212;
+
+static const CoordType kNoradPlatformLeft = kNavAreaLeft + 36;
+static const CoordType kNoradPlatformTop = kNavAreaTop + 87;
+
+static const CoordType kNoradSubControlLeft = kNavAreaLeft + 0;
+static const CoordType kNoradSubControlTop = kNavAreaTop + 84;
+
+static const CoordType kNoradSubControlPinchLeft = kNoradSubControlLeft + 106;
+static const CoordType kNoradSubControlPinchTop = kNoradSubControlTop + 86;
+
+static const CoordType kNoradSubControlDownLeft = kNoradSubControlLeft + 66;
+static const CoordType kNoradSubControlDownTop = kNoradSubControlTop + 106;
+
+static const CoordType kNoradSubControlRightLeft = kNoradSubControlLeft + 83;
+static const CoordType kNoradSubControlRightTop = kNoradSubControlTop + 90;
+
+static const CoordType kNoradSubControlLeftLeft = kNoradSubControlLeft + 56;
+static const CoordType kNoradSubControlLeftTop = kNoradSubControlTop + 91;
+
+static const CoordType kNoradSubControlUpLeft = kNoradSubControlLeft + 66;
+static const CoordType kNoradSubControlUpTop = kNoradSubControlTop + 81;
+
+static const CoordType kNoradSubControlCCWLeft = kNoradSubControlLeft + 29;
+static const CoordType kNoradSubControlCCWTop = kNoradSubControlTop + 88;
+
+static const CoordType kNoradSubControlCWLeft = kNoradSubControlLeft + 0;
+static const CoordType kNoradSubControlCWTop = kNoradSubControlTop + 89;
+
+static const CoordType kNoradClawMonitorLeft = kNavAreaLeft + 288;
+static const CoordType kNoradClawMonitorTop = kNavAreaTop + 97;
+
+static const CoordType kNoradGreenBallAtALeft = kNoradClawMonitorLeft + 179;
+static const CoordType kNoradGreenBallAtATop = kNoradClawMonitorTop + 82;
+
+static const CoordType kNoradGreenBallAtBLeft = kNoradClawMonitorLeft + 130;
+static const CoordType kNoradGreenBallAtBTop = kNoradClawMonitorTop + 73;
+
+static const CoordType kNoradGreenBallAtCLeft = kNoradClawMonitorLeft + 110;
+static const CoordType kNoradGreenBallAtCTop = kNoradClawMonitorTop + 26;
+
+static const CoordType kNoradGreenBallAtDLeft = kNoradClawMonitorLeft + 21;
+static const CoordType kNoradGreenBallAtDTop = kNoradClawMonitorTop + 49;
+
+/////////////////////////////////////////////
+//
+// Norad Delta
+
+static const CoordType kGlobeMonitorLeft = kNavAreaLeft + 360;
+static const CoordType kGlobeMonitorTop = kNavAreaTop + 144;
+
+static const CoordType kGlobeLeft = kNavAreaLeft + 172;
+static const CoordType kGlobeTop = kNavAreaTop;
+
+static const CoordType kGlobeCircleLeftLeft = kNavAreaLeft + 186;
+static const CoordType kGlobeCircleLeftTop = kNavAreaTop + 41;
+
+static const CoordType kGlobeCircleRightLeft = kNavAreaLeft + 321;
+static const CoordType kGlobeCircleRightTop = kNavAreaTop + 41;
+
+static const CoordType kGlobeCircleUpLeft = kNavAreaLeft + 220;
+static const CoordType kGlobeCircleUpTop = kNavAreaTop + 7;
+
+static const CoordType kGlobeCircleDownLeft = kNavAreaLeft + 220;
+static const CoordType kGlobeCircleDownTop = kNavAreaTop + 142;
+
+static const CoordType kGlobeUpperLeftHiliteLeft = kNavAreaLeft + 207;
+static const CoordType kGlobeUpperLeftHiliteTop = kNavAreaTop + 28;
+
+static const CoordType kGlobeUpperRightHiliteLeft = kNavAreaLeft + 307;
+static const CoordType kGlobeUpperRightHiliteTop = kNavAreaTop + 28;
+
+static const CoordType kGlobeLowerLeftHiliteLeft = kNavAreaLeft + 207;
+static const CoordType kGlobeLowerLeftHiliteTop = kNavAreaTop + 128;
+
+static const CoordType kGlobeLowerRightHiliteLeft = kNavAreaLeft + 307;
+static const CoordType kGlobeLowerRightHiliteTop = kNavAreaTop + 128;
+
+static const CoordType kGlobeLeftMotionHiliteLeft = kNavAreaLeft + 182;
+static const CoordType kGlobeLeftMotionHiliteTop = kNavAreaTop + 60;
+
+static const CoordType kGlobeRightMotionHiliteLeft = kNavAreaLeft + 331;
+static const CoordType kGlobeRightMotionHiliteTop = kNavAreaTop + 60;
+
+static const CoordType kGlobeUpMotionHiliteLeft = kNavAreaLeft + 239;
+static const CoordType kGlobeUpMotionHiliteTop = kNavAreaTop + 3;
+
+static const CoordType kGlobeDownMotionHiliteLeft = kNavAreaLeft + 239;
+static const CoordType kGlobeDownMotionHiliteTop = kNavAreaTop + 152;
+
+static const CoordType kGlobeUpperNamesLeft = kNavAreaLeft + 368;
+static const CoordType kGlobeUpperNamesTop = kNavAreaTop + 188;
+
+static const CoordType kGlobeLowerNamesLeft = kNavAreaLeft + 368;
+static const CoordType kGlobeLowerNamesTop = kNavAreaTop + 212;
+
+static const CoordType kGlobeCountdownLeft = kNavAreaLeft + 478;
+static const CoordType kGlobeCountdownTop = kNavAreaTop + 164;
+
+// Norad Alpha display IDs.
+
+static const DisplayElementID kECRSlideShowMovieID = kNeighborhoodDisplayID;
+static const DisplayElementID kECRPanID = kECRSlideShowMovieID + 1;
+static const DisplayElementID kNoradAlphaDeathMovieID = kECRPanID + 1;
+static const DisplayElementID kNoradElevatorControlsID = kNoradAlphaDeathMovieID + 1;
+static const DisplayElementID kN01LeftSideID = kNoradElevatorControlsID + 1;
+static const DisplayElementID kN01RightSideID = kN01LeftSideID + 1;
+static const DisplayElementID kPressureDoorLevelsID = kN01RightSideID + 1;
+static const DisplayElementID kPressureDoorTypeID = kPressureDoorLevelsID + 1;
+static const DisplayElementID kPressureDoorUpButtonID = kPressureDoorTypeID + 1;
+static const DisplayElementID kPressureDoorDownButtonID = kPressureDoorUpButtonID + 1;
+static const DisplayElementID kPlatformMonitorID = kPressureDoorDownButtonID + 1;
+static const DisplayElementID kSubControlMonitorID = kPlatformMonitorID + 1;
+static const DisplayElementID kClawMonitorID = kSubControlMonitorID + 1;
+static const DisplayElementID kSubControlPinchID = kClawMonitorID + 1;
+static const DisplayElementID kSubControlDownID = kSubControlPinchID + 1;
+static const DisplayElementID kSubControlRightID = kSubControlDownID + 1;
+static const DisplayElementID kSubControlLeftID = kSubControlRightID + 1;
+static const DisplayElementID kSubControlUpID = kSubControlLeftID + 1;
+static const DisplayElementID kSubControlCCWID = kSubControlUpID + 1;
+static const DisplayElementID kSubControlCWID = kSubControlCCWID + 1;
+static const DisplayElementID kClawMonitorGreenBallID = kSubControlCWID + 1;
+
+// Norad Delta display IDs.
+
+static const DisplayElementID kGlobeMonitorID = kNeighborhoodDisplayID;
+static const DisplayElementID kGlobeMovieID = kGlobeMonitorID + 14;
+static const DisplayElementID kGlobeCircleLeftID = kGlobeMovieID + 1;
+static const DisplayElementID kGlobeCircleRightID = kGlobeCircleLeftID + 1;
+static const DisplayElementID kGlobeCircleUpID = kGlobeCircleRightID + 1;
+static const DisplayElementID kGlobeCircleDownID = kGlobeCircleUpID + 1;
+static const DisplayElementID kMotionHiliteLeftID = kGlobeCircleDownID + 1;
+static const DisplayElementID kMotionHiliteRightID = kMotionHiliteLeftID + 1;
+static const DisplayElementID kMotionHiliteUpID = kMotionHiliteRightID + 1;
+static const DisplayElementID kMotionHiliteDownID = kMotionHiliteUpID + 1;
+static const DisplayElementID kTargetHiliteUpperLeftID = kMotionHiliteDownID + 1;
+static const DisplayElementID kTargetHiliteUpperRightID = kTargetHiliteUpperLeftID + 1;
+static const DisplayElementID kTargetHiliteLowerLeftID = kTargetHiliteUpperRightID + 1;
+static const DisplayElementID kTargetHiliteLowerRightID = kTargetHiliteLowerLeftID + 1;
+static const DisplayElementID kGlobeUpperNamesID = kTargetHiliteLowerRightID + 1;
+static const DisplayElementID kGlobeLowerNamesID = kGlobeUpperNamesID + 1;
+static const DisplayElementID kGlobeCountdownID = kGlobeLowerNamesID + 1;
+
+// Norad Alpha:
+
+static const DisplayOrder kECRMonitorOrder = kMonitorLayer;
+static const DisplayOrder kECRPanOrder = kECRMonitorOrder + 1;
+
+static const DisplayOrder kN01LeftSideOrder = kMonitorLayer;
+static const DisplayOrder kN01RightSideOrder = kN01LeftSideOrder + 1;
+
+static const DisplayOrder kElevatorControlsOrder = kMonitorLayer;
+
+static const DisplayOrder kPressureLevelsOrder = kMonitorLayer;
+static const DisplayOrder kPressureTypeOrder = kPressureLevelsOrder + 1;
+static const DisplayOrder kPressureUpOrder = kPressureTypeOrder + 1;
+static const DisplayOrder kPressureDownOrder = kPressureUpOrder + 1;
+
+static const DisplayOrder kPlatformOrder = kMonitorLayer;
+
+static const DisplayOrder kSubControlOrder = kMonitorLayer;
+static const DisplayOrder kClawMonitorOrder = kSubControlOrder + 1;
+static const DisplayOrder kSubControlPinchOrder = kClawMonitorOrder + 1;
+static const DisplayOrder kSubControlDownOrder = kSubControlPinchOrder + 1;
+static const DisplayOrder kSubControlRightOrder = kSubControlDownOrder + 1;
+static const DisplayOrder kSubControlLeftOrder = kSubControlRightOrder + 1;
+static const DisplayOrder kSubControlUpOrder = kSubControlLeftOrder + 1;
+static const DisplayOrder kSubControlCCWOrder = kSubControlUpOrder + 1;
+static const DisplayOrder kSubControlCWOrder = kSubControlCCWOrder + 1;
+static const DisplayOrder kClawMonitorGreenBallOrder = kSubControlCWOrder + 1;
+
+// Norad Delta:
+
+static const DisplayOrder kGlobeMonitorLayer = kMonitorLayer;
+static const DisplayOrder kGlobeMovieLayer = kGlobeMonitorLayer + 1;
+static const DisplayOrder kGlobeCircleLayer = kGlobeMovieLayer + 1;
+static const DisplayOrder kGlobeHilitesLayer = kGlobeCircleLayer + 1;
+static const DisplayOrder kGlobeUpperNamesLayer = kGlobeHilitesLayer + 1;
+static const DisplayOrder kGlobeLowerNamesLayer = kGlobeUpperNamesLayer + 1;
+static const DisplayOrder kGlobeCountdownLayer = kGlobeLowerNamesLayer + 1;
+
+// Norad Alpha Tables
+
+static const TimeScale kNoradAlphaMovieScale = 600;
+static const TimeScale kNoradAlphaFramesPerSecond = 15;
+static const TimeScale kNoradAlphaFrameDuration = 40;
+
+// Alternate IDs.
+
+static const AlternateID kAltNoradAlphaNormal = 0;
+
+// Room IDs.
+
+static const RoomID kNorad01 = 0;
+static const RoomID kNorad01East = 1;
+static const RoomID kNorad01West = 2;
+static const RoomID kNorad02 = 3;
+static const RoomID kNorad03 = 4;
+static const RoomID kNorad04 = 5;
+static const RoomID kNorad05 = 6;
+static const RoomID kNorad06 = 7;
+static const RoomID kNorad07 = 8;
+static const RoomID kNorad07North = 9;
+static const RoomID kNorad08 = 10;
+static const RoomID kNorad09 = 11;
+static const RoomID kNorad10 = 12;
+static const RoomID kNorad10East = 13;
+static const RoomID kNorad11 = 14;
+static const RoomID kNorad11South = 15;
+static const RoomID kNorad12 = 16;
+static const RoomID kNorad12South = 17;
+static const RoomID kNorad13 = 18;
+static const RoomID kNorad14 = 19;
+static const RoomID kNorad15 = 20;
+static const RoomID kNorad16 = 21;
+static const RoomID kNorad17 = 22;
+static const RoomID kNorad18 = 23;
+static const RoomID kNorad19 = 24;
+static const RoomID kNorad19West = 25;
+static const RoomID kNorad21 = 26;
+static const RoomID kNorad21West = 27;
+static const RoomID kNorad22 = 28;
+static const RoomID kNorad22West = 29;
+
+// Hot Spot Activation IDs.
+
+
+// Hot Spot IDs.
+
+static const HotSpotID kNorad01ECRSpotID = 5000;
+static const HotSpotID kNorad01GasSpotID = 5001;
+static const HotSpotID kNorad01ECROutSpotID = 5002;
+static const HotSpotID kNorad01GasOutSpotID = 5003;
+static const HotSpotID kNorad01MonitorSpotID = 5004;
+static const HotSpotID kNorad01IntakeSpotID = 5005;
+static const HotSpotID kNorad01DispenseSpotID = 5006;
+static const HotSpotID kNorad01ArSpotID = 5007;
+static const HotSpotID kNorad01CO2SpotID = 5008;
+static const HotSpotID kNorad01HeSpotID = 5009;
+static const HotSpotID kNorad01OSpotID = 5010;
+static const HotSpotID kNorad01NSpotID = 5011;
+static const HotSpotID kN01GasCanisterSpotID = 5012;
+static const HotSpotID kN01ArgonCanisterSpotID = 5013;
+static const HotSpotID kN01AirMaskSpotID = 5014;
+static const HotSpotID kN01NitrogenCanisterSpotID = 5015;
+static const HotSpotID kN01GasOutletSpotID = 5016;
+static const HotSpotID kNorad07DoorSpotID = 5017;
+static const HotSpotID kNorad07DoorOutSpotID = 5018;
+static const HotSpotID kNorad10DoorSpotID = 5019;
+static const HotSpotID kNorad10EastOutSpotID = 5020;
+static const HotSpotID kAlphaUpperPressureDoorUpSpotID = 5021;
+static const HotSpotID kAlphaUpperPressureDoorDownSpotID = 5022;
+static const HotSpotID kNorad11ElevatorSpotID = 5023;
+static const HotSpotID kNorad11ElevatorOutSpotID = 5024;
+static const HotSpotID kNorad11ElevatorDownSpotID = 5025;
+static const HotSpotID kNorad12ElevatorSpotID = 5026;
+static const HotSpotID kNorad12ElevatorOutSpotID = 5027;
+static const HotSpotID kNorad12ElevatorUpSpotID = 5028;
+static const HotSpotID kNorad19MonitorSpotID = 5029;
+static const HotSpotID kNorad19MonitorOutSpotID = 5030;
+static const HotSpotID kNorad19ActivateMonitorSpotID = 5031;
+static const HotSpotID kNorad21WestSpotID = 5032;
+static const HotSpotID kNorad21WestOutSpotID = 5033;
+static const HotSpotID kAlphaLowerPressureDoorUpSpotID = 5034;
+static const HotSpotID kAlphaLowerPressureDoorDownSpotID = 5035;
+static const HotSpotID kNorad22MonitorSpotID = 5036;
+static const HotSpotID kNorad22MonitorOutSpotID = 5037;
+static const HotSpotID kNorad22LaunchPrepSpotID = 5038;
+static const HotSpotID kNorad22ClawControlSpotID = 5039;
+static const HotSpotID kNorad22ClawPinchSpotID = 5040;
+static const HotSpotID kNorad22ClawDownSpotID = 5041;
+static const HotSpotID kNorad22ClawRightSpotID = 5042;
+static const HotSpotID kNorad22ClawLeftSpotID = 5043;
+static const HotSpotID kNorad22ClawUpSpotID = 5044;
+static const HotSpotID kNorad22ClawCCWSpotID = 5045;
+static const HotSpotID kNorad22ClawCWSpotID = 5046;
+
+// Extra sequence IDs.
+
+static const ExtraID kNoradArriveFromTSA = 0;
+static const ExtraID kNorad01RobotTaunt = 1;
+static const ExtraID kNorad01ZoomInWithGasCanister = 2;
+static const ExtraID kN01WGasCanister = 3;
+static const ExtraID kNorad01ZoomOutWithGasCanister = 4;
+static const ExtraID kN01WZEmptyLit = 5;
+static const ExtraID kN01WZGasCanisterDim = 6;
+static const ExtraID kN01WZGasCanisterLit = 7;
+static const ExtraID kN01WZArgonCanisterDim = 8;
+static const ExtraID kN01WZArgonCanisterLit = 9;
+static const ExtraID kN01WZAirMaskDim = 10;
+static const ExtraID kN01WZAirMaskLit = 11;
+static const ExtraID kN01WZNitrogenCanisterDim = 12;
+static const ExtraID kN01WZNitrogenCanisterLit = 13;
+static const ExtraID kNorad04EastDeath = 14;
+static const ExtraID kNorad19PrepSub = 15;
+static const ExtraID kNorad19ExitToSub = 16;
+static const ExtraID kNorad22SouthIntro = 17;
+static const ExtraID kNorad22SouthReply = 18;
+static const ExtraID kNorad22SouthFinish = 19;
+static const ExtraID kN22ClawFromAToB = 20;
+static const ExtraID kN22ClawALoop = 21;
+static const ExtraID kN22ClawAPinch = 22;
+static const ExtraID kN22ClawACounterclockwise = 23;
+static const ExtraID kN22ClawAClockwise = 24;
+static const ExtraID kN22ClawFromBToA = 25;
+static const ExtraID kN22ClawFromBToC = 26;
+static const ExtraID kN22ClawFromBToD = 27;
+static const ExtraID kN22ClawBLoop = 28;
+static const ExtraID kN22ClawBPinch = 29;
+static const ExtraID kN22ClawBCounterclockwise = 30;
+static const ExtraID kN22ClawBClockwise = 31;
+static const ExtraID kN22ClawFromCToB = 32;
+static const ExtraID kN22ClawCLoop = 33;
+static const ExtraID kN22ClawCPinch = 34;
+static const ExtraID kN22ClawCCounterclockwise = 35;
+static const ExtraID kN22ClawCClockwise = 36;
+static const ExtraID kN22ClawFromDToB = 37;
+static const ExtraID kN22ClawDLoop = 38;
+static const ExtraID kN22ClawDPinch = 39;
+static const ExtraID kN22ClawDCounterclockwise = 40;
+static const ExtraID kN22ClawDClockwise = 41;
+
+
+// Norad Delta Extra sequence IDs.
+
+static const ExtraID kArriveFromSubChase = 0;
+static const ExtraID kN59ZoomWithRobot = 1;
+static const ExtraID kN59RobotApproaches = 2;
+static const ExtraID kN59RobotPunchLoop = 3;
+static const ExtraID kN59PlayerWins1 = 4;
+static const ExtraID kN59PlayerWins2 = 5;
+static const ExtraID kN59RobotWins = 6;
+static const ExtraID kN59RobotHeadOpens = 7;
+static const ExtraID kN59Biochips111 = 8;
+static const ExtraID kN59Biochips011 = 9;
+static const ExtraID kN59Biochips101 = 10;
+static const ExtraID kN59Biochips001 = 11;
+static const ExtraID kN59Biochips110 = 12;
+static const ExtraID kN59Biochips010 = 13;
+static const ExtraID kN59Biochips100 = 14;
+static const ExtraID kN59Biochips000 = 15;
+static const ExtraID kN59RobotDisappears = 16;
+static const ExtraID kN60ClawFromAToB = 17;
+static const ExtraID kN60ClawALoop = 18;
+static const ExtraID kN60ClawAPinch = 19;
+static const ExtraID kN60ClawACounterclockwise = 20;
+static const ExtraID kN60ClawAClockwise = 21;
+static const ExtraID kN60ClawFromBToA = 22;
+static const ExtraID kN60ClawFromBToC = 23;
+static const ExtraID kN60ClawFromBToD = 24;
+static const ExtraID kN60ClawBLoop = 25;
+static const ExtraID kN60ClawBPinch = 26;
+static const ExtraID kN60ClawBCounterclockwise = 27;
+static const ExtraID kN60ClawBClockwise = 28;
+static const ExtraID kN60ClawFromCToB = 29;
+static const ExtraID kN60ClawCLoop = 30;
+static const ExtraID kN60ClawCPinch = 31;
+static const ExtraID kN60ClawCCounterclockwise = 32;
+static const ExtraID kN60ClawCClockwise = 33;
+static const ExtraID kN60ClawFromDToB = 34;
+static const ExtraID kN60ClawDLoop = 35;
+static const ExtraID kN60ClawDPinch = 36;
+static const ExtraID kN60ClawDCounterclockwise = 37;
+static const ExtraID kN60ClawDClockwise = 38;
+static const ExtraID kN60RobotApproaches = 39;
+static const ExtraID kN60FirstMistake = 40;
+static const ExtraID kN60ArmActivated = 41;
+static const ExtraID kN60SecondMistake = 42;
+static const ExtraID kN60ArmToPositionB = 43;
+static const ExtraID kN60ThirdMistake = 44;
+static const ExtraID kN60ArmGrabsRobot = 45;
+static const ExtraID kN60FourthMistake = 46;
+static const ExtraID kN60ArmCarriesRobotToPositionA = 47;
+static const ExtraID kN60PlayerFollowsRobotToDoor = 48;
+static const ExtraID kN60RobotHeadOpens = 49;
+static const ExtraID kN60Biochips111 = 50;
+static const ExtraID kN60Biochips011 = 51;
+static const ExtraID kN60Biochips101 = 52;
+static const ExtraID kN60Biochips001 = 53;
+static const ExtraID kN60Biochips110 = 54;
+static const ExtraID kN60Biochips010 = 55;
+static const ExtraID kN60Biochips100 = 56;
+static const ExtraID kN60Biochips000 = 57;
+static const ExtraID kN60RobotDisappears = 58;
+static const ExtraID kNoradDeltaRetinalScanBad = 59;
+static const ExtraID kNoradDeltaRetinalScanGood = 60;
+static const ExtraID kN79BrightView = 61;
+
+// Norad Delta Tables
+
+static const TimeScale kNoradDeltaMovieScale = 600;
+static const TimeScale kNoradDeltaFramesPerSecond = 15;
+static const TimeScale kNoradDeltaFrameDuration = 40;
+
+// Alternate IDs.
+
+static const AlternateID kAltNoradDeltaNormal = 0;
+
+// Room IDs.
+
+static const RoomID kNorad41 = 0;
+static const RoomID kNorad42 = 1;
+static const RoomID kNorad43 = 2;
+static const RoomID kNorad44 = 3;
+static const RoomID kNorad45 = 4;
+static const RoomID kNorad46 = 5;
+static const RoomID kNorad47 = 6;
+static const RoomID kNorad48 = 7;
+static const RoomID kNorad48South = 8;
+static const RoomID kNorad49 = 9;
+static const RoomID kNorad49South = 10;
+static const RoomID kNorad50 = 11;
+static const RoomID kNorad50East = 12;
+static const RoomID kNorad51 = 13;
+static const RoomID kNorad52 = 14;
+static const RoomID kNorad53 = 15;
+static const RoomID kNorad54 = 16;
+static const RoomID kNorad54North = 17;
+static const RoomID kNorad55 = 18;
+static const RoomID kNorad56 = 19;
+static const RoomID kNorad57 = 20;
+static const RoomID kNorad58 = 21;
+static const RoomID kNorad59 = 22;
+static const RoomID kNorad59West = 23;
+static const RoomID kNorad60 = 24;
+static const RoomID kNorad60West = 25;
+static const RoomID kNorad61 = 26;
+static const RoomID kNorad62 = 27;
+static const RoomID kNorad63 = 28;
+static const RoomID kNorad64 = 29;
+static const RoomID kNorad65 = 30;
+static const RoomID kNorad66 = 31;
+static const RoomID kNorad67 = 32;
+static const RoomID kNorad68 = 33;
+static const RoomID kNorad68West = 34;
+static const RoomID kNorad69 = 35;
+static const RoomID kNorad78 = 36;
+static const RoomID kNorad79 = 37;
+static const RoomID kNorad79West = 38;
+
+// Hot Spot Activation IDs.
+
+
+// Hot Spot IDs.
+
+static const HotSpotID kNorad48ElevatorSpotID = 5000;
+static const HotSpotID kNorad48ElevatorOutSpotID = 5001;
+static const HotSpotID kNorad48ElevatorUpSpotID = 5002;
+static const HotSpotID kNorad49ElevatorSpotID = 5003;
+static const HotSpotID kNorad49ElevatorOutSpotID = 5004;
+static const HotSpotID kNorad49ElevatorDownSpotID = 5005;
+static const HotSpotID kNorad50DoorSpotID = 5006;
+static const HotSpotID kNorad50DoorOutSpotID = 5007;
+static const HotSpotID kDeltaUpperPressureDoorUpSpotID = 5008;
+static const HotSpotID kDeltaUpperPressureDoorDownSpotID = 5009;
+static const HotSpotID kNorad54DoorSpotID = 5010;
+static const HotSpotID kNorad54DoorOutSpotID = 5011;
+static const HotSpotID kNorad59WestSpotID = 5012;
+static const HotSpotID kNorad59WestOutSpotID = 5013;
+static const HotSpotID kDeltaLowerPressureDoorUpSpotID = 5014;
+static const HotSpotID kDeltaLowerPressureDoorDownSpotID = 5015;
+static const HotSpotID kDelta59RobotHeadSpotID = 5016;
+static const HotSpotID kDelta59RobotShieldBiochipSpotID = 5017;
+static const HotSpotID kDelta59RobotOpMemBiochipSpotID = 5018;
+static const HotSpotID kDelta59RobotRetinalBiochipSpotID = 5019;
+static const HotSpotID kNorad60MonitorSpotID = 5020;
+static const HotSpotID kNorad60MonitorOutSpotID = 5021;
+static const HotSpotID kNorad60LaunchPrepSpotID = 5022;
+static const HotSpotID kNorad60ClawControlSpotID = 5023;
+static const HotSpotID kNorad60ClawPinchSpotID = 5024;
+static const HotSpotID kNorad60ClawDownSpotID = 5025;
+static const HotSpotID kNorad60ClawRightSpotID = 5026;
+static const HotSpotID kNorad60ClawLeftSpotID = 5027;
+static const HotSpotID kNorad60ClawUpSpotID = 5028;
+static const HotSpotID kNorad60ClawCCWSpotID = 5029;
+static const HotSpotID kNorad60ClawCWSpotID = 5030;
+static const HotSpotID kDelta60RobotHeadSpotID = 5031;
+static const HotSpotID kDelta60RobotShieldBiochipSpotID = 5032;
+static const HotSpotID kDelta60RobotOpMemBiochipSpotID = 5033;
+static const HotSpotID kDelta60RobotRetinalBiochipSpotID = 5034;
+static const HotSpotID kNorad68WestSpotID = 5035;
+static const HotSpotID kNorad68WestOutSpotID = 5036;
+static const HotSpotID kNorad79WestSpotID = 5037;
+static const HotSpotID kNorad79WestOutSpotID = 5038;
+static const HotSpotID kNorad79SpinLeftSpotID = 5039;
+static const HotSpotID kNorad79SpinRightSpotID = 5040;
+static const HotSpotID kNorad79SpinUpSpotID = 5041;
+static const HotSpotID kNorad79SpinDownSpotID = 5042;
+static const HotSpotID kNorad79SiloAreaSpotID = 5043;
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/norad/delta/globegame.cpp b/engines/pegasus/neighborhood/norad/delta/globegame.cpp
new file mode 100644
index 0000000000..06e40c2b3a
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/delta/globegame.cpp
@@ -0,0 +1,1062 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/cursor.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/neighborhood/norad/constants.h"
+#include "pegasus/neighborhood/norad/delta/globegame.h"
+#include "pegasus/neighborhood/norad/delta/noraddelta.h"
+
+namespace Pegasus {
+
+static const TimeValue kDurationPerFrame = 600 / 15;
+static const TimeValue kDurationPerRow = kNumLongSlices * kDurationPerFrame;
+static const short kVerticalDuration = 16;
+
+GlobeTracker::GlobeTracker(Movie *globeMovie, Picture *leftHighlight, Picture *rightHighlight,
+ Picture *upHighlight, Picture *downHighlight) {
+ _globeMovie = globeMovie;
+ _leftHighlight = leftHighlight;
+ _rightHighlight = rightHighlight;
+ _upHighlight = upHighlight;
+ _downHighlight = downHighlight;
+}
+
+void GlobeTracker::setTrackParameters(const Hotspot *trackSpot, GlobeTrackDirection direction) {
+ _trackSpot = trackSpot;
+ _trackDirection = direction;
+
+ TimeValue time, newTime, start;
+
+ switch (_trackDirection) {
+ case kTrackLeft:
+ time = _globeMovie->getTime();
+
+ if (((time / kDurationPerRow) & 1) == 0) {
+ start = (time / kDurationPerRow + 1) * kDurationPerRow;
+ newTime = start + kDurationPerRow - time % kDurationPerRow;
+ } else {
+ start = (time / kDurationPerRow) * kDurationPerRow;
+ newTime = time;
+ }
+
+ _globeMovie->setSegment(start, start + kDurationPerRow);
+
+ if (newTime != time) {
+ _globeMovie->setTime(newTime);
+ _globeMovie->redrawMovieWorld();
+ }
+
+ _globeMovie->setFlags(kLoopTimeBase);
+ break;
+ case kTrackRight:
+ time = _globeMovie->getTime();
+
+ if (((time / kDurationPerRow) & 1) == 0) {
+ start = (time / kDurationPerRow) * kDurationPerRow;
+ newTime = time;
+ } else {
+ start = (time / kDurationPerRow - 1) * kDurationPerRow;
+ newTime = start + kDurationPerRow - time % kDurationPerRow;
+ }
+
+ _globeMovie->setSegment(start, start + kDurationPerRow);
+
+ if (newTime != time) {
+ _globeMovie->setTime(newTime);
+ _globeMovie->redrawMovieWorld();
+ }
+
+ _globeMovie->setFlags(kLoopTimeBase);
+ break;
+ case kTrackUp:
+ case kTrackDown:
+ _globeMovie->setSegment(0, _globeMovie->getDuration());
+ _globeMovie->setFlags(0);
+ break;
+ }
+}
+
+void GlobeTracker::activateHotspots() {
+ Tracker::activateHotspots();
+
+ if (_trackSpot)
+ g_allHotspots.activateOneHotspot(_trackSpot->getObjectID());
+}
+
+bool GlobeTracker::stopTrackingInput(const Input &input) {
+ return !JMPPPInput::isPressingInput(input);
+}
+
+void GlobeTracker::continueTracking(const Input &input) {
+ Common::Point where;
+ input.getInputLocation(where);
+
+ if (g_allHotspots.findHotspot(where) == _trackSpot)
+ trackGlobeMovie();
+ else
+ stopGlobeMovie();
+}
+
+void GlobeTracker::startTracking(const Input &input) {
+ Tracker::startTracking(input);
+ trackGlobeMovie();
+}
+
+void GlobeTracker::stopTracking(const Input &input) {
+ Tracker::stopTracking(input);
+ stopGlobeMovie();
+}
+
+void GlobeTracker::trackGlobeMovie() {
+ TimeValue time;
+
+ switch (_trackDirection) {
+ case kTrackLeft:
+ if (!_globeMovie->isRunning())
+ _globeMovie->start();
+
+ _leftHighlight->show();
+ break;
+ case kTrackRight:
+ if (!_globeMovie->isRunning())
+ _globeMovie->start();
+
+ _rightHighlight->show();
+ break;
+ case kTrackUp:
+ time = _globeMovie->getTime();
+
+ if (_trackTime == 0) {
+ _trackTime = tickCount();
+ } else if ((int)time - (int)kDurationPerRow * 2 >= 0 && (int)tickCount() >= _trackTime + kVerticalDuration) {
+ _trackTime = tickCount();
+ _globeMovie->setTime(time - kDurationPerRow * 2);
+ _globeMovie->redrawMovieWorld();
+ }
+
+ _upHighlight->show();
+ break;
+ case kTrackDown:
+ time = _globeMovie->getTime();
+
+ if (_trackTime == 0) {
+ _trackTime = tickCount();
+ } else if (time + kDurationPerRow * 2 < _globeMovie->getDuration() && (int)tickCount() >= _trackTime + kVerticalDuration) {
+ _trackTime = tickCount();
+ _globeMovie->setTime(time + kDurationPerRow * 2);
+ _globeMovie->redrawMovieWorld();
+ }
+
+ _downHighlight->show();
+ break;
+ }
+}
+
+void GlobeTracker::stopGlobeMovie() {
+ switch (_trackDirection) {
+ case kTrackLeft:
+ _leftHighlight->hide();
+ _globeMovie->stop();
+ break;
+ case kTrackRight:
+ _rightHighlight->hide();
+ _globeMovie->stop();
+ break;
+ case kTrackUp:
+ _upHighlight->hide();
+ _trackTime = tickCount() - kVerticalDuration;
+ break;
+ case kTrackDown:
+ _downHighlight->hide();
+ _trackTime = tickCount() - kVerticalDuration;
+ break;
+ }
+}
+
+// Globe game PICTs:
+static const ResIDType kGlobeCircleLeftPICTID = 300;
+static const ResIDType kGlobeCircleRightPICTID = 301;
+static const ResIDType kGlobeCircleUpPICTID = 302;
+static const ResIDType kGlobeCircleDownPICTID = 303;
+static const ResIDType kTargetUpperLeftPICTID = 304;
+static const ResIDType kTargetUpperRightPICTID = 305;
+static const ResIDType kTargetLowerLeftPICTID = 306;
+static const ResIDType kTargetLowerRightPICTID = 307;
+static const ResIDType kMotionHiliteLeftPICTID = 308;
+static const ResIDType kMotionHiliteRightPICTID = 309;
+static const ResIDType kMotionHiliteUpPICTID = 310;
+static const ResIDType kMotionHiliteDownPICTID = 311;
+
+static const ResIDType kGlobeCountdownDigitsID = 350;
+
+static const int kGlobeCountdownWidth = 28;
+static const int kGlobeCountdownHeight = 12;
+static const int kGlobeCountdownOffset1 = 12;
+static const int kGlobeCountdownOffset2 = 20;
+
+GlobeCountdown::GlobeCountdown(const DisplayElementID id) : IdlerAnimation(id) {
+ _digits.getImageFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kGlobeCountdownDigitsID);
+
+ Common::Rect r;
+ _digits.getSurfaceBounds(r);
+ _digitOffset = r.width() / 10;
+ setScale(1);
+ sizeElement(kGlobeCountdownWidth, kGlobeCountdownHeight);
+}
+
+void GlobeCountdown::setDisplayOrder(const DisplayOrder order) {
+ IdlerAnimation::setDisplayOrder(order);
+}
+
+void GlobeCountdown::show() {
+ IdlerAnimation::show();
+}
+
+void GlobeCountdown::hide() {
+ IdlerAnimation::hide();
+}
+
+void GlobeCountdown::moveElementTo(const CoordType x, const CoordType y) {
+ IdlerAnimation::moveElementTo(x, y);
+}
+
+void GlobeCountdown::setCountdownTime(const int numSeconds) {
+ stop();
+ setSegment(0, numSeconds);
+ setTime(numSeconds);
+}
+
+void GlobeCountdown::startCountdown() {
+ setRate(-1);
+}
+
+void GlobeCountdown::stopCountdown() {
+ stop();
+}
+
+void GlobeCountdown::draw(const Common::Rect &) {
+ Common::Rect r1;
+ _digits.getSurfaceBounds(r1);
+ r1.right = r1.left + _digitOffset;
+ Common::Rect r2 = r1;
+ TimeValue time = getTime();
+
+ Common::Rect bounds;
+ getBounds(bounds);
+
+ if (time > 60 * 9 + 59) {
+ r2.moveTo(bounds.left, bounds.top);
+ r1.moveTo(9 * _digitOffset, 0);
+ _digits.copyToCurrentPort(r1, r2);
+
+ r2.moveTo(bounds.left + kGlobeCountdownOffset1, bounds.top);
+ r1.moveTo(5 * _digitOffset, 0);
+ _digits.copyToCurrentPort(r1, r2);
+
+ r2.moveTo(bounds.left + kGlobeCountdownOffset2, bounds.top);
+ r1.moveTo(9 * _digitOffset, 0);
+ _digits.copyToCurrentPort(r1, r2);
+ } else {
+ r2.moveTo(bounds.left, bounds.top);
+ r1.moveTo((time / 60) * _digitOffset, 0);
+ _digits.copyToCurrentPort(r1, r2);
+
+ time %= 60;
+ r2.moveTo(bounds.left + kGlobeCountdownOffset1, bounds.top);
+ r1.moveTo((time / 10) * _digitOffset, 0);
+ _digits.copyToCurrentPort(r1, r2);
+
+ r2.moveTo(bounds.left + kGlobeCountdownOffset2, bounds.top);
+ r1.moveTo((time % 10) * _digitOffset, 0);
+ _digits.copyToCurrentPort(r1, r2);
+ }
+}
+
+const int16 GlobeGame::_siloCoords[kNumAllSilos][2] = {
+ { 60, -151 }, // Anchorage, Alaska
+ { 6, 39 }, // Addis Ababa, Ethiopia
+ { -22, 44 }, // Antaro, Madagascar
+ { 30, -83 }, // Atlanta, Georgia
+ { -41, 173 }, // Auckland, New Zealand
+ { 39, -78 }, // Baltimore, Maryland
+ { 11, 101 }, // Bangkok, Thailand
+ { 2, -75 }, // Bogota, Colombia
+ { 46, 4 }, // Bonn, Germany
+ { 51, -7 }, // Dublin, Ireland
+ { 28, -1 }, // El Menia, Algeria
+ { 67, -111 }, // Ellesmere, Canada
+ { 43, -107 }, // Glasgow, Montana
+ { 61, -48 }, // Godthab, Greenland
+ { 19, -157 }, // Honolulu, Hawaii
+ { 6, 5 }, // Ibadan, Nigeria
+ { -29, 26 }, // Johannesburg, South Africa
+ { 46, 92 }, // Kobdo, Mongolia
+ { -15, -63 }, // La Paz, Bolivia
+ { -35, -61 }, // La Plata, Argentina
+ { -9, -76 }, // Lima, Peru
+ { 38, -4 }, // Madrid, Spain
+ { -8, -51 }, // Manaus, Brazil
+ { 13, 120 }, // Manila, Phillipines
+ { -35, 143 }, // Melbourne, Australia
+ { 60, -161 }, // Nome, Alaska
+ { -7, 142 }, // Papua, New Guinea
+ { -32, 117 }, // Perth, West Australia
+ { 34, -114 }, // Phoenix, Arizona
+ { 18, -71 }, // Port-Au-Prince, Haiti
+ { 42, -121 }, // Portland, Oregon
+ { 61, -20 }, // Reykjavik, Iceland
+ { -22, -46 }, // Rio de Janeiro
+ { 27, -101 }, // San Antonio, Texas
+ { 34, 126 }, // Seoul, Korea
+ { 37, -87 }, // Saint Louis, Missouri
+ { 60, 30 }, // Saint Petersberg, Russia
+ { 56, 12 }, // Stockholm, Sweden
+ { 51, 105 }, // Svortalsk, Siberia
+ { 36, -96 } // Tulsa, Oklahoma
+};
+
+const int16 GlobeGame::_targetSilo[kNumTargetSilos] = {
+ 14, 9, 1, 33, 6, 8, 34, 31, 38, 21
+};
+
+const short GlobeGame::_timeLimit[kNumTargetSilos] = {
+ 120, 110, 100, 90, 80, 70, 60, 50, 40, 30
+};
+
+const TimeValue GlobeGame::_siloName[kNumTargetSilos][2] = {
+ { kHonoluluIn, kHonoluluOut },
+ { kDublinIn, kDublinOut },
+ { kAddisAbabaIn, kAddisAbabaOut },
+ { kSanAntonioIn, kSanAntonioOut },
+ { kBangkokIn, kBangkokOut },
+ { kBonnIn, kBonnOut },
+ { kSeoulIn, kSeoulOut },
+ { kReykjavikIn, kReykjavikOut },
+ { kSvortalskIn, kSvortalskOut },
+ { kMadridIn, kMadridOut }
+};
+
+// From globe room models
+
+static const GlobeGame::Point3D kCameraLocation = { 0.53f, 4.4f, -0.86f };
+static const GlobeGame::Point3D kGlobeCenter = { -31.5f, 8.0f, 0.0f };
+static const float kGlobeRadius = 8.25f;
+static const int16 kDegreesPerLongSlice = 360 / kNumLongSlices;
+static const int16 kDegreesPerLatSlice = 25;
+static const int16 kLongOrigin = -95;
+
+// Other constants.
+
+static const float kTanFieldOfView = 0.7082373180482f;
+static const float kPicturePlaneDistance = 10.0f; // Completely arbitrary.
+static const int16 kLatError = 2;
+static const int16 kLongError = 2;
+static const TimeValue kGlobeMovieStartTime = 2 * 2 * kNumLongSlices * 600 / 15;
+
+static const TimeValue kTimePerGlobeFrame = 40;
+
+static const NotificationFlags kGlobeSplash1Finished = 1;
+static const NotificationFlags kGlobeTimerExpired = kGlobeSplash1Finished << 1;
+static const NotificationFlags kMaxDeactivatedFinished = kGlobeTimerExpired << 1;
+
+static const NotificationFlags kGlobeNotificationFlags = kGlobeSplash1Finished |
+ kGlobeTimerExpired |
+ kMaxDeactivatedFinished;
+
+static const int16 kSplash1End = 4;
+static const int16 kSplash2End = 5;
+static const int16 kSplash3Start = 8;
+static const int16 kSplash3Stop = 9;
+static const int16 kSplash4Start = 9;
+static const int16 kSplash4Stop = 10;
+static const int16 kNewLaunchSiloTime = 10;
+static const int16 kSiloDeactivatedTime = 11;
+static const int16 kMissileLaunchedTime = 12;
+static const int16 kMaxDeactivatedStart = 13;
+static const int16 kMaxDeactivatedStop = 23;
+
+static const int16 kGamePlaying = 1;
+static const int16 kGameOver = 2;
+
+enum {
+ kGameIntro,
+ kPlayingRobotIntro,
+ kPlayingStrikeAuthorized,
+ kPlayingPrimaryTarget,
+ kPlayingNewSilo1,
+ kPlayingNewSilo2,
+ kPlayingNewSilo3,
+ kPlayingTime,
+ kPlayingInstructions,
+ kWaitingForPlayer,
+ kSiloDeactivated,
+ kRobotTaunting,
+ kDelayingPlayer,
+ kPlayerWon1,
+ kPlayerWon2,
+ kPlayerLost1
+};
+
+// TODO: Use ScummVM equivalent
+static const float kPI = 3.1415926535f;
+
+float degreesToRadians(float angle) {
+ return (angle * kPI) / 180;
+}
+
+float radiansToDegrees(float angle) {
+ return (angle * 180) / kPI;
+}
+
+GlobeGame::GlobeGame(Neighborhood *handler) : GameInteraction(kNoradGlobeGameInteractionID, handler),
+ _monitorMovie(kGlobeMonitorID), _globeMovie(kGlobeMovieID), _upperNamesMovie(kGlobeUpperNamesID),
+ _lowerNamesMovie(kGlobeLowerNamesID), _globeNotification(kNoradGlobeNotificationID, (PegasusEngine *)g_engine),
+ _globeCircleLeft(kGlobeCircleLeftID), _globeCircleRight(kGlobeCircleRightID),
+ _globeCircleUp(kGlobeCircleUpID), _globeCircleDown(kGlobeCircleDownID),
+ _motionHighlightLeft(kMotionHiliteLeftID), _motionHighlightRight(kMotionHiliteRightID),
+ _motionHighlightUp(kMotionHiliteUpID), _motionHighlightDown(kMotionHiliteDownID),
+ _targetHighlightUpperLeft(kTargetHiliteUpperLeftID), _targetHighlightUpperRight(kTargetHiliteUpperRightID),
+ _targetHighlightLowerLeft(kTargetHiliteLowerLeftID), _targetHighlightLowerRight(kTargetHiliteLowerRightID),
+ _globeTracker(&_globeMovie, &_motionHighlightLeft, &_motionHighlightRight, &_motionHighlightUp,
+ &_motionHighlightDown), _countdown(kGlobeCountdownID) {
+ _neighborhoodNotification = handler->getNeighborhoodNotification();
+}
+
+void GlobeGame::openInteraction() {
+ _monitorMovie.initFromMovieFile("Images/Norad Delta/N79 Left Monitor");
+ _monitorMovie.moveElementTo(kGlobeMonitorLeft, kGlobeMonitorTop);
+ _monitorMovie.setDisplayOrder(kGlobeMonitorLayer);
+ _monitorMovie.startDisplaying();
+ _monitorMovie.setSegment(0, kSplash1End * _monitorMovie.getScale());
+ _monitorMovie.show();
+
+ _monitorCallBack.setNotification(&_globeNotification);
+ _monitorCallBack.initCallBack(&_monitorMovie, kCallBackAtExtremes);
+ _monitorCallBack.setCallBackFlag(kGlobeSplash1Finished);
+ _monitorCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+
+ _upperNamesMovie.initFromMovieFile("Images/Norad Delta/Upper Names");
+ _upperNamesMovie.moveElementTo(kGlobeUpperNamesLeft, kGlobeUpperNamesTop);
+ _upperNamesMovie.setDisplayOrder(kGlobeUpperNamesLayer);
+ _upperNamesMovie.startDisplaying();
+
+ _lowerNamesMovie.initFromMovieFile("Images/Norad Delta/Lower Names");
+ _lowerNamesMovie.moveElementTo(kGlobeLowerNamesLeft, kGlobeLowerNamesTop);
+ _lowerNamesMovie.setDisplayOrder(kGlobeLowerNamesLayer);
+ _lowerNamesMovie.startDisplaying();
+
+ _globeMovie.initFromMovieFile("Images/Norad Delta/Spinning Globe");
+ _globeMovie.moveElementTo(kGlobeLeft, kGlobeTop);
+ _globeMovie.setDisplayOrder(kGlobeMovieLayer);
+ _globeMovie.startDisplaying();
+ _globeMovie.setTime(kGlobeMovieStartTime);
+ _globeMovie.redrawMovieWorld();
+
+ _globeCircleLeft.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kGlobeCircleLeftPICTID, true);
+ _globeCircleLeft.moveElementTo(kGlobeCircleLeftLeft, kGlobeCircleLeftTop);
+ _globeCircleLeft.setDisplayOrder(kGlobeCircleLayer);
+ _globeCircleLeft.startDisplaying();
+
+ _globeCircleRight.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kGlobeCircleRightPICTID, true);
+ _globeCircleRight.moveElementTo(kGlobeCircleRightLeft, kGlobeCircleRightTop);
+ _globeCircleRight.setDisplayOrder(kGlobeCircleLayer);
+ _globeCircleRight.startDisplaying();
+
+ _globeCircleUp.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kGlobeCircleUpPICTID, true);
+ _globeCircleUp.moveElementTo(kGlobeCircleUpLeft, kGlobeCircleUpTop);
+ _globeCircleUp.setDisplayOrder(kGlobeCircleLayer);
+ _globeCircleUp.startDisplaying();
+
+ _globeCircleDown.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kGlobeCircleDownPICTID, true);
+ _globeCircleDown.moveElementTo(kGlobeCircleDownLeft, kGlobeCircleDownTop);
+ _globeCircleDown.setDisplayOrder(kGlobeCircleLayer);
+ _globeCircleDown.startDisplaying();
+
+ _motionHighlightLeft.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kMotionHiliteLeftPICTID, true);
+ _motionHighlightLeft.moveElementTo(kGlobeLeftMotionHiliteLeft, kGlobeLeftMotionHiliteTop);
+ _motionHighlightLeft.setDisplayOrder(kGlobeHilitesLayer);
+ _motionHighlightLeft.startDisplaying();
+
+ _motionHighlightRight.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kMotionHiliteRightPICTID, true);
+ _motionHighlightRight.moveElementTo(kGlobeRightMotionHiliteLeft, kGlobeRightMotionHiliteTop);
+ _motionHighlightRight.setDisplayOrder(kGlobeCircleLayer);
+ _motionHighlightRight.startDisplaying();
+
+ _motionHighlightUp.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kMotionHiliteUpPICTID, true);
+ _motionHighlightUp.moveElementTo(kGlobeUpMotionHiliteLeft, kGlobeUpMotionHiliteTop);
+ _motionHighlightUp.setDisplayOrder(kGlobeHilitesLayer);
+ _motionHighlightUp.startDisplaying();
+
+ _motionHighlightDown.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kMotionHiliteDownPICTID, true);
+ _motionHighlightDown.moveElementTo(kGlobeDownMotionHiliteLeft, kGlobeDownMotionHiliteTop);
+ _motionHighlightDown.setDisplayOrder(kGlobeHilitesLayer);
+ _motionHighlightDown.startDisplaying();
+
+ _targetHighlightUpperLeft.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kTargetUpperLeftPICTID, true);
+ _targetHighlightUpperLeft.moveElementTo(kGlobeUpperLeftHiliteLeft, kGlobeUpperLeftHiliteTop);
+ _targetHighlightUpperLeft.setDisplayOrder(kGlobeHilitesLayer);
+ _targetHighlightUpperLeft.startDisplaying();
+
+ _targetHighlightUpperRight.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kTargetUpperRightPICTID, true);
+ _targetHighlightUpperRight.moveElementTo(kGlobeUpperRightHiliteLeft, kGlobeUpperRightHiliteTop);
+ _targetHighlightUpperRight.setDisplayOrder(kGlobeHilitesLayer);
+ _targetHighlightUpperRight.startDisplaying();
+
+ _targetHighlightLowerLeft.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kTargetLowerLeftPICTID, true);
+ _targetHighlightLowerLeft.moveElementTo(kGlobeLowerLeftHiliteLeft, kGlobeLowerLeftHiliteTop);
+ _targetHighlightLowerLeft.setDisplayOrder(kGlobeHilitesLayer);
+ _targetHighlightLowerLeft.startDisplaying();
+
+ _targetHighlightLowerRight.initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kTargetLowerRightPICTID, true);
+ _targetHighlightLowerRight.moveElementTo(kGlobeLowerRightHiliteLeft, kGlobeLowerRightHiliteTop);
+ _targetHighlightLowerRight.setDisplayOrder(kGlobeHilitesLayer);
+ _targetHighlightLowerRight.startDisplaying();
+
+ _countdown.setDisplayOrder(kGlobeCountdownLayer);
+ _countdown.moveElementTo(kGlobeCountdownLeft, kGlobeCountdownTop);
+ _countdown.startDisplaying();
+ _countdown.setCountdownTime(_timeLimit[0]);
+
+ _countdownCallBack.setNotification(&_globeNotification);
+ _countdownCallBack.initCallBack(&_countdown, kCallBackAtExtremes);
+ _countdownCallBack.setCallBackFlag(kGlobeTimerExpired);
+ _countdownCallBack.scheduleCallBack(kTriggerAtStart, 0, 0);
+
+ _globeNotification.notifyMe(this, kGlobeNotificationFlags, kGlobeNotificationFlags);
+
+ _gameState = kGameIntro;
+ _currentSiloIndex = 0;
+ _playedInstructions = false;
+
+ _neighborhoodNotification->notifyMe(this, kDelayCompletedFlag | kSpotSoundCompletedFlag, kDelayCompletedFlag | kSpotSoundCompletedFlag);
+}
+
+void GlobeGame::initInteraction() {
+ _monitorMovie.start();
+ _monitorMovie.redrawMovieWorld();
+}
+
+void GlobeGame::closeInteraction() {
+ _monitorMovie.stop();
+ _monitorMovie.stopDisplaying();
+ _monitorMovie.releaseMovie();
+ _monitorCallBack.releaseCallBack();
+
+ _globeMovie.stop();
+ _globeMovie.stopDisplaying();
+ _globeMovie.releaseMovie();
+ _globeNotification.cancelNotification(this);
+
+ _upperNamesMovie.stop();
+ _upperNamesMovie.stopDisplaying();
+ _upperNamesMovie.releaseMovie();
+
+ _lowerNamesMovie.stop();
+ _lowerNamesMovie.stopDisplaying();
+ _lowerNamesMovie.releaseMovie();
+
+ _countdown.hide();
+ _countdown.stopDisplaying();
+ _countdownCallBack.releaseCallBack();
+
+ _globeCircleLeft.stopDisplaying();
+ _globeCircleLeft.deallocateSurface();
+ _globeCircleRight.stopDisplaying();
+ _globeCircleRight.deallocateSurface();
+ _globeCircleUp.stopDisplaying();
+ _globeCircleUp.deallocateSurface();
+ _globeCircleDown.stopDisplaying();
+ _globeCircleDown.deallocateSurface();
+
+ _motionHighlightLeft.stopDisplaying();
+ _motionHighlightLeft.deallocateSurface();
+ _motionHighlightRight.stopDisplaying();
+ _motionHighlightRight.deallocateSurface();
+ _motionHighlightUp.stopDisplaying();
+ _motionHighlightUp.deallocateSurface();
+ _motionHighlightDown.stopDisplaying();
+ _motionHighlightDown.deallocateSurface();
+
+ _targetHighlightUpperLeft.stopDisplaying();
+ _targetHighlightUpperLeft.deallocateSurface();
+ _targetHighlightUpperRight.stopDisplaying();
+ _targetHighlightUpperRight.deallocateSurface();
+ _targetHighlightLowerLeft.stopDisplaying();
+ _targetHighlightLowerLeft.deallocateSurface();
+ _targetHighlightLowerRight.stopDisplaying();
+ _targetHighlightLowerRight.deallocateSurface();
+
+ _neighborhoodNotification->cancelNotification(this);
+}
+
+void GlobeGame::receiveNotification(Notification *notification, const NotificationFlags flags) {
+ TimeScale scale = _monitorMovie.getScale();
+
+ if (notification == _neighborhoodNotification) {
+ switch (_gameState) {
+ case kPlayingRobotIntro:
+ _monitorMovie.stop();
+ _monitorMovie.setSegment(0, _monitorMovie.getDuration());
+ _monitorMovie.setTime(kSplash2End * scale - 1);
+ _monitorMovie.setFlags(0);
+
+ _owner->requestDelay(1, 2, kFilterNoInput, 0);
+ _owner->requestSpotSound(kStrikeAuthorizedIn, kStrikeAuthorizedOut,
+ kFilterNoInput, kSpotSoundCompletedFlag);
+ _gameState = kPlayingStrikeAuthorized;
+ break;
+ case kPlayingStrikeAuthorized:
+ _monitorMovie.setSegment(kSplash3Start * scale, kSplash3Stop * scale);
+ _monitorMovie.setTime(kSplash3Start * scale);
+ _monitorMovie.redrawMovieWorld();
+
+ _owner->requestDelay(1, 3, kFilterNoInput, 0);
+ _owner->requestSpotSound(kPrimaryTargetIn, kPrimaryTargetOut, kFilterNoInput, 0);
+ _owner->requestDelay(1, 5, kFilterNoInput, kDelayCompletedFlag);
+ _monitorMovie.start();
+ _gameState = kPlayingPrimaryTarget;
+ break;
+ case kPlayingPrimaryTarget:
+ _monitorMovie.stop();
+ _monitorMovie.setSegment(0, _monitorMovie.getDuration());
+ _monitorMovie.setTime(kNewLaunchSiloTime * scale);
+ _owner->requestSpotSound(kNewLaunchSiloIn, kNewLaunchSiloOut, kFilterNoInput,
+ kSpotSoundCompletedFlag);
+ _gameState = kPlayingNewSilo1;
+ break;
+ case kPlayingNewSilo1:
+ _monitorMovie.stop();
+ _monitorMovie.setSegment(0, _monitorMovie.getDuration());
+ _owner->requestDelay(1, 3, kFilterNoInput, kDelayCompletedFlag);
+ _gameState = kPlayingNewSilo2;
+ break;
+ case kPlayingNewSilo2:
+ _upperNamesMovie.show();
+ _upperNamesMovie.setTime(_currentSiloIndex * _upperNamesMovie.getScale());
+ _upperNamesMovie.redrawMovieWorld();
+ _monitorMovie.setTime(kSplash4Stop * scale - 1);
+ _monitorMovie.redrawMovieWorld();
+ _owner->requestSpotSound(_siloName[_currentSiloIndex][0], _siloName[_currentSiloIndex][1], kFilterNoInput, 0);
+ _owner->requestDelay(1, 3, kFilterNoInput, 0);
+ _owner->requestSpotSound(kLaunchToProceedIn, kLaunchToProceedOut, kFilterNoInput, 0);
+ _owner->requestDelay(1, 5, kFilterNoInput, kDelayCompletedFlag);
+ _gameState = kPlayingNewSilo3;
+ break;
+ case kPlayingNewSilo3:
+ _countdown.stopCountdown();
+ _countdown.setCountdownTime(_timeLimit[_currentSiloIndex]);
+ _countdown.show();
+ _gameState = kPlayingTime;
+
+ if (_timeLimit[_currentSiloIndex] >= 120)
+ _owner->requestSpotSound(kTwoMinutesIn, kTwoMinutesOut, kFilterNoInput, 0);
+ else if (_timeLimit[_currentSiloIndex] >= 60)
+ _owner->requestSpotSound(kOneMinuteIn, kOneMinuteOut, kFilterNoInput, 0);
+
+ switch (_timeLimit[_currentSiloIndex] % 60) {
+ case 0:
+ _owner->requestDelay(1, 5, kFilterNoInput, kDelayCompletedFlag);
+ break;
+ case 10:
+ _owner->requestDelay(1, 5, kFilterNoInput, 0);
+ _owner->requestSpotSound(kTenSecondsIn, kTenSecondsOut, kFilterNoInput,
+ kSpotSoundCompletedFlag);
+ break;
+ case 20:
+ _owner->requestDelay(1, 5, kFilterNoInput, 0);
+ _owner->requestSpotSound(kTwentySecondsIn, kTwentySecondsOut,
+ kFilterNoInput, kSpotSoundCompletedFlag);
+ break;
+ case 30:
+ _owner->requestDelay(1, 5, kFilterNoInput, 0);
+ _owner->requestSpotSound(kThirtySecondsIn, kThirtySecondsOut,
+ kFilterNoInput, kSpotSoundCompletedFlag);
+ break;
+ case 40:
+ _owner->requestDelay(1, 5, kFilterNoInput, 0);
+ _owner->requestSpotSound(kFortySecondsIn, kFortySecondsOut,
+ kFilterNoInput, kSpotSoundCompletedFlag);
+ break;
+ case 50:
+ _owner->requestDelay(1, 5, kFilterNoInput, 0);
+ _owner->requestSpotSound(kFiftySecondsIn, kFiftySecondsOut,
+ kFilterNoInput, kSpotSoundCompletedFlag);
+ break;
+ }
+ case kPlayingTime:
+ _gameState = kPlayingInstructions;
+ _globeMovie.show();
+ _globeCircleLeft.show();
+ _globeCircleRight.show();
+ _globeCircleUp.show();
+ _globeCircleDown.show();
+
+ if (_playedInstructions) {
+ receiveNotification(notification, flags);
+ } else {
+ _owner->requestSpotSound(kToDeactivateIn, kToDeactivateOut, kFilterNoInput,
+ kSpotSoundCompletedFlag);
+ _playedInstructions = true;
+ }
+ break;
+ case kPlayingInstructions:
+ _gameState = kWaitingForPlayer;
+ _countdown.startCountdown();
+ break;
+ case kSiloDeactivated:
+ _gameState = kRobotTaunting;
+
+ switch (_currentSiloIndex) {
+ case 3:
+ _owner->requestSpotSound(kYouCannotPossiblyIn, kYouCannotPossiblyOut,
+ kFilterNoInput, kSpotSoundCompletedFlag);
+ break;
+ case 5:
+ _owner->requestSpotSound(kYouWillFailIn, kYouWillFailOut, kFilterNoInput,
+ kSpotSoundCompletedFlag);
+ break;
+ case 7:
+ _owner->requestSpotSound(kGiveUpHumanIn, kGiveUpHumanOut, kFilterNoInput,
+ kSpotSoundCompletedFlag);
+ break;
+ case 9:
+ _owner->requestSpotSound(kYouAreRunningIn, kYouAreRunningOut,
+ kFilterNoInput, kSpotSoundCompletedFlag);
+ break;
+ default:
+ _owner->requestSpotSound(kNewLaunchSiloIn, kNewLaunchSiloOut,
+ kFilterNoInput, kSpotSoundCompletedFlag);
+ _monitorMovie.setTime(kNewLaunchSiloTime * scale);
+ _monitorMovie.redrawMovieWorld();
+ _gameState = kPlayingNewSilo1;
+ break;
+ }
+ break;
+ case kRobotTaunting:
+ _owner->requestDelay(1, 1, kFilterNoInput, 0);
+ _owner->requestSpotSound(kNewLaunchSiloIn, kNewLaunchSiloOut, kFilterNoInput, kSpotSoundCompletedFlag);
+ _monitorMovie.setTime(kNewLaunchSiloTime * scale);
+ _monitorMovie.redrawMovieWorld();
+ _gameState = kPlayingNewSilo1;
+ break;
+ case kDelayingPlayer:
+ _gameState = kWaitingForPlayer;
+ break;
+ case kPlayerLost1:
+ _owner->recallToTSAFailure();
+ break;
+ case kPlayerWon2:
+ ((NoradDelta *)_owner)->finishedGlobeGame();
+ _owner->requestDeleteCurrentInteraction();
+ break;
+ default:
+ break;
+ }
+ } else if (notification == &_globeNotification) {
+ ExtraTable::Entry entry;
+
+ switch (flags) {
+ case kGlobeSplash1Finished:
+ _owner->getExtraEntry(kN79BrightView, entry);
+ _monitorMovie.stop();
+ _monitorMovie.setSegment(kSplash1End * scale, kSplash2End * scale);
+ _monitorMovie.setFlags(kLoopTimeBase);
+ _monitorMovie.start();
+ _owner->showViewFrame(entry.movieStart);
+ _owner->requestSpotSound(kIJustBrokeIn, kIJustBrokeOut, kFilterNoInput, 0);
+ _owner->requestDelay(1, 2, kFilterNoInput, kDelayCompletedFlag);
+ _gameState = kPlayingRobotIntro;
+ break;
+ case kGlobeTimerExpired:
+ // Missile launched, player loses.
+ _owner->requestSpotSound(kMissileLaunchedIn, kMissileLaunchedOut, kFilterNoInput, kSpotSoundCompletedFlag);
+ _gameState = kPlayerLost1;
+ break;
+ case kMaxDeactivatedFinished:
+ _monitorMovie.stop();
+ _monitorMovie.setSegment(0, _monitorMovie.getDuration());
+ _owner->requestDelay(1, 2, kFilterNoInput, 0);
+ _owner->requestSpotSound(kTheOnlyGoodHumanIn, kTheOnlyGoodHumanOut, kFilterNoInput, 0);
+ _owner->requestDelay(1, 2, kFilterNoInput, kDelayCompletedFlag);
+ _gameState = kPlayerWon2;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+// Prevent the player from getting up until the game is over.
+
+void GlobeGame::handleInput(const Input &input, const Hotspot *cursorSpot) {
+ Common::Point where;
+ input.getInputLocation(where);
+ Hotspot *spot = g_allHotspots.findHotspot(where);
+
+ if (((PegasusEngine *)g_engine)->_cursor->isVisible() && spot != 0 &&
+ spot->getObjectID() == kNorad79SiloAreaSpotID && findClickedSilo(input) != -1) {
+ _targetHighlightUpperLeft.show();
+ _targetHighlightUpperRight.show();
+ _targetHighlightLowerLeft.show();
+ _targetHighlightLowerRight.show();
+ } else {
+ _targetHighlightUpperLeft.hide();
+ _targetHighlightUpperRight.hide();
+ _targetHighlightLowerLeft.hide();
+ _targetHighlightLowerRight.hide();
+ }
+
+ // Interrupt certain inputs to prevent player from switching modes.
+ InputHandler::handleInput(input, cursorSpot);
+}
+
+int16 GlobeGame::findClickedSilo(const Input &input) {
+ Common::Point screenPoint;
+ input.getInputLocation(screenPoint);
+ screenPoint.x -= kNavAreaLeft;
+ screenPoint.y -= kNavAreaTop;
+
+ Line3D ray;
+ screenPointTo3DPoint(screenPoint.x, screenPoint.y, ray.pt2);
+ ray.pt1 = kCameraLocation;
+
+ Point3D globePoint;
+ if (lineHitsGlobe(ray, globePoint)) {
+ int16 latOrigin, longOrigin, latitude, longitude;
+ globeMovieFrameToOrigin(_globeMovie.getTime() / kTimePerGlobeFrame, latOrigin, longOrigin);
+ globePointToLatLong(globePoint, latOrigin, longOrigin, latitude, longitude);
+
+ for (int16 i = 0; i < kNumAllSilos; i++)
+ if (_siloCoords[i][0] >= latitude - kLatError && _siloCoords[i][0] <= latitude + kLatError &&
+ _siloCoords[i][1] >= longitude - kLongError && _siloCoords[i][1] <= longitude + kLongError)
+ return i;
+ }
+
+ return -1;
+}
+
+void GlobeGame::spinGlobe(const Input &input, const Hotspot *spot, GlobeTrackDirection trackDirection) {
+ _globeTracker.setTrackParameters(spot, trackDirection);
+ _globeTracker.startTracking(input);
+}
+
+void GlobeGame::clickGlobe(const Input &input) {
+ int16 newSilo = findClickedSilo(input);
+
+ if (newSilo != -1) {
+ _targetHighlightUpperLeft.hide();
+ _targetHighlightUpperRight.hide();
+ _targetHighlightLowerLeft.hide();
+ _targetHighlightLowerRight.hide();
+ _lowerNamesMovie.show();
+ _lowerNamesMovie.setTime(newSilo * _lowerNamesMovie.getScale());
+ _lowerNamesMovie.redrawMovieWorld();
+ _owner->requestSpotSound(kSiloBeepIn, kSiloBeepOut, kFilterNoInput, 0);
+
+ if (newSilo == _targetSilo[_currentSiloIndex]) {
+ _currentSiloIndex++;
+ _countdown.stopCountdown();
+ _owner->requestSpotSound(kSiloDeactivatedIn, kSiloDeactivatedOut, kFilterNoInput, 0);
+
+ if (_currentSiloIndex == kNumTargetSilos) {
+ // Player won.
+ _owner->requestDelay(1, 2, kFilterNoInput, 0);
+ _upperNamesMovie.hide();
+ _lowerNamesMovie.hide();
+ _countdown.hide();
+ _monitorMovie.setSegment(kMaxDeactivatedStart * _monitorMovie.getScale(),
+ kMaxDeactivatedStop * _monitorMovie.getScale());
+ _monitorMovie.setTime(kMaxDeactivatedStart * _monitorMovie.getScale());
+ _monitorCallBack.setCallBackFlag(kMaxDeactivatedFinished);
+ _monitorCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ _monitorMovie.start();
+ _owner->requestSpotSound(kMaximumDeactivationIn, kMaximumDeactivationOut,
+ kFilterNoInput, kSpotSoundCompletedFlag);
+ _gameState = kPlayerWon1;
+ } else {
+ _owner->requestDelay(2, 1, kFilterNoInput, kDelayCompletedFlag);
+ _upperNamesMovie.hide();
+ _lowerNamesMovie.hide();
+ _countdown.hide();
+ _monitorMovie.setTime(kSiloDeactivatedTime * _monitorMovie.getScale());
+ _monitorMovie.redrawMovieWorld();
+ _gameState = kSiloDeactivated;
+ }
+ } else {
+ _owner->requestDelay(5, 1, kFilterNoInput, kDelayCompletedFlag);
+ _gameState = kDelayingPlayer;
+ // Play "incorrect" sound?
+ }
+ }
+}
+
+void GlobeGame::clickInHotspot(const Input &input, const Hotspot *spot) {
+ switch (spot->getObjectID()) {
+ case kNorad79SpinLeftSpotID:
+ spinGlobe(input, spot, kTrackLeft);
+ break;
+ case kNorad79SpinRightSpotID:
+ spinGlobe(input, spot, kTrackRight);
+ break;
+ case kNorad79SpinUpSpotID:
+ spinGlobe(input, spot, kTrackUp);
+ break;
+ case kNorad79SpinDownSpotID:
+ spinGlobe(input, spot, kTrackDown);
+ break;
+ case kNorad79SiloAreaSpotID:
+ clickGlobe(input);
+ break;
+ default:
+ GameInteraction::clickInHotspot(input, spot);
+ break;
+ }
+}
+
+void GlobeGame::activateHotspots() {
+ GameInteraction::activateHotspots();
+
+ switch (_gameState) {
+ case kWaitingForPlayer:
+ g_allHotspots.deactivateOneHotspot(kNorad79WestOutSpotID);
+ g_allHotspots.activateOneHotspot(kNorad79SpinLeftSpotID);
+ g_allHotspots.activateOneHotspot(kNorad79SpinRightSpotID);
+ g_allHotspots.activateOneHotspot(kNorad79SpinUpSpotID);
+ g_allHotspots.activateOneHotspot(kNorad79SpinDownSpotID);
+ g_allHotspots.activateOneHotspot(kNorad79SiloAreaSpotID);
+ break;
+ default:
+ g_allHotspots.deactivateOneHotspot(kNorad79WestOutSpotID);
+ break;
+ }
+}
+
+void GlobeGame::globeMovieFrameToOrigin(int16 frameNum, int16 &latOrigin, int16 &longOrigin) {
+ latOrigin = kDegreesPerLatSlice * 2 - (frameNum / (kNumLongSlices * 2)) * kDegreesPerLatSlice;
+ frameNum %= kNumLongSlices * 2;
+
+ if (frameNum >= kNumLongSlices)
+ longOrigin = kLongOrigin + (kNumLongSlices * 2 - 1 - frameNum) * kDegreesPerLongSlice;
+ else
+ longOrigin = kLongOrigin + frameNum * kDegreesPerLongSlice;
+
+ if (longOrigin > 180)
+ longOrigin -= 360;
+}
+
+void GlobeGame::globePointToLatLong(const GlobeGame::Point3D &pt, int16 latOrigin, int16 longOrigin,
+ int16 &latitude, int16 &longitude) {
+ Point3D scratch = pt;
+
+ // Translate globe center to origin.
+ scratch.x -= kGlobeCenter.x;
+ scratch.y -= kGlobeCenter.y;
+ scratch.z -= kGlobeCenter.z;
+
+ // Rotate around z axis latOrigin degrees to bring equator parallel with XZ plane
+ float theta = degreesToRadians(latOrigin);
+ float s = sin(theta);
+ float c = cos(theta);
+ float x = scratch.x * c - scratch.y * s;
+ float y = scratch.y * c + scratch.x * s;
+ scratch.x = x;
+ scratch.y = y;
+
+ // Calculate latitude
+ latitude = (int16)radiansToDegrees(asin(scratch.y / kGlobeRadius));
+
+ // Rotate around y axis longOrigin degrees to bring longitude 0 to positive X axis
+ theta = degreesToRadians(longOrigin);
+ s = sin(theta);
+ c = cos(theta);
+ x = scratch.x * c - scratch.z * s;
+ float z = scratch.z * c + scratch.x * s;
+ scratch.x = x;
+ scratch.z = z;
+
+ // Calculate longitude
+ longitude = (int16)radiansToDegrees(acos(scratch.x / sqrt(scratch.x * scratch.x + scratch.z * scratch.z)));
+
+ if (scratch.z < 0)
+ longitude = -longitude;
+}
+
+// h, v in [0, 511][0, 255]
+// Looking down negative x axis.
+void GlobeGame::screenPointTo3DPoint(int16 h, int16 v, GlobeGame::Point3D &pt) {
+ pt.x = kCameraLocation.x - kPicturePlaneDistance;
+ pt.y = kCameraLocation.y + (128 - v) * kPicturePlaneDistance * kTanFieldOfView / 256;
+ pt.z = kCameraLocation.z + (h - 256) * kPicturePlaneDistance * kTanFieldOfView / 256;
+}
+
+// Fundamentals of Three-Dimensional Graphics, by Alan Watt
+// pp. 163-164
+bool GlobeGame::lineHitsGlobe(const GlobeGame::Line3D &line, GlobeGame::Point3D &pt) {
+ float i = line.pt2.x - line.pt1.x;
+ float j = line.pt2.y - line.pt1.y;
+ float k = line.pt2.z - line.pt1.z;
+ float a = i * i + j * j + k * k;
+ float b = 2 * i * (line.pt1.x - kGlobeCenter.x) + 2 * j * (line.pt1.y - kGlobeCenter.y) +
+ 2 * k * (line.pt1.z - kGlobeCenter.z);
+ float c = kGlobeCenter.x * kGlobeCenter.x + kGlobeCenter.y * kGlobeCenter.y +
+ kGlobeCenter.z * kGlobeCenter.z + line.pt1.x * line.pt1.x + line.pt1.y * line.pt1.y +
+ line.pt1.z * line.pt1.z + -2 * (kGlobeCenter.x * line.pt1.x + kGlobeCenter.y * line.pt1.y +
+ kGlobeCenter.z * line.pt1.z) - kGlobeRadius * kGlobeRadius;
+
+ // Solve quadratic equation of a, b, c.
+ float t = b * b - 4 * a * c;
+
+ if (t >= 0.0f) {
+ // Return smaller root, which corresponds to closest intersection point.
+ t = (-b - sqrt(t)) / (2 * a);
+ pt.x = i * t + line.pt1.x;
+ pt.y = j * t + line.pt1.y;
+ pt.z = k * t + line.pt1.z;
+ return true;
+ }
+
+ return false;
+}
+
+bool GlobeGame::canSolve() {
+ return _gameState != kPlayerWon1 && _gameState != kPlayerWon2 && _gameState != kPlayerLost1;
+}
+
+void GlobeGame::doSolve() {
+ _owner->requestDelay(1, 2, kFilterNoInput, 0);
+ _upperNamesMovie.hide();
+ _lowerNamesMovie.hide();
+ _countdown.hide();
+ _monitorMovie.setSegment(kMaxDeactivatedStart * _monitorMovie.getScale(), kMaxDeactivatedStop * _monitorMovie.getScale());
+ _monitorMovie.setTime(kMaxDeactivatedStart * _monitorMovie.getScale());
+ _monitorCallBack.setCallBackFlag(kMaxDeactivatedFinished);
+ _monitorCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ _monitorMovie.start();
+ _owner->requestSpotSound(kMaximumDeactivationIn, kMaximumDeactivationOut, kFilterNoInput, kSpotSoundCompletedFlag);
+ _gameState = kPlayerWon1;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/norad/delta/globegame.h b/engines/pegasus/neighborhood/norad/delta/globegame.h
new file mode 100644
index 0000000000..73ed48866f
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/delta/globegame.h
@@ -0,0 +1,169 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_NORAD_DELTA_GLOBEGAME_H
+#define PEGASUS_NEIGHBORHOOD_NORAD_DELTA_GLOBEGAME_H
+
+#include "pegasus/interaction.h"
+#include "pegasus/movie.h"
+#include "pegasus/notification.h"
+
+namespace Pegasus {
+
+enum GlobeTrackDirection {
+ kTrackLeft,
+ kTrackRight,
+ kTrackUp,
+ kTrackDown
+};
+
+// This class assumes that the globe movie is built at 15 frames per second with a
+// time scale of 600, yielding 40 time unit per frame.
+
+class GlobeTracker : public Tracker {
+public:
+ GlobeTracker(Movie *, Picture *, Picture *, Picture *, Picture *);
+ virtual ~GlobeTracker() {}
+
+ void setTrackParameters(const Hotspot *, GlobeTrackDirection);
+ void continueTracking(const Input &);
+ void startTracking(const Input &);
+ void stopTracking(const Input &);
+ void activateHotspots();
+ bool stopTrackingInput(const Input &);
+
+protected:
+ void trackGlobeMovie();
+ void stopGlobeMovie();
+
+ Movie *_globeMovie;
+ Picture *_leftHighlight;
+ Picture *_rightHighlight;
+ Picture *_upHighlight;
+ Picture *_downHighlight;
+ const Hotspot *_trackSpot;
+ int _trackTime;
+ GlobeTrackDirection _trackDirection;
+};
+
+class GlobeCountdown : public IdlerAnimation {
+public:
+ GlobeCountdown(const DisplayElementID);
+ virtual ~GlobeCountdown() {}
+
+ void setCountdownTime(const int);
+ void startCountdown();
+ void stopCountdown();
+
+ void setDisplayOrder(const DisplayOrder);
+ void show();
+ void hide();
+ void moveElementTo(const CoordType, const CoordType);
+
+ void draw(const Common::Rect &);
+
+protected:
+ Surface _digits;
+ int16 _digitOffset;
+};
+
+static const int16 kNumAllSilos = 40;
+static const int16 kNumTargetSilos = 10;
+static const int16 kNumLongSlices = 72;
+
+class GlobeGame : public GameInteraction, public NotificationReceiver {
+public:
+ GlobeGame(Neighborhood *);
+ virtual ~GlobeGame() {}
+
+ void handleInput(const Input &, const Hotspot *);
+ void clickInHotspot(const Input &, const Hotspot *);
+ void activateHotspots();
+
+ bool canSolve();
+ void doSolve();
+
+ struct Point3D {
+ float x, y, z;
+ };
+
+ struct Line3D {
+ Point3D pt1, pt2;
+ };
+
+protected:
+ // Latitude (-90 - 90) and longitude (-180 - 180)
+ static const int16 _siloCoords[kNumAllSilos][2];
+
+ static const int16 _targetSilo[kNumTargetSilos];
+ static const int16 _timeLimit[kNumTargetSilos];
+ static const TimeValue _siloName[kNumTargetSilos][2];
+
+ void openInteraction();
+ void initInteraction();
+ void closeInteraction();
+
+ void receiveNotification(Notification *, const NotificationFlags);
+
+ void spinGlobe(const Input &, const Hotspot *, GlobeTrackDirection);
+ void clickGlobe(const Input &);
+
+ int16 findClickedSilo(const Input &);
+
+ void globeMovieFrameToOrigin(int16, int16 &, int16 &);
+ void globePointToLatLong(const Point3D &, int16, int16, int16 &, int16 &);
+ void screenPointTo3DPoint(int16, int16, Point3D &);
+ bool lineHitsGlobe(const Line3D &, Point3D &);
+
+ Movie _monitorMovie;
+ Movie _globeMovie;
+ Movie _upperNamesMovie;
+ Movie _lowerNamesMovie;
+ Notification _globeNotification;
+ NotificationCallBack _monitorCallBack;
+ GlobeTracker _globeTracker;
+ Picture _globeCircleLeft;
+ Picture _globeCircleRight;
+ Picture _globeCircleUp;
+ Picture _globeCircleDown;
+ Picture _motionHighlightLeft;
+ Picture _motionHighlightRight;
+ Picture _motionHighlightUp;
+ Picture _motionHighlightDown;
+ Picture _targetHighlightUpperLeft;
+ Picture _targetHighlightUpperRight;
+ Picture _targetHighlightLowerLeft;
+ Picture _targetHighlightLowerRight;
+ GlobeCountdown _countdown;
+ NotificationCallBack _countdownCallBack;
+ int16 _gameState;
+ int16 _currentSiloIndex;
+ Notification *_neighborhoodNotification;
+ bool _playedInstructions;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp b/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp
new file mode 100644
index 0000000000..f2ea53ff89
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/delta/noraddelta.cpp
@@ -0,0 +1,869 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/energymonitor.h"
+#include "pegasus/gamestate.h"
+#include "pegasus/interface.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/biochips/opticalchip.h"
+#include "pegasus/items/biochips/retscanchip.h"
+#include "pegasus/items/inventory/airmask.h"
+#include "pegasus/neighborhood/norad/constants.h"
+#include "pegasus/neighborhood/norad/subcontrolroom.h"
+#include "pegasus/neighborhood/norad/delta/globegame.h"
+#include "pegasus/neighborhood/norad/delta/noraddelta.h"
+
+namespace Pegasus {
+
+const uint32 NoradDelta::_noradDeltaClawExtras[22] = {
+ kN60ClawFromAToB,
+ kN60ClawALoop,
+ kN60ClawAPinch,
+ kN60ClawACounterclockwise,
+ kN60ClawAClockwise,
+ kN60ClawFromBToA,
+ kN60ClawFromBToC,
+ kN60ClawFromBToD,
+ kN60ClawBLoop,
+ kN60ClawBPinch,
+ kN60ClawBCounterclockwise,
+ kN60ClawBClockwise,
+ kN60ClawFromCToB,
+ kN60ClawCLoop,
+ kN60ClawCPinch,
+ kN60ClawCCounterclockwise,
+ kN60ClawCClockwise,
+ kN60ClawFromDToB,
+ kN60ClawDLoop,
+ kN60ClawDPinch,
+ kN60ClawDCounterclockwise,
+ kN60ClawDClockwise
+};
+
+NoradDelta::NoradDelta(InputHandler *nextHandler, PegasusEngine *owner) : Norad(nextHandler, owner, "Norad Delta", kNoradDeltaID) {
+ _elevatorUpRoomID = kNorad49South;
+ _elevatorDownRoomID = kNorad48South;
+ _elevatorUpSpotID = kNorad48ElevatorUpSpotID;
+ _elevatorDownSpotID = kNorad49ElevatorDownSpotID;
+
+ // Pressure door stuff.
+
+ _subRoomEntryRoom1 = kNorad50;
+ _subRoomEntryDir1 = kEast;
+ _subRoomEntryRoom2 = kNorad59;
+ _subRoomEntryDir2 = kWest;
+ _upperPressureDoorRoom = kNorad50East;
+ _lowerPressureDoorRoom = kNorad59West;
+
+ _upperPressureDoorUpSpotID = kDeltaUpperPressureDoorUpSpotID;
+ _upperPressureDoorDownSpotID = kDeltaUpperPressureDoorDownSpotID;
+ _upperPressureDoorAbortSpotID = kNorad50DoorOutSpotID;
+
+ _lowerPressureDoorUpSpotID = kDeltaLowerPressureDoorUpSpotID;
+ _lowerPressureDoorDownSpotID = kDeltaLowerPressureDoorDownSpotID;
+ _lowerPressureDoorAbortSpotID = kNorad59WestOutSpotID;
+
+ _pressureSoundIn = kPressureDoorIntro1In;
+ _pressureSoundOut = kPressureDoorIntro1Out;
+ _equalizeSoundIn = kPressureDoorIntro2In;
+ _equalizeSoundOut = kPressureDoorIntro2Out;
+ _accessDeniedIn = kDeltaAccessDeniedIn;
+ _accessDeniedOut = kDeltaAccessDeniedOut;
+
+ GameState.setNoradSubPrepState(kSubDamaged);
+
+ _subControlRoom = kNorad60West;
+}
+
+void NoradDelta::init() {
+ Norad::init();
+
+ // Little fix for the retinal scan zoom in spot...
+ Hotspot *hotspot = _vm->getAllHotspots().findHotspotByID(kNorad68WestSpotID);
+ hotspot->setMaskedHotspotFlags(kZoomInSpotFlag, kZoomInSpotFlag | kZoomOutSpotFlag);
+
+ hotspot = _vm->getAllHotspots().findHotspotByID(kNorad79WestSpotID);
+ hotspot->setMaskedHotspotFlags(kZoomInSpotFlag, kZoomInSpotFlag | kZoomOutSpotFlag);
+
+ hotspot = _vm->getAllHotspots().findHotspotByID(kDelta59RobotShieldBiochipSpotID);
+ hotspot->setMaskedHotspotFlags(kPickUpBiochipSpotFlag, kPickUpBiochipSpotFlag);
+ HotspotInfoTable::Entry *hotspotEntry = findHotspotEntry(kDelta59RobotShieldBiochipSpotID);
+ hotspotEntry->hotspotItem = kShieldBiochip;
+
+ hotspot = _vm->getAllHotspots().findHotspotByID(kDelta59RobotOpMemBiochipSpotID);
+ hotspot->setMaskedHotspotFlags(kPickUpBiochipSpotFlag, kPickUpBiochipSpotFlag);
+ hotspotEntry = findHotspotEntry(kDelta59RobotOpMemBiochipSpotID);
+ hotspotEntry->hotspotItem = kOpticalBiochip;
+
+ hotspot = _vm->getAllHotspots().findHotspotByID(kDelta59RobotRetinalBiochipSpotID);
+ hotspot->setMaskedHotspotFlags(kPickUpBiochipSpotFlag, kPickUpBiochipSpotFlag);
+ hotspotEntry = findHotspotEntry(kDelta59RobotRetinalBiochipSpotID);
+ hotspotEntry->hotspotItem = kRetinalScanBiochip;
+
+ hotspot = _vm->getAllHotspots().findHotspotByID(kDelta60RobotShieldBiochipSpotID);
+ hotspot->setMaskedHotspotFlags(kPickUpBiochipSpotFlag, kPickUpBiochipSpotFlag);
+ hotspotEntry = findHotspotEntry(kDelta60RobotShieldBiochipSpotID);
+ hotspotEntry->hotspotItem = kShieldBiochip;
+
+ hotspot = _vm->getAllHotspots().findHotspotByID(kDelta60RobotOpMemBiochipSpotID);
+ hotspot->setMaskedHotspotFlags(kPickUpBiochipSpotFlag, kPickUpBiochipSpotFlag);
+ hotspotEntry = findHotspotEntry(kDelta60RobotOpMemBiochipSpotID);
+ hotspotEntry->hotspotItem = kOpticalBiochip;
+
+ hotspot = _vm->getAllHotspots().findHotspotByID(kDelta60RobotRetinalBiochipSpotID);
+ hotspot->setMaskedHotspotFlags(kPickUpBiochipSpotFlag, kPickUpBiochipSpotFlag);
+ hotspotEntry = findHotspotEntry(kDelta60RobotRetinalBiochipSpotID);
+ hotspotEntry->hotspotItem = kRetinalScanBiochip;
+}
+
+void NoradDelta::start() {
+ if (g_energyMonitor) {
+ g_energyMonitor->stopEnergyDraining();
+ g_energyMonitor->restoreLastEnergyValue();
+ _vm->resetEnergyDeathReason();
+ g_energyMonitor->startEnergyDraining();
+ }
+
+ Norad::start();
+}
+
+void NoradDelta::setUpAIRules() {
+ Neighborhood::setUpAIRules();
+
+ if (g_AIArea) {
+ AIPlayMessageAction *messageAction = new AIPlayMessageAction("Images/AI/Norad/XN07NE", false);
+ AILocationCondition *locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kNorad68, kWest));
+ AIRule *rule = new AIRule(locCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+ }
+}
+
+void NoradDelta::getExtraCompassMove(const ExtraTable::Entry &entry, FaderMoveSpec &compassMove) {
+ switch (entry.extra) {
+ case kArriveFromSubChase:
+ compassMove.makeTwoKnotFaderSpec(kNoradDeltaMovieScale, entry.movieStart, 20, entry.movieEnd, 90);
+ compassMove.insertFaderKnot(entry.movieStart + 25 * kNoradDeltaFrameDuration, 20);
+ compassMove.insertFaderKnot(entry.movieStart + 94 * kNoradDeltaFrameDuration, 45);
+ compassMove.insertFaderKnot(entry.movieStart + 101 * kNoradDeltaFrameDuration, 45);
+ compassMove.insertFaderKnot(entry.movieStart + 146 * kNoradDeltaFrameDuration, 90 + 15);
+ compassMove.insertFaderKnot(entry.movieStart + 189 * kNoradDeltaFrameDuration, 90 + 15);
+ compassMove.insertFaderKnot(entry.movieStart + 204 * kNoradDeltaFrameDuration, 90 + 30);
+ compassMove.insertFaderKnot(entry.movieStart + 214 * kNoradDeltaFrameDuration, 90 + 20);
+ compassMove.insertFaderKnot(entry.movieStart + 222 * kNoradDeltaFrameDuration, 90 + 20);
+ compassMove.insertFaderKnot(entry.movieStart + 228 * kNoradDeltaFrameDuration, 90 + 10);
+ compassMove.insertFaderKnot(entry.movieStart + 245 * kNoradDeltaFrameDuration, 90 + 85);
+ compassMove.insertFaderKnot(entry.movieStart + 262 * kNoradDeltaFrameDuration, 90 + 70);
+ compassMove.insertFaderKnot(entry.movieStart + 273 * kNoradDeltaFrameDuration, 90 + 80);
+ compassMove.insertFaderKnot(entry.movieStart + 287 * kNoradDeltaFrameDuration, 90);
+ break;
+ case kN60PlayerFollowsRobotToDoor:
+ compassMove.makeTwoKnotFaderSpec(kNoradDeltaMovieScale, entry.movieStart, 270 + kSubControlCompassAngle,
+ entry.movieEnd, 270 - 15);
+ compassMove.insertFaderKnot(entry.movieStart + 280, 270 + kSubControlCompassAngle);
+ compassMove.insertFaderKnot(entry.movieStart + 920, 360);
+ compassMove.insertFaderKnot(entry.movieStart + 1840, 360);
+ compassMove.insertFaderKnot(entry.movieStart + 2520, 270);
+ compassMove.insertFaderKnot(entry.movieStart + 3760, 270);
+ compassMove.insertFaderKnot(entry.movieStart + 4640, 270 + kSubControlCompassAngle);
+ break;
+ case kN59PlayerWins2:
+ compassMove.makeTwoKnotFaderSpec(kNoradDeltaMovieScale, entry.movieStart, 270, entry.movieEnd, 280);
+ compassMove.insertFaderKnot(entry.movieEnd - 1000, 270);
+ default:
+ Norad::getExtraCompassMove(entry, compassMove);
+ break;
+ }
+}
+
+GameInteraction *NoradDelta::makeInteraction(const InteractionID interactionID) {
+ if (interactionID == kNoradGlobeGameInteractionID)
+ return new GlobeGame(this);
+
+ return Norad::makeInteraction(interactionID);
+}
+
+void NoradDelta::playClawMonitorIntro() {
+ playSpotSoundSync(kLoadClawIntroIn, kLoadClawIntroOut);
+}
+
+void NoradDelta::getExitEntry(const RoomID room, const DirectionConstant direction, ExitTable::Entry &entry) {
+ Norad::getExitEntry(room, direction, entry);
+
+ if (room == kNorad61 && direction == kSouth)
+ entry.movieStart += kNoradDeltaFrameDuration;
+}
+
+void NoradDelta::getZoomEntry(const HotSpotID id, ZoomTable::Entry &zoomEntry) {
+ Norad::getZoomEntry(id, zoomEntry);
+
+ if (id == kNorad59WestSpotID && GameState.getNoradPlayedGlobeGame()) {
+ ExtraTable::Entry extraEntry;
+ getExtraEntry(kN59ZoomWithRobot, extraEntry);
+ zoomEntry.movieStart = extraEntry.movieStart;
+ zoomEntry.movieEnd = extraEntry.movieEnd;
+ }
+}
+
+void NoradDelta::loadAmbientLoops() {
+/*
+ Logic:
+
+ loop sound 1:
+ if room == kNorad79West
+ if player globe game
+ play kNoradGlobeLoop2SoundNum
+ else
+ play kNoradRedAlertLoopSoundNum
+ else if room >= kNorad78 && room <= kNorad79
+ play kNoradGlobeLoop2SoundNum
+ else if gassed,
+ if room >= kNorad41 && room <= kNorad49South
+ play kNoradNewSubLoopSoundNum, kNoradWarningVolume
+ else if room >= kNorad59 && room <= kNorad60West
+ play kNoradSubControlLoopSoundNum, kNoradWarningVolume
+ else
+ play kNoradWarningLoopSoundNum, kNoradWarningVolume
+ else
+ play nothing
+ loop sound 2:
+ if gassed and not wearing air mask
+ if room == kNorad54North
+ play breathing unmanned loop
+ else
+ play breathing
+ else
+ if room == kNorad54North
+ play unmanned loop
+ else
+ play nothing
+*/
+
+ if (GameState.getNoradArrivedFromSub()) {
+ RoomID room = GameState.getCurrentRoom();
+
+ if (room == kNorad79West) {
+ if (_privateFlags.getFlag(kNoradPrivateFinishedGlobeGameFlag))
+ loadLoopSound1("Sounds/Norad/GlobAmb2.22K.AIFF");
+ else
+ loadLoopSound1("Sounds/Norad/RedAlert.22K.AIFF");
+ } else if (room >= kNorad78 && room <= kNorad79) {
+ // clone2727 says: This looks like it should be loadLoopSound1...
+ loadLoopSound2("Sounds/Norad/RedAlert.22K.AIFF");
+ } else if (GameState.getNoradGassed()) {
+ if (room >= kNorad41 && room <= kNorad49South)
+ loadLoopSound1("Sounds/Norad/NEW SUB AMB.22K.AIFF", kNoradWarningVolume * 3);
+ else if (room >= kNorad59 && room <= kNorad60West)
+ loadLoopSound1("Sounds/Norad/SUB CONTRL LOOP.22K.AIFF", kNoradWarningVolume * 3);
+ else
+ loadLoopSound1("Sounds/Norad/WARNING LOOP.22K.AIFF", kNoradWarningVolume);
+ } else {
+ loadLoopSound1("");
+ }
+
+ if (GameState.getNoradGassed() && !g_airMask->isAirFilterOn()) {
+ if (room == kNorad54North)
+ loadLoopSound2("Sounds/Norad/Breathing Typing.22K.AIFF", 0x100 / 2);
+ else
+ loadLoopSound2("Sounds/Norad/SUCKING WIND.22K.AIFF", kNoradSuckWindVolume, 0, 0);
+ } else {
+ if (room == kNorad54North)
+ loadLoopSound2("Sounds/Norad/N54NAS.22K.AIFF", 0x100 / 2);
+ else
+ loadLoopSound2("");
+ }
+ } else {
+ // Start them off at zero...
+ if (GameState.getNoradGassed())
+ loadLoopSound1("Sounds/Norad/NEW SUB AMB.22K.AIFF", 0, 0, 0);
+ if (!g_airMask->isAirFilterOn())
+ loadLoopSound2("Sounds/Norad/SUCKING WIND.22K.AIFF", 0, 0, 0);
+ }
+}
+
+void NoradDelta::checkContinuePoint(const RoomID room, const DirectionConstant direction) {
+ switch (MakeRoomView(room, direction)) {
+ case MakeRoomView(kNorad41, kEast):
+ case MakeRoomView(kNorad49, kEast):
+ case MakeRoomView(kNorad49, kWest):
+ case MakeRoomView(kNorad61, kSouth):
+ case MakeRoomView(kNorad68, kEast):
+ case MakeRoomView(kNorad79, kWest):
+ makeContinuePoint();
+ break;
+ }
+}
+
+void NoradDelta::arriveAt(const RoomID room, const DirectionConstant direction) {
+ if (room != kNorad68)
+ GameState.setNoradRetScanGood(false);
+
+ Norad::arriveAt(room, direction);
+
+ FaderMoveSpec loop1Spec, loop2Spec;
+ ExtraTable::Entry entry;
+
+ switch (room) {
+ case kNorad41:
+ if (direction == kEast && !GameState.getNoradArrivedFromSub()) {
+ GameState.setNoradPlayedGlobeGame(false);
+
+ GameState.setNoradBeatRobotWithClaw(false);
+ GameState.setNoradBeatRobotWithDoor(false);
+ GameState.setNoradRetScanGood(false);
+
+ GameState.setScoringExitedSub(true);
+
+ getExtraEntry(kArriveFromSubChase, entry);
+
+ loop1Spec.makeTwoKnotFaderSpec(kNoradDeltaMovieScale, 0, 0, entry.movieEnd -
+ entry.movieStart, kNoradWarningVolume);
+ loop1Spec.insertFaderKnot(7320, 0);
+ loop1Spec.insertFaderKnot(7880, kNoradWarningVolume);
+
+ loop2Spec.makeTwoKnotFaderSpec(kNoradDeltaMovieScale, 0, 0, entry.movieEnd -
+ entry.movieStart, kNoradSuckWindVolume);
+ loop1Spec.insertFaderKnot(7320, 0);
+ loop1Spec.insertFaderKnot(7880, kNoradSuckWindVolume);
+
+ startExtraSequence(kArriveFromSubChase, kExtraCompletedFlag, kFilterNoInput);
+
+ startLoop1Fader(loop1Spec);
+ startLoop2Fader(loop2Spec);
+ }
+ break;
+ case kNorad54North:
+ GameState.setScoringSawRobotAt54North(true);
+ break;
+ case kNorad68:
+ if (GameState.getNoradRetScanGood())
+ openDoor();
+ break;
+ case kNorad68West:
+ arriveAtNorad68West();
+ break;
+ case kNorad79West:
+ arriveAtNorad79West();
+ break;
+ default:
+ break;
+ }
+}
+
+void NoradDelta::doorOpened() {
+ Norad::doorOpened();
+ GameState.setNoradRetScanGood(false);
+}
+
+void NoradDelta::arriveAtNorad68West() {
+ playSpotSoundSync(kHoldForRetinalIn, kHoldForRetinalOut);
+
+ BiochipItem *retScan = _vm->getCurrentBiochip();
+
+ if (retScan != 0 && retScan->getObjectID() == kRetinalScanBiochip) {
+ ((RetScanChip *)retScan)->searchForLaser();
+ succeedRetinalScan();
+ } else {
+ failRetinalScan();
+ }
+}
+
+void NoradDelta::arriveAtNorad79West() {
+ if (!GameState.getNoradPlayedGlobeGame())
+ newInteraction(kNoradGlobeGameInteractionID);
+}
+
+void NoradDelta::bumpIntoWall() {
+ requestSpotSound(kDeltaBumpIntoWallIn, kDeltaBumpIntoWallOut, kFilterNoInput, 0);
+ Neighborhood::bumpIntoWall();
+}
+
+void NoradDelta::failRetinalScan() {
+ startExtraSequence(kNoradDeltaRetinalScanBad, kExtraCompletedFlag, kFilterNoInput);
+}
+
+void NoradDelta::succeedRetinalScan() {
+ startExtraSequence(kNoradDeltaRetinalScanGood, kExtraCompletedFlag, kFilterNoInput);
+ GameState.setNoradRetScanGood(true);
+ GameState.setScoringUsedRetinalChip(true);
+}
+
+void NoradDelta::getDoorEntry(const RoomID room, const DirectionConstant direction, DoorTable::Entry &entry) {
+ Norad::getDoorEntry(room, direction, entry);
+
+ if (room == kNorad68 && direction == kWest && !GameState.getNoradRetScanGood())
+ entry.flags = kDoorPresentMask | kDoorLockedMask;
+}
+
+void NoradDelta::finishedGlobeGame() {
+ GameState.setNoradPlayedGlobeGame(true);
+ _privateFlags.setFlag(kNoradPrivateFinishedGlobeGameFlag, true);
+ GameState.setScoringFinishedGlobeGame(true);
+ loadAmbientLoops();
+ g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/Norad/XN60WD1", false, kWarningInterruption);
+}
+
+bool NoradDelta::playingAgainstRobot() {
+ return GameState.getNoradPlayedGlobeGame();
+}
+
+void NoradDelta::getClawInfo(HotSpotID &outSpotID, HotSpotID &prepSpotID, HotSpotID &clawControlSpotID, HotSpotID &pinchClawSpotID,
+ HotSpotID &moveClawDownSpotID, HotSpotID &moveClawRightSpotID, HotSpotID &moveClawLeftSpotID, HotSpotID &moveClawUpSpotID,
+ HotSpotID &clawCCWSpotID, HotSpotID &clawCWSpotID, uint32 &clawPosition, const uint32 *&clawExtraIDs) {
+ outSpotID = kNorad60MonitorOutSpotID;
+ prepSpotID = kNorad60LaunchPrepSpotID;
+ clawControlSpotID = kNorad60ClawControlSpotID;
+ pinchClawSpotID = kNorad60ClawPinchSpotID;
+ moveClawDownSpotID = kNorad60ClawDownSpotID;
+ moveClawRightSpotID = kNorad60ClawRightSpotID;
+ moveClawLeftSpotID = kNorad60ClawLeftSpotID;
+ moveClawUpSpotID = kNorad60ClawUpSpotID;
+ clawCCWSpotID = kNorad60ClawCCWSpotID;
+ clawCWSpotID = kNorad60ClawCWSpotID;
+ clawPosition = kClawAtC;
+ clawExtraIDs = _noradDeltaClawExtras;
+}
+
+void NoradDelta::playerBeatRobotWithDoor() {
+ GameState.setNoradBeatRobotWithDoor(true);
+ updateViewFrame();
+ GameState.setScoringStoppedNoradRobot(true);
+ g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/Norad/XN59WD", false, kWarningInterruption);
+}
+
+void NoradDelta::playerBeatRobotWithClaw() {
+ GameState.setNoradBeatRobotWithClaw(true);
+ updateViewFrame();
+ GameState.setScoringStoppedNoradRobot(true);
+ GameState.setScoringNoradGandhi(true);
+ g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/Norad/XN59WD", false, kWarningInterruption);
+}
+
+TimeValue NoradDelta::getViewTime(const RoomID room, const DirectionConstant direction) {
+ ExtraTable::Entry entry;
+
+ if (room == kNorad41 && direction == kSouth && !GameState.getNoradArrivedFromSub()) {
+ getExtraEntry(kArriveFromSubChase, entry);
+ return entry.movieStart;
+ }
+
+ if (GameState.getNoradBeatRobotWithDoor()) {
+ if (_privateFlags.getFlag(kNoradPrivateRobotHeadOpenFlag)) {
+ uint32 extraID = kN59Biochips111;
+ if (_privateFlags.getFlag(kNoradPrivateGotShieldChipFlag))
+ extraID += 1;
+ if (_privateFlags.getFlag(kNoradPrivateGotOpticalChipFlag))
+ extraID += 2;
+ if (_privateFlags.getFlag(kNoradPrivateGotRetScanChipFlag))
+ extraID += 4;
+ getExtraEntry(extraID, entry);
+ return entry.movieStart;
+ }
+
+ getExtraEntry(kN59RobotHeadOpens, entry);
+ return entry.movieStart;
+ } else if (GameState.getNoradBeatRobotWithClaw()) {
+ if (_privateFlags.getFlag(kNoradPrivateRobotHeadOpenFlag)) {
+ uint32 extraID = kN60Biochips111;
+ if (_privateFlags.getFlag(kNoradPrivateGotShieldChipFlag))
+ extraID += 1;
+ if (_privateFlags.getFlag(kNoradPrivateGotOpticalChipFlag))
+ extraID += 2;
+ if (_privateFlags.getFlag(kNoradPrivateGotRetScanChipFlag))
+ extraID += 4;
+ getExtraEntry(extraID, entry);
+ return entry.movieStart;
+ }
+
+ getExtraEntry(kN60RobotHeadOpens, entry);
+ return entry.movieStart;
+ }
+
+ return Norad::getViewTime(room, direction);
+}
+
+void NoradDelta::openDoor() {
+ if (GameState.getCurrentRoom() == kNorad59 && GameState.getCurrentDirection() == kWest && GameState.getNoradPlayedGlobeGame()) {
+ Input scratch;
+ InputHandler::_inputHandler->clickInHotspot(scratch, _vm->getAllHotspots().findHotspotByID(kNorad59WestSpotID));
+ } else {
+ Norad::openDoor();
+ }
+}
+
+void NoradDelta::activateHotspots() {
+ Norad::activateHotspots();
+
+ if (GameState.getCurrentRoom() == kNorad59West && GameState.getCurrentDirection() == kWest && GameState.getNoradBeatRobotWithDoor()) {
+ _vm->getAllHotspots().deactivateOneHotspot(kNorad59WestOutSpotID);
+
+ if (_privateFlags.getFlag(kNoradPrivateRobotHeadOpenFlag)) {
+ if (!_privateFlags.getFlag(kNoradPrivateGotShieldChipFlag))
+ _vm->getAllHotspots().activateOneHotspot(kDelta59RobotShieldBiochipSpotID);
+ else
+ _vm->getAllHotspots().deactivateOneHotspot(kDelta59RobotShieldBiochipSpotID);
+
+ if (!_privateFlags.getFlag(kNoradPrivateGotOpticalChipFlag))
+ _vm->getAllHotspots().activateOneHotspot(kDelta59RobotOpMemBiochipSpotID);
+ else
+ _vm->getAllHotspots().deactivateOneHotspot(kDelta59RobotOpMemBiochipSpotID);
+
+ if (!_privateFlags.getFlag(kNoradPrivateGotRetScanChipFlag))
+ _vm->getAllHotspots().activateOneHotspot(kDelta59RobotRetinalBiochipSpotID);
+ else
+ _vm->getAllHotspots().deactivateOneHotspot(kDelta59RobotRetinalBiochipSpotID);
+ } else
+ _vm->getAllHotspots().activateOneHotspot(kDelta59RobotHeadSpotID);
+ } else if (GameState.getCurrentRoom() == kNorad60West && GameState.getCurrentDirection() == kWest &&
+ GameState.getNoradBeatRobotWithClaw()) {
+ _vm->getAllHotspots().deactivateOneHotspot(kNorad60MonitorOutSpotID);
+
+ if (_privateFlags.getFlag(kNoradPrivateRobotHeadOpenFlag)) {
+ if (!_privateFlags.getFlag(kNoradPrivateGotShieldChipFlag))
+ _vm->getAllHotspots().activateOneHotspot(kDelta60RobotShieldBiochipSpotID);
+ else
+ _vm->getAllHotspots().deactivateOneHotspot(kDelta60RobotShieldBiochipSpotID);
+
+ if (!_privateFlags.getFlag(kNoradPrivateGotOpticalChipFlag))
+ _vm->getAllHotspots().activateOneHotspot(kDelta60RobotOpMemBiochipSpotID);
+ else
+ _vm->getAllHotspots().deactivateOneHotspot(kDelta60RobotOpMemBiochipSpotID);
+
+ if (!_privateFlags.getFlag(kNoradPrivateGotRetScanChipFlag))
+ _vm->getAllHotspots().activateOneHotspot(kDelta60RobotRetinalBiochipSpotID);
+ else
+ _vm->getAllHotspots().deactivateOneHotspot(kDelta60RobotRetinalBiochipSpotID);
+ } else {
+ _vm->getAllHotspots().activateOneHotspot(kDelta60RobotHeadSpotID);
+ }
+ } else if (GameState.getCurrentRoomAndView() == MakeRoomView(kNorad50, kEast)) {
+ if (GameState.isCurrentDoorOpen())
+ _vm->getAllHotspots().deactivateOneHotspot(kNorad50DoorSpotID);
+ } else if (GameState.getCurrentRoomAndView() == MakeRoomView(kNorad59, kWest)) {
+ if (GameState.isCurrentDoorOpen())
+ _vm->getAllHotspots().deactivateOneHotspot(kNorad59WestSpotID);
+ }
+}
+
+void NoradDelta::clickInHotspot(const Input &input, const Hotspot *clickedSpot) {
+ switch (clickedSpot->getObjectID()) {
+ case kDelta59RobotHeadSpotID:
+ startExtraSequence(kN59RobotHeadOpens, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kDelta60RobotHeadSpotID:
+ startExtraSequence(kN60RobotHeadOpens, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ default:
+ Norad::clickInHotspot(input, clickedSpot);
+ break;
+ }
+}
+
+void NoradDelta::receiveNotification(Notification *notification, const NotificationFlags flags) {
+ Norad::receiveNotification(notification, flags);
+
+ if ((flags & kExtraCompletedFlag) != 0) {
+ RetScanChip *retScan;
+ Input dummy;
+
+ switch (_lastExtra) {
+ case kArriveFromSubChase:
+ GameState.setNoradArrivedFromSub(true);
+ GameState.setCurrentRoom(kNoRoomID);
+ GameState.setCurrentDirection(kNoDirection);
+ arriveAt(kNorad41, kEast);
+ break;
+ case kN59RobotHeadOpens:
+ case kN60RobotHeadOpens:
+ _privateFlags.setFlag(kNoradPrivateRobotHeadOpenFlag, true);
+ break;
+ case kNoradDeltaRetinalScanBad:
+ retScan = (RetScanChip *)_vm->getCurrentBiochip();
+ retScan->setItemState(kNormalItem);
+ playSpotSoundSync(kRetinalScanFailedIn, kRetinalScanFailedOut);
+ downButton(dummy);
+ break;
+ case kNoradDeltaRetinalScanGood:
+ retScan = (RetScanChip *)_vm->getCurrentBiochip();
+ retScan->setItemState(kNormalItem);
+ downButton(dummy);
+ break;
+ case kN59RobotDisappears:
+ case kN60RobotDisappears:
+ recallToTSASuccess();
+ break;
+ }
+
+ _interruptionFilter = kFilterAllInput;
+ }
+
+ g_AIArea->checkMiddleArea();
+}
+
+void NoradDelta::pickedUpItem(Item *item) {
+ switch (item->getObjectID()) {
+ case kShieldBiochip:
+ if (_privateFlags.getFlag(kNoradPrivateGotShieldChipFlag) &&
+ _privateFlags.getFlag(kNoradPrivateGotRetScanChipFlag) &&
+ _privateFlags.getFlag(kNoradPrivateGotOpticalChipFlag)) {
+ GameState.setNoradFinished(true);
+
+ if (GameState.getCurrentRoom() == kNorad59West)
+ startExtraSequence(kN59RobotDisappears, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraSequence(kN60RobotDisappears, kExtraCompletedFlag, kFilterNoInput);
+ }
+ break;
+ case kRetinalScanBiochip:
+ if (_privateFlags.getFlag(kNoradPrivateGotShieldChipFlag) &&
+ _privateFlags.getFlag(kNoradPrivateGotRetScanChipFlag) &&
+ _privateFlags.getFlag(kNoradPrivateGotOpticalChipFlag)) {
+ GameState.setNoradFinished(true);
+
+ if (GameState.getCurrentRoom() == kNorad59West)
+ startExtraSequence(kN59RobotDisappears, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraSequence(kN60RobotDisappears, kExtraCompletedFlag, kFilterNoInput);
+ }
+ break;
+ case kOpticalBiochip:
+ g_opticalChip->addPoseidon();
+ GameState.setScoringGotNoradOpMemChip();
+
+ if (_privateFlags.getFlag(kNoradPrivateGotShieldChipFlag) &&
+ _privateFlags.getFlag(kNoradPrivateGotRetScanChipFlag) &&
+ _privateFlags.getFlag(kNoradPrivateGotOpticalChipFlag)) {
+ GameState.setNoradFinished(true);
+
+ if (GameState.getCurrentRoom() == kNorad59West)
+ startExtraSequence(kN59RobotDisappears, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraSequence(kN60RobotDisappears, kExtraCompletedFlag, kFilterNoInput);
+ }
+ break;
+ }
+
+ Norad::pickedUpItem(item);
+}
+
+void NoradDelta::takeItemFromRoom(Item *item) {
+ switch (item->getObjectID()) {
+ case kShieldBiochip:
+ _privateFlags.setFlag(kNoradPrivateGotShieldChipFlag, true);
+ break;
+ case kRetinalScanBiochip:
+ _privateFlags.setFlag(kNoradPrivateGotRetScanChipFlag, true);
+ break;
+ case kOpticalBiochip:
+ _privateFlags.setFlag(kNoradPrivateGotOpticalChipFlag, true);
+ break;
+ }
+
+ Norad::takeItemFromRoom(item);
+}
+
+void NoradDelta::dropItemIntoRoom(Item *item, Hotspot *hotspot) {
+ switch (item->getObjectID()) {
+ case kShieldBiochip:
+ _privateFlags.setFlag(kNoradPrivateGotShieldChipFlag, false);
+ break;
+ case kOpticalBiochip:
+ _privateFlags.setFlag(kNoradPrivateGotOpticalChipFlag, false);
+ break;
+ case kRetinalScanBiochip:
+ _privateFlags.setFlag(kNoradPrivateGotRetScanChipFlag, false);
+ break;
+ }
+
+ Norad::dropItemIntoRoom(item, hotspot);
+}
+
+Hotspot *NoradDelta::getItemScreenSpot(Item *item, DisplayElement *element) {
+ HotSpotID id = kNoHotSpotID;
+
+ switch (item->getObjectID()) {
+ case kShieldBiochip:
+ if (GameState.getNoradBeatRobotWithDoor())
+ id = kDelta59RobotShieldBiochipSpotID;
+ else
+ id = kDelta60RobotShieldBiochipSpotID;
+ break;
+ case kOpticalBiochip:
+ if (GameState.getNoradBeatRobotWithDoor())
+ id = kDelta59RobotOpMemBiochipSpotID;
+ else
+ id = kDelta60RobotOpMemBiochipSpotID;
+ break;
+ case kRetinalScanBiochip:
+ if (GameState.getNoradBeatRobotWithDoor())
+ id = kDelta59RobotRetinalBiochipSpotID;
+ else
+ id = kDelta60RobotRetinalBiochipSpotID;
+ break;
+ }
+
+ if (id != kNoHotSpotID)
+ return _vm->getAllHotspots().findHotspotByID(id);
+
+ return Norad::getItemScreenSpot(item, element);
+}
+
+Common::String NoradDelta::getEnvScanMovie() {
+ return "Images/AI/Norad/XNE2";
+}
+
+uint NoradDelta::getNumHints() {
+ uint numHints = Neighborhood::getNumHints();
+
+ if (numHints == 0) {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kNorad60, kWest):
+ if (GameState.getNoradPlayedGlobeGame())
+ numHints = 2;
+ else
+ numHints = 1;
+ break;
+ case MakeRoomView(kNorad59, kNorth):
+ case MakeRoomView(kNorad59, kSouth):
+ case MakeRoomView(kNorad59, kEast):
+ case MakeRoomView(kNorad59, kWest):
+ case MakeRoomView(kNorad60, kNorth):
+ case MakeRoomView(kNorad60, kSouth):
+ case MakeRoomView(kNorad60, kEast):
+ if (GameState.getNoradPlayedGlobeGame())
+ numHints = 2;
+ break;
+ case MakeRoomView(kNorad68, kWest):
+ if (_vm->playerHasItemID(kRetinalScanBiochip)) {
+ BiochipItem *retScan = _vm->getCurrentBiochip();
+ if (retScan == 0 || retScan->getObjectID() != kRetinalScanBiochip)
+ numHints = 2;
+ } else if (!GameState.isCurrentDoorOpen()) {
+ numHints = 2;
+ }
+ break;
+ }
+ }
+
+ return numHints;
+}
+
+Common::String NoradDelta::getHintMovie(uint hintNum) {
+ Common::String movieName = Neighborhood::getHintMovie(hintNum);
+
+ if (movieName.empty()) {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kNorad60, kWest):
+ if (GameState.getNoradPlayedGlobeGame()) {
+ if (hintNum == 1)
+ return "Images/AI/Norad/XN60WD2";
+
+ return "Images/AI/Norad/XN60WD3";
+ }
+
+ return "Images/AI/Globals/XGLOB1C";
+ case MakeRoomView(kNorad59, kNorth):
+ case MakeRoomView(kNorad59, kSouth):
+ case MakeRoomView(kNorad59, kEast):
+ case MakeRoomView(kNorad59, kWest):
+ case MakeRoomView(kNorad60, kNorth):
+ case MakeRoomView(kNorad60, kSouth):
+ case MakeRoomView(kNorad60, kEast):
+ if (hintNum == 1)
+ return "Images/AI/Norad/XN60WD2";
+
+ return "Images/AI/Norad/XN60WD3";
+ case MakeRoomView(kNorad68, kWest):
+ if (_vm->playerHasItemID(kRetinalScanBiochip)) {
+ if (hintNum == 1)
+ return "Images/AI/Globals/XGLOB1A";
+
+ return "Images/AI/Globals/XGLOB1C";
+ }
+
+ if (hintNum == 1)
+ return "Images/AI/Globals/XGLOB1B";
+
+ return "Images/AI/Globals/XGLOB3B";
+ }
+ }
+
+ return movieName;
+}
+
+void NoradDelta::closeDoorOffScreen(const RoomID room, const DirectionConstant) {
+ switch (room) {
+ case kNorad47:
+ case kNorad48:
+ case kNorad41:
+ case kNorad42:
+ playSpotSoundSync(kDeltaElevatorDoorCloseIn, kDeltaElevatorDoorCloseOut);
+ break;
+ default:
+ playSpotSoundSync(kDeltaRegDoorCloseIn, kDeltaRegDoorCloseOut);
+ break;
+ }
+}
+
+bool NoradDelta::canSolve() {
+ if (Norad::canSolve())
+ return true;
+
+ if (GameState.getCurrentRoomAndView() == MakeRoomView(kNorad68, kWest)) {
+ BiochipItem *biochip = _vm->getCurrentBiochip();
+ if (biochip != 0 && biochip->getObjectID() != kRetinalScanBiochip)
+ return true;
+ }
+
+ return false;
+}
+
+void NoradDelta::doSolve() {
+ Norad::doSolve();
+
+ if (GameState.getCurrentRoomAndView() == MakeRoomView(kNorad68, kWest)) {
+ if (!_vm->playerHasItemID(kRetinalScanBiochip))
+ _vm->addItemToBiochips((BiochipItem *)_vm->getAllItems().findItemByID(kRetinalScanBiochip));
+
+ BiochipItem *biochip = _vm->getCurrentBiochip();
+ if (biochip != 0 && biochip->getObjectID() != kRetinalScanBiochip && g_interface)
+ g_interface->setCurrentBiochipID(kRetinalScanBiochip);
+
+ Hotspot *spot = _vm->getAllHotspots().findHotspotByID(kNorad68WestSpotID);
+ Input scratch;
+ InputHandler::_inputHandler->clickInHotspot(scratch, spot);
+ }
+}
+
+Common::String NoradDelta::getSoundSpotsName() {
+ return "Sounds/Norad/Norad Delta Spots";
+}
+
+Common::String NoradDelta::getNavMovieName() {
+ return "Images/Norad Delta/Norad Delta.movie";
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/norad/delta/noraddelta.h b/engines/pegasus/neighborhood/norad/delta/noraddelta.h
new file mode 100644
index 0000000000..11065f2c9d
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/delta/noraddelta.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_NORAD_DELTA_NORADDELTA_H
+#define PEGASUS_NEIGHBORHOOD_NORAD_DELTA_NORADDELTA_H
+
+#include "pegasus/neighborhood/norad/norad.h"
+
+namespace Pegasus {
+
+class NoradDelta : public Norad {
+public:
+ NoradDelta(InputHandler *, PegasusEngine *);
+ virtual ~NoradDelta() {}
+
+ void init();
+
+ void start();
+
+ void getExtraCompassMove(const ExtraTable::Entry &, FaderMoveSpec &);
+
+ void finishedGlobeGame();
+
+ virtual GameInteraction *makeInteraction(const InteractionID);
+
+ void playClawMonitorIntro();
+
+ virtual void getClawInfo(HotSpotID &outSpotID, HotSpotID &prepSpotID, HotSpotID &clawControlSpotID,
+ HotSpotID &pinchClawSpotID, HotSpotID &moveClawDownSpotID, HotSpotID &moveClawRightSpotID,
+ HotSpotID &moveClawLeftSpotID, HotSpotID &moveClawUpSpotID, HotSpotID &clawCCWSpotID,
+ HotSpotID &clawCWSpotID, uint32 &, const uint32 *&);
+
+ void playerBeatRobotWithClaw();
+ void playerBeatRobotWithDoor();
+
+ void loadAmbientLoops();
+
+ void setUpAIRules();
+ Common::String getEnvScanMovie();
+ uint getNumHints();
+ Common::String getHintMovie(uint);
+ void closeDoorOffScreen(const RoomID, const DirectionConstant);
+
+ void checkContinuePoint(const RoomID, const DirectionConstant);
+
+ bool canSolve();
+ void doSolve();
+
+ void doorOpened();
+
+protected:
+ enum {
+ kNoradPrivateArrivedFromSubFlag,
+ kNoradPrivateFinishedGlobeGameFlag,
+ kNoradPrivateRobotHeadOpenFlag,
+ kNoradPrivateGotShieldChipFlag,
+ kNoradPrivateGotOpticalChipFlag,
+ kNoradPrivateGotRetScanChipFlag,
+ kNumNoradPrivateFlags
+ };
+
+ static const uint32 _noradDeltaClawExtras[22];
+
+ void getExitEntry(const RoomID, const DirectionConstant, ExitTable::Entry &);
+ void getZoomEntry(const HotSpotID, ZoomTable::Entry &);
+ virtual void arriveAt(const RoomID, const DirectionConstant);
+ void arriveAtNorad68West();
+ void arriveAtNorad79West();
+ TimeValue getViewTime(const RoomID, const DirectionConstant);
+ void openDoor();
+ void activateHotspots();
+ void clickInHotspot(const Input &, const Hotspot *);
+ void receiveNotification(Notification *, const NotificationFlags);
+ void pickedUpItem(Item *item);
+ void takeItemFromRoom(Item *item);
+ void dropItemIntoRoom(Item *item, Hotspot *);
+ Hotspot *getItemScreenSpot(Item *, DisplayElement *);
+
+ virtual bool playingAgainstRobot();
+
+ void failRetinalScan();
+ void succeedRetinalScan();
+ void getDoorEntry(const RoomID, const DirectionConstant, DoorTable::Entry &);
+
+ void bumpIntoWall();
+
+ FlagsArray<byte, kNumNoradPrivateFlags> _privateFlags;
+
+ Common::String getSoundSpotsName();
+ Common::String getNavMovieName();
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/norad/norad.cpp b/engines/pegasus/neighborhood/norad/norad.cpp
new file mode 100644
index 0000000000..578f062dea
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/norad.cpp
@@ -0,0 +1,285 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/energymonitor.h"
+#include "pegasus/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/inventory/airmask.h"
+#include "pegasus/neighborhood/norad/constants.h"
+#include "pegasus/neighborhood/norad/norad.h"
+#include "pegasus/neighborhood/norad/noradelevator.h"
+#include "pegasus/neighborhood/norad/pressuredoor.h"
+#include "pegasus/neighborhood/norad/subcontrolroom.h"
+#include "pegasus/neighborhood/norad/subplatform.h"
+
+namespace Pegasus {
+
+const NotificationFlags kDoneWithPressureDoorNotification = 1;
+
+const NotificationFlags kNoradNotificationFlags = kDoneWithPressureDoorNotification;
+
+// This class handles everything that Norad Alpha and Delta have in common, such as
+// oxygen mask usage, the elevator and the pressure doors.
+
+Norad::Norad(InputHandler *nextHandler, PegasusEngine *vm, const Common::String &resName, NeighborhoodID id) :
+ Neighborhood(nextHandler, vm, resName, id), _noradNotification(kNoradNotificationID, vm) {
+ _elevatorUpSpotID = kNoHotSpotID;
+ _elevatorDownSpotID = kNoHotSpotID;
+ _elevatorUpRoomID = kNoHotSpotID;
+ _elevatorDownRoomID = kNoHotSpotID;
+
+ _subRoomEntryRoom1 = kNoRoomID;
+ _subRoomEntryDir1 = kNoDirection;
+ _subRoomEntryRoom2 = kNoRoomID;
+ _subRoomEntryDir2 = kNoDirection;
+ _upperPressureDoorRoom = kNoRoomID;
+ _lowerPressureDoorRoom = kNoRoomID;
+
+ _upperPressureDoorUpSpotID = kNoHotSpotID;
+ _upperPressureDoorDownSpotID = kNoHotSpotID;
+ _upperPressureDoorAbortSpotID = kNoHotSpotID;
+
+ _lowerPressureDoorUpSpotID = kNoHotSpotID;
+ _lowerPressureDoorDownSpotID = kNoHotSpotID;
+ _lowerPressureDoorAbortSpotID = kNoHotSpotID;
+
+ _pressureSoundIn = 0xffffffff;
+ _pressureSoundOut = 0xffffffff;
+ _equalizeSoundIn = 0xffffffff;
+ _equalizeSoundOut = 0xffffffff;
+ _accessDeniedIn = 0xffffffff;
+ _accessDeniedOut = 0xffffffff;
+
+ _platformRoom = kNoRoomID;
+ _subControlRoom = kNoRoomID;
+
+ _doneWithPressureDoor = false;
+
+ _noradNotification.notifyMe(this, kNoradNotificationFlags, kNoradNotificationFlags);
+}
+
+GameInteraction *Norad::makeInteraction(const InteractionID interactionID) {
+ PressureDoor *pressureDoor;
+ SubControlRoom *subControl;
+
+ switch (interactionID) {
+ case kNoradElevatorInteractionID:
+ return new NoradElevator(this, _elevatorUpRoomID, _elevatorDownRoomID, _elevatorUpSpotID, _elevatorDownSpotID);
+ case kNoradPressureDoorInteractionID:
+ if (GameState.getCurrentRoom() == _upperPressureDoorRoom)
+ pressureDoor = new PressureDoor(this, true, _upperPressureDoorUpSpotID, _upperPressureDoorDownSpotID,
+ _upperPressureDoorAbortSpotID, _pressureSoundIn, _pressureSoundOut, _equalizeSoundIn, _equalizeSoundOut);
+ else
+ pressureDoor = new PressureDoor(this, false, _lowerPressureDoorUpSpotID, _lowerPressureDoorDownSpotID,
+ _lowerPressureDoorAbortSpotID, _pressureSoundIn, _pressureSoundOut, _equalizeSoundIn, _equalizeSoundOut);
+
+ if (GameState.getCurrentRoom() == kNorad59West && playingAgainstRobot())
+ pressureDoor->playAgainstRobot();
+
+ return pressureDoor;
+ case kNoradSubControlRoomInteractionID:
+ subControl = new SubControlRoom(this);
+
+ if (GameState.getCurrentRoom() == kNorad60West && playingAgainstRobot())
+ subControl->playAgainstRobot();
+
+ return subControl;
+ case kNoradSubPlatformInteractionID:
+ return new SubPlatform(this);
+ default:
+ return 0;
+ }
+}
+
+void Norad::flushGameState() {
+ g_energyMonitor->saveCurrentEnergyValue();
+}
+
+void Norad::start() {
+ setUpAirMask();
+ Neighborhood::start();
+}
+
+void Norad::activateHotspots() {
+ Neighborhood::activateHotspots();
+
+ RoomID room = GameState.getCurrentRoom();
+ if (room == _elevatorUpRoomID)
+ _neighborhoodHotspots.activateOneHotspot(_elevatorDownSpotID);
+ else if (room == _elevatorDownRoomID)
+ _neighborhoodHotspots.activateOneHotspot(_elevatorUpSpotID);
+}
+
+void Norad::arriveAt(const RoomID room, const DirectionConstant direction) {
+ Neighborhood::arriveAt(room, direction);
+
+ if (GameState.getCurrentRoom() == _elevatorUpRoomID || GameState.getCurrentRoom() == _elevatorDownRoomID)
+ arriveAtNoradElevator();
+ else if (GameState.getCurrentRoom() == _upperPressureDoorRoom)
+ arriveAtUpperPressureDoorRoom();
+ else if (GameState.getCurrentRoom() == _lowerPressureDoorRoom)
+ arriveAtLowerPressureDoorRoom();
+ else if (GameState.getCurrentRoom() == _platformRoom)
+ arriveAtSubPlatformRoom();
+ else if (GameState.getCurrentRoom() == _subControlRoom)
+ arriveAtSubControlRoom();
+
+ if (_doneWithPressureDoor) {
+ _doneWithPressureDoor = false;
+ openDoor();
+ }
+}
+
+void Norad::arriveAtNoradElevator() {
+ if (_currentInteraction)
+ _currentInteraction->startOverInteraction();
+ else
+ newInteraction(kNoradElevatorInteractionID);
+}
+
+void Norad::arriveAtUpperPressureDoorRoom() {
+ newInteraction(kNoradPressureDoorInteractionID);
+}
+
+void Norad::arriveAtLowerPressureDoorRoom() {
+ newInteraction(kNoradPressureDoorInteractionID);
+}
+
+void Norad::arriveAtSubPlatformRoom() {
+ newInteraction(kNoradSubPlatformInteractionID);
+}
+
+void Norad::arriveAtSubControlRoom() {
+ newInteraction(kNoradSubControlRoomInteractionID);
+}
+
+int16 Norad::getStaticCompassAngle(const RoomID room, const DirectionConstant dir) {
+ int16 result = Neighborhood::getStaticCompassAngle(room, dir);
+
+ if (room == _elevatorUpRoomID || room == _elevatorDownRoomID)
+ result += kElevatorCompassAngle;
+ else if (room == _platformRoom)
+ result += kSubPlatformCompassAngle;
+ else if (room == _subControlRoom)
+ result += kSubControlCompassAngle;
+
+ return result;
+}
+
+CanOpenDoorReason Norad::canOpenDoor(DoorTable::Entry &entry) {
+ if (((GameState.getCurrentRoom() == _subRoomEntryRoom1 && GameState.getCurrentDirection() == _subRoomEntryDir1) ||
+ (GameState.getCurrentRoom() == _subRoomEntryRoom2 && GameState.getCurrentDirection() == _subRoomEntryDir2)) &&
+ GameState.getNoradSubRoomPressure() != kNormalSubRoomPressure)
+ return kCantOpenBadPressure;
+
+ return Neighborhood::canOpenDoor(entry);
+}
+
+void Norad::cantOpenDoor(CanOpenDoorReason reason) {
+ if (reason == kCantOpenBadPressure)
+ playSpotSoundSync(_pressureSoundIn, _pressureSoundOut);
+ else
+ playSpotSoundSync(_accessDeniedIn, _accessDeniedOut);
+}
+
+void Norad::startExitMovie(const ExitTable::Entry &exitEntry) {
+ if (GameState.getCurrentRoom() == _elevatorUpRoomID) {
+ if (exitEntry.exitRoom != _elevatorDownRoomID)
+ newInteraction(kNoInteractionID);
+ } else if (GameState.getCurrentRoom() == _elevatorDownRoomID) {
+ if (exitEntry.exitRoom != _elevatorUpRoomID)
+ newInteraction(kNoInteractionID);
+ } else {
+ newInteraction(kNoInteractionID);
+ }
+
+ Neighborhood::startExitMovie(exitEntry);
+}
+
+void Norad::startZoomMovie(const ZoomTable::Entry &zoomEntry) {
+ newInteraction(kNoInteractionID);
+ Neighborhood::startZoomMovie(zoomEntry);
+}
+
+void Norad::upButton(const Input &input) {
+ if (GameState.getCurrentRoom() != _elevatorUpRoomID && GameState.getCurrentRoom() != _elevatorDownRoomID)
+ Neighborhood::upButton(input);
+}
+
+void Norad::setUpAirMask() {
+ _airMaskCallBack.setNotification(&_neighborhoodNotification);
+ _airMaskCallBack.initCallBack(&_airMaskTimer, kCallBackAtExtremes);
+ _airMaskCallBack.setCallBackFlag(kAirTimerExpiredFlag);
+ _neighborhoodNotification.notifyMe(this, kAirTimerExpiredFlag, kAirTimerExpiredFlag);
+ _airMaskCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ _airMaskTimer.setScale(1);
+ _airMaskTimer.setSegment(0, kNoradAirMaskTimeLimit);
+ checkAirMask();
+}
+
+void Norad::checkAirMask() {
+ if (g_airMask && g_airMask->isAirFilterOn()) {
+ _airMaskTimer.stop();
+ } else if (GameState.getNoradGassed() && !_airMaskTimer.isRunning()) {
+ _airMaskTimer.setTime(0);
+ _airMaskTimer.start();
+ }
+
+ loadAmbientLoops();
+}
+
+void Norad::receiveNotification(Notification *notification, const NotificationFlags flags) {
+ if (notification == &_neighborhoodNotification && (flags & kAirTimerExpiredFlag) != 0)
+ ((PegasusEngine *)g_engine)->die(kDeathGassedInNorad);
+
+ Neighborhood::receiveNotification(notification, flags);
+
+ if (notification == &_noradNotification) {
+ // Must be kDoneWithPressureDoorNotification...
+ Input scratch;
+ _doneWithPressureDoor = true;
+ downButton(scratch);
+ }
+}
+
+uint16 Norad::getDateResID() const {
+ return kDate2112ID;
+}
+
+Common::String Norad::getBriefingMovie() {
+ return "Images/AI/Norad/XNO";
+}
+
+void Norad::pickedUpItem(Item *item) {
+ Neighborhood::pickedUpItem(item);
+ g_AIArea->checkMiddleArea();
+}
+
+void Norad::doneWithPressureDoor() {
+ _noradNotification.setNotificationFlags(kDoneWithPressureDoorNotification, kDoneWithPressureDoorNotification);
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/norad/norad.h b/engines/pegasus/neighborhood/norad/norad.h
new file mode 100644
index 0000000000..3cd77cc54b
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/norad.h
@@ -0,0 +1,121 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_NORAD_NORAD_H
+#define PEGASUS_NEIGHBORHOOD_NORAD_NORAD_H
+
+#include "pegasus/neighborhood/neighborhood.h"
+
+namespace Pegasus {
+
+// This is the code common to both Norad Alpha and Norad Delta
+
+class Norad : public Neighborhood {
+public:
+ Norad(InputHandler *, PegasusEngine *owner, const Common::String &resName, const NeighborhoodID);
+ virtual ~Norad() {}
+
+ void flushGameState();
+
+ virtual void start();
+
+ virtual void getClawInfo(HotSpotID &outSpotID, HotSpotID &prepSpotID,
+ HotSpotID &clawControlSpotID, HotSpotID &pinchClawSpotID,
+ HotSpotID &moveClawDownSpotID, HotSpotID &moveClawRightSpotID,
+ HotSpotID &moveClawLeftSpotID,HotSpotID &moveClawUpSpotID,
+ HotSpotID &clawCCWSpotID, HotSpotID &clawCWSpotID, uint32 &, const uint32 *&) = 0;
+ void checkAirMask();
+
+ virtual uint16 getDateResID() const;
+
+ virtual GameInteraction *makeInteraction(const InteractionID);
+
+ Common::String getBriefingMovie();
+
+ void pickedUpItem(Item *);
+
+ virtual void playClawMonitorIntro() {}
+
+ void doneWithPressureDoor();
+
+protected:
+ CanOpenDoorReason canOpenDoor(DoorTable::Entry &);
+ void cantOpenDoor(CanOpenDoorReason);
+ int16 getStaticCompassAngle(const RoomID, const DirectionConstant);
+ virtual void startExitMovie(const ExitTable::Entry &);
+ void startZoomMovie(const ZoomTable::Entry &);
+ virtual void upButton(const Input &);
+ virtual void activateHotspots();
+
+ virtual void arriveAt(const RoomID, const DirectionConstant);
+ virtual void arriveAtNoradElevator();
+ virtual void arriveAtUpperPressureDoorRoom();
+ virtual void arriveAtLowerPressureDoorRoom();
+ virtual void arriveAtSubPlatformRoom();
+ virtual void arriveAtSubControlRoom();
+ void setUpAirMask();
+ virtual void receiveNotification(Notification *, const NotificationFlags);
+ virtual bool playingAgainstRobot() { return false; }
+
+ Notification _noradNotification;
+ bool _doneWithPressureDoor;
+
+ RoomID _elevatorUpRoomID;
+ RoomID _elevatorDownRoomID;
+ HotSpotID _elevatorUpSpotID;
+ HotSpotID _elevatorDownSpotID;
+
+ TimeBase _airMaskTimer;
+ NotificationCallBack _airMaskCallBack;
+
+ RoomID _subRoomEntryRoom1;
+ DirectionConstant _subRoomEntryDir1;
+ RoomID _subRoomEntryRoom2;
+ DirectionConstant _subRoomEntryDir2;
+ RoomID _upperPressureDoorRoom;
+ RoomID _lowerPressureDoorRoom;
+
+ HotSpotID _upperPressureDoorUpSpotID;
+ HotSpotID _upperPressureDoorDownSpotID;
+ HotSpotID _upperPressureDoorAbortSpotID;
+
+ HotSpotID _lowerPressureDoorUpSpotID;
+ HotSpotID _lowerPressureDoorDownSpotID;
+ HotSpotID _lowerPressureDoorAbortSpotID;
+
+ TimeValue _pressureSoundIn;
+ TimeValue _pressureSoundOut;
+ TimeValue _equalizeSoundIn;
+ TimeValue _equalizeSoundOut;
+ TimeValue _accessDeniedIn;
+ TimeValue _accessDeniedOut;
+
+ RoomID _platformRoom;
+ RoomID _subControlRoom;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/norad/noradelevator.cpp b/engines/pegasus/neighborhood/norad/noradelevator.cpp
new file mode 100644
index 0000000000..1751f4dcb6
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/noradelevator.cpp
@@ -0,0 +1,130 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/neighborhood/norad/constants.h"
+#include "pegasus/neighborhood/norad/norad.h"
+#include "pegasus/neighborhood/norad/noradelevator.h"
+
+namespace Pegasus {
+
+// Norad elevator PICTs:
+static const ResIDType kElevatorLabelID = 200;
+static const ResIDType kElevatorButtonsID = 201;
+static const ResIDType kElevatorDownOnID = 202;
+static const ResIDType kElevatorUpOnID = 203;
+
+NoradElevator::NoradElevator(Neighborhood *handler, const RoomID upRoom, const RoomID downRoom,
+ const HotSpotID upHotspot, const HotSpotID downHotspot) : GameInteraction(kNoradElevatorInteractionID, handler),
+ _elevatorControls(kNoradElevatorControlsID), _elevatorNotification(kNoradElevatorNotificationID, ((PegasusEngine *)g_engine)) {
+ _timerExpired = false;
+ _upRoom = upRoom;
+ _downRoom = downRoom;
+ _upHotspot = upHotspot;
+ _downHotspot = downHotspot;
+}
+
+void NoradElevator::openInteraction() {
+ SpriteFrame *frame = new SpriteFrame();
+ frame->initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kElevatorLabelID, true);
+ _elevatorControls.addFrame(frame, 0, 0);
+
+ frame = new SpriteFrame();
+ frame->initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kElevatorButtonsID, true);
+ _elevatorControls.addFrame(frame, 0, 0);
+
+ frame = new SpriteFrame();
+ frame->initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kElevatorDownOnID, true);
+ _elevatorControls.addFrame(frame, 0, 0);
+
+ frame = new SpriteFrame();
+ frame->initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kElevatorUpOnID, true);
+ _elevatorControls.addFrame(frame, 0, 0);
+
+ _elevatorControls.setCurrentFrameIndex(0);
+ _elevatorControls.setDisplayOrder(kElevatorControlsOrder);
+
+ Common::Rect r;
+ frame->getSurfaceBounds(r);
+ r.moveTo(kNoradAlphaElevatorControlsLeft, kNoradAlphaElevatorControlsTop);
+
+ _elevatorControls.setBounds(r);
+ _elevatorControls.startDisplaying();
+ _elevatorControls.show();
+}
+
+void NoradElevator::initInteraction() {
+ _elevatorTimer.setScale(2);
+ _elevatorTimer.setSegment(0, 1);
+ _elevatorCallBack.initCallBack(&_elevatorTimer, kCallBackAtExtremes);
+ _elevatorCallBack.setCallBackFlag(1);
+ _elevatorCallBack.setNotification(&_elevatorNotification);
+ _elevatorNotification.notifyMe(this, 1, 1);
+ _elevatorCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ _elevatorTimer.start();
+}
+
+void NoradElevator::closeInteraction() {
+ _elevatorControls.stopDisplaying();
+ _elevatorControls.discardFrames();
+ _elevatorCallBack.releaseCallBack();
+}
+
+void NoradElevator::resetInteraction() {
+ _elevatorControls.setCurrentFrameIndex(1);
+}
+
+void NoradElevator::activateHotspots() {
+ GameInteraction::activateHotspots();
+
+ if (_timerExpired) {
+ if (GameState.getCurrentRoom() == _upRoom)
+ g_allHotspots.activateOneHotspot(_downHotspot);
+ else if (GameState.getCurrentRoom() == _downRoom)
+ g_allHotspots.activateOneHotspot(_upHotspot);
+ }
+}
+
+void NoradElevator::clickInHotspot(const Input &input, const Hotspot *spot) {
+ HotSpotID id = spot->getObjectID();
+
+ if (id == _upHotspot || id == _downHotspot) {
+ g_neighborhood->moveForward();
+ if (id == _downHotspot)
+ _elevatorControls.setCurrentFrameIndex(2);
+ else
+ _elevatorControls.setCurrentFrameIndex(3);
+ } else {
+ GameInteraction::clickInHotspot(input, spot);
+ }
+}
+
+void NoradElevator::receiveNotification(Notification *, const NotificationFlags) {
+ _elevatorControls.setCurrentFrameIndex(1);
+ _timerExpired = true;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/norad/noradelevator.h b/engines/pegasus/neighborhood/norad/noradelevator.h
new file mode 100644
index 0000000000..24aa488534
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/noradelevator.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_NORAD_NORADELEVATOR_H
+#define PEGASUS_NEIGHBORHOOD_NORAD_NORADELEVATOR_H
+
+#include "pegasus/interaction.h"
+#include "pegasus/notification.h"
+#include "pegasus/surface.h"
+#include "pegasus/timers.h"
+
+namespace Pegasus {
+
+class Neighborhood;
+
+class NoradElevator : public GameInteraction, private NotificationReceiver {
+public:
+ NoradElevator(Neighborhood *, const RoomID, const RoomID, const HotSpotID, const HotSpotID);
+ virtual ~NoradElevator() {}
+
+protected:
+ virtual void openInteraction();
+ virtual void initInteraction();
+ virtual void closeInteraction();
+ virtual void resetInteraction();
+
+ virtual void activateHotspots();
+ virtual void clickInHotspot(const Input &, const Hotspot *);
+
+ virtual void receiveNotification(Notification *, const NotificationFlags);
+
+ RoomID _upRoom;
+ RoomID _downRoom;
+ HotSpotID _upHotspot;
+ HotSpotID _downHotspot;
+ Sprite _elevatorControls;
+ TimeBase _elevatorTimer;
+ NotificationCallBack _elevatorCallBack;
+ Notification _elevatorNotification;
+ bool _timerExpired;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/norad/pressuredoor.cpp b/engines/pegasus/neighborhood/norad/pressuredoor.cpp
new file mode 100644
index 0000000000..d1378567d3
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/pressuredoor.cpp
@@ -0,0 +1,554 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/neighborhood/norad/constants.h"
+#include "pegasus/neighborhood/norad/norad.h"
+#include "pegasus/neighborhood/norad/pressuredoor.h"
+#include "pegasus/neighborhood/norad/delta/noraddelta.h"
+
+namespace Pegasus {
+
+static const TimeValue kLevelsSplashStart = 0;
+static const TimeValue kLevelsSplashStop = 1;
+static const TimeValue kPressureBase = 1;
+
+static const TimeValue kDoorSealedTime = 0;
+static const TimeValue kEqualizeTime = 1;
+static const TimeValue kMaxPressureLoopStart = 2;
+static const TimeValue kMaxPressureLoopStop = 3;
+static const TimeValue kOpeningDoorLoopStart = 3;
+static const TimeValue kOpeningDoorLoopStop = 4;
+static const TimeValue kIncreasingPressureTime = 4;
+static const TimeValue kDecreasingPressureTime = 5;
+static const TimeValue kCautionLoopStart = 6;
+static const TimeValue kCautionLoopStop = 7;
+
+static const NotificationFlags kSplashFinished = 1;
+static const NotificationFlags kPressureDroppingFlag = kSplashFinished << 1;
+
+static const NotificationFlags kPressureNotificationFlags = kSplashFinished |
+ kPressureDroppingFlag;
+
+static const NotificationFlags kDoorJumpsUpFlag = 1;
+static const NotificationFlags kDoorJumpsBackFlag = kDoorJumpsUpFlag << 1;
+static const NotificationFlags kDoorCrushedFlag = kDoorJumpsBackFlag << 1;
+
+static const NotificationFlags kUtilityNotificationFlags = kDoorJumpsUpFlag |
+ kDoorJumpsBackFlag |
+ kDoorCrushedFlag;
+
+enum {
+ kPlayingRobotApproaching,
+ kRobotPunching,
+ kRobotComingThrough,
+ kRobotDying,
+ kRobotDead
+};
+
+const short kMaxPunches = 5;
+
+enum {
+ kPlayingSplash,
+ kPlayingPressureMessage,
+ kPlayingEqualizeMessage,
+ kWaitingForPlayer,
+ kPlayingDoneMessage,
+ kGameOver
+};
+
+// Pressure values range from 0 to 11.
+static const short kMinPressure = 0;
+static const short kMaxPressure = 11;
+
+static const TimeScale kNavTimeScale = 600;
+static const TimeValue kNavFrameRate = 15;
+static const TimeValue kNavTimePerFrame = kNavTimeScale / kNavFrameRate;
+
+static const TimeValue kApproachPunchInTime = 122 * kNavTimePerFrame;
+static const TimeValue kLoopPunchInTime = 38 * kNavTimePerFrame;
+static const TimeValue kPunchThroughTime = 38 * kNavTimePerFrame;
+
+// Pressure door PICTs:
+static const ResIDType kUpperPressureUpOffPICTID = 400;
+static const ResIDType kUpperPressureUpOnPICTID = 401;
+static const ResIDType kUpperPressureDownOffPICTID = 402;
+static const ResIDType kUpperPressureDownOnPICTID = 403;
+
+static const ResIDType kLowerPressureUpOffPICTID = 404;
+static const ResIDType kLowerPressureUpOnPICTID = 405;
+static const ResIDType kLowerPressureDownOffPICTID = 406;
+static const ResIDType kLowerPressureDownOnPICTID = 407;
+
+PressureDoor::PressureDoor(Neighborhood *handler, bool isUpperDoor, const HotSpotID upSpotID, const HotSpotID downSpotID,
+ const HotSpotID outSpotID, TimeValue pressureSoundIn, TimeValue pressureSoundOut, TimeValue equalizeSoundIn,
+ TimeValue equalizeSoundOut) : GameInteraction(kNoradPressureDoorInteractionID, handler),
+ _levelsMovie(kPressureDoorLevelsID), _typeMovie(kPressureDoorTypeID), _upButton(kPressureDoorUpButtonID),
+ _downButton(kPressureDoorDownButtonID), _pressureNotification(kNoradPressureNotificationID, ((PegasusEngine *)g_engine)),
+ _doorTracker(this), _utilityNotification(kNoradUtilityNotificationID, ((PegasusEngine *)g_engine)) {
+ _neighborhoodNotification = handler->getNeighborhoodNotification();
+ _upHotspotID = upSpotID;
+ _downHotspotID = downSpotID;
+ _outHotspotID = outSpotID;
+ _pressureSoundIn = pressureSoundIn;
+ _pressureSoundOut = pressureSoundOut;
+ _equalizeSoundIn = equalizeSoundIn;
+ _equalizeSoundOut = equalizeSoundOut;
+ _playingAgainstRobot = false;
+ _isUpperDoor = isUpperDoor;
+}
+
+void PressureDoor::openInteraction() {
+ if (_isUpperDoor) {
+ _levelsMovie.initFromMovieFile("Images/Norad Alpha/Upper Levels Movie");
+ _levelsMovie.moveElementTo(kNoradUpperLevelsLeft, kNoradUpperLevelsTop);
+ } else {
+ _levelsMovie.initFromMovieFile("Images/Norad Alpha/Lower Levels Movie");
+ _levelsMovie.moveElementTo(kNoradLowerLevelsLeft, kNoradLowerLevelsTop);
+ }
+
+ _levelsScale = _levelsMovie.getScale();
+ _levelsMovie.setDisplayOrder(kPressureLevelsOrder);
+ _levelsMovie.startDisplaying();
+ _levelsMovie.setSegment(kLevelsSplashStart * _levelsScale, kLevelsSplashStop * _levelsScale);
+ _levelsMovie.setTime(kLevelsSplashStart * _levelsScale);
+ _levelsMovie.redrawMovieWorld();
+ _levelsMovie.show();
+
+ _pressureCallBack.setNotification(&_pressureNotification);
+ _pressureCallBack.initCallBack(&_levelsMovie, kCallBackAtExtremes);
+ _pressureCallBack.setCallBackFlag(kSplashFinished);
+ _pressureCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+
+ _pressureNotification.notifyMe(this, kPressureNotificationFlags, kPressureNotificationFlags);
+
+ if (_isUpperDoor) {
+ _typeMovie.initFromMovieFile("Images/Norad Alpha/Upper Type Movie");
+ _typeMovie.moveElementTo(kNoradUpperTypeLeft, kNoradUpperTypeTop);
+ } else {
+ _typeMovie.initFromMovieFile("Images/Norad Alpha/Lower Type Movie");
+ _typeMovie.moveElementTo(kNoradLowerTypeLeft, kNoradLowerTypeTop);
+ }
+
+ _typeScale = _typeMovie.getScale();
+ _typeMovie.setDisplayOrder(kPressureTypeOrder);
+ _typeMovie.startDisplaying();
+ _typeMovie.setTime(kDoorSealedTime * _typeScale);
+ _typeMovie.redrawMovieWorld();
+
+ SpriteFrame *frame = new SpriteFrame();
+ if (_isUpperDoor)
+ frame->initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kLowerPressureUpOffPICTID);
+ else
+ frame->initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kUpperPressureUpOffPICTID);
+ _upButton.addFrame(frame, 0, 0);
+
+ frame = new SpriteFrame();
+ if (_isUpperDoor)
+ frame->initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kLowerPressureUpOnPICTID);
+ else
+ frame->initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kUpperPressureUpOnPICTID);
+ _upButton.addFrame(frame, 0, 0);
+
+ _upButton.setCurrentFrameIndex(0);
+ _upButton.setDisplayOrder(kPressureUpOrder);
+
+ Common::Rect r;
+ frame->getSurfaceBounds(r);
+ if (_isUpperDoor)
+ r.moveTo(kNoradUpperUpLeft, kNoradUpperUpTop);
+ else
+ r.moveTo(kNoradLowerUpLeft, kNoradLowerUpTop);
+
+ _upButton.setBounds(r);
+ _upButton.startDisplaying();
+ _upButton.show();
+
+ frame = new SpriteFrame();
+ if (_isUpperDoor)
+ frame->initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kLowerPressureDownOffPICTID);
+ else
+ frame->initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kUpperPressureDownOffPICTID);
+ _downButton.addFrame(frame, 0, 0);
+
+ frame = new SpriteFrame();
+ if (_isUpperDoor)
+ frame->initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kLowerPressureDownOnPICTID);
+ else
+ frame->initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kUpperPressureDownOnPICTID);
+ _downButton.addFrame(frame, 0, 0);
+
+ _downButton.setCurrentFrameIndex(0);
+ _downButton.setDisplayOrder(kPressureDownOrder);
+
+ frame->getSurfaceBounds(r);
+ if (_isUpperDoor)
+ r.moveTo(kNoradUpperDownLeft, kNoradUpperDownTop);
+ else
+ r.moveTo(kNoradLowerDownLeft, kNoradLowerDownTop);
+
+ _downButton.setBounds(r);
+ _downButton.startDisplaying();
+ _downButton.show();
+
+ _utilityCallBack.setNotification(&_utilityNotification);
+ _utilityCallBack.initCallBack(&_utilityTimer, kCallBackAtTime);
+ _utilityNotification.notifyMe(this, kUtilityNotificationFlags, kUtilityNotificationFlags);
+ _utilityTimer.setMasterTimeBase(getOwner()->getNavMovie());
+
+ if (_playingAgainstRobot)
+ _neighborhoodNotification->notifyMe(this, kExtraCompletedFlag | kDelayCompletedFlag |
+ kSpotSoundCompletedFlag, kExtraCompletedFlag | kDelayCompletedFlag | kSpotSoundCompletedFlag);
+ else
+ _neighborhoodNotification->notifyMe(this, kDelayCompletedFlag | kSpotSoundCompletedFlag,
+ kDelayCompletedFlag | kSpotSoundCompletedFlag);
+
+ _gameState = kPlayingSplash;
+}
+
+void PressureDoor::initInteraction() {
+ _levelsMovie.start();
+
+ if (_playingAgainstRobot) {
+ ExtraTable::Entry entry;
+ _owner->getExtraEntry(kN59RobotApproaches, entry);
+ _utilityTimer.setSegment(entry.movieStart, entry.movieEnd);
+ _utilityCallBack.setCallBackFlag(kDoorJumpsUpFlag);
+ _punchInTime = kApproachPunchInTime + entry.movieStart;
+ _utilityCallBack.scheduleCallBack(kTriggerTimeFwd, _punchInTime, kNavTimeScale);
+ _utilityTimer.setTime(entry.movieStart);
+ _owner->startExtraSequence(kN59RobotApproaches, kExtraCompletedFlag, kFilterAllInput);
+ _utilityTimer.start();
+ _robotState = kPlayingRobotApproaching;
+ }
+
+ _levelsMovie.redrawMovieWorld();
+}
+
+void PressureDoor::closeInteraction() {
+ _pressureNotification.cancelNotification(this);
+ _pressureCallBack.releaseCallBack();
+ _utilityNotification.cancelNotification(this);
+ _utilityCallBack.releaseCallBack();
+ _neighborhoodNotification->cancelNotification(this);
+}
+
+void PressureDoor::playAgainstRobot() {
+ _playingAgainstRobot = true;
+}
+
+void PressureDoor::receiveNotification(Notification *notification, const NotificationFlags flags) {
+ Neighborhood *owner = getOwner();
+
+ if (notification == _neighborhoodNotification) {
+ if (_playingAgainstRobot && (flags & kExtraCompletedFlag) != 0) {
+ ExtraTable::Entry entry;
+
+ switch (_robotState) {
+ case kPlayingRobotApproaching:
+ _utilityTimer.stop();
+ if (GameState.getNoradSubRoomPressure() == kMaxPressure) {
+ owner->getExtraEntry(kN59PlayerWins1, entry);
+ _utilityTimer.setSegment(entry.movieStart, entry.movieEnd);
+ _utilityTimer.setTime(entry.movieStart);
+ _utilityCallBack.setCallBackFlag(kDoorJumpsUpFlag);
+ _punchInTime = kLoopPunchInTime + entry.movieStart;
+ _utilityCallBack.scheduleCallBack(kTriggerTimeFwd, _punchInTime, kNavTimeScale);
+ owner->startExtraSequence(kN59PlayerWins1, kExtraCompletedFlag, kFilterNoInput);
+ _utilityTimer.start();
+ _robotState = kRobotDying;
+ } else {
+ owner->getExtraEntry(kN59RobotPunchLoop, entry);
+ _utilityTimer.setSegment(entry.movieStart, entry.movieEnd);
+ _utilityTimer.setTime(entry.movieStart);
+ _utilityCallBack.setCallBackFlag(kDoorJumpsUpFlag);
+ _punchInTime = kLoopPunchInTime + entry.movieStart;
+ _utilityCallBack.scheduleCallBack(kTriggerTimeFwd, _punchInTime, kNavTimeScale);
+ owner->startSpotLoop(entry.movieStart, entry.movieEnd, kExtraCompletedFlag);
+ _utilityTimer.start();
+ _robotState = kRobotPunching;
+ _punchCount = 1;
+ }
+ break;
+ case kRobotPunching:
+ if (GameState.getNoradSubRoomPressure() == kMaxPressure) {
+ owner->startExtraSequence(kN59PlayerWins1, kExtraCompletedFlag, kFilterNoInput);
+ _robotState = kRobotDying;
+ } else if (++_punchCount >= kMaxPunches) {
+ _robotState = kRobotComingThrough;
+ owner->getExtraEntry(kN59RobotWins, entry);
+ _utilityTimer.stop();
+ _utilityTimer.setSegment(entry.movieStart, entry.movieEnd);
+ _utilityTimer.setTime(entry.movieStart);
+ _utilityCallBack.cancelCallBack();
+ _utilityCallBack.setCallBackFlag(kDoorCrushedFlag);
+ _utilityCallBack.scheduleCallBack(kTriggerTimeFwd, kPunchThroughTime + entry.movieStart, kNavTimeScale);
+ owner->startExtraSequence(kN59RobotWins, kExtraCompletedFlag, kFilterNoInput);
+ _utilityTimer.start();
+ } else {
+ _utilityCallBack.setCallBackFlag(kDoorJumpsUpFlag);
+ _utilityCallBack.scheduleCallBack(kTriggerTimeFwd, _punchInTime, kNavTimeScale);
+ owner->scheduleNavCallBack(kExtraCompletedFlag);
+ }
+ break;
+ case kRobotComingThrough:
+ g_system->delayMillis(2 * 1000);
+ ((PegasusEngine *)g_engine)->die(kDeathRobotThroughNoradDoor);
+ break;
+ case kRobotDying:
+ _robotState = kRobotDead;
+ _levelsMovie.stop();
+ _levelsMovie.setSegment((kNormalSubRoomPressure + kPressureBase) * _levelsScale,
+ (GameState.getNoradSubRoomPressure() + kPressureBase) * _levelsScale);
+ _pressureCallBack.setCallBackFlag(kPressureDroppingFlag);
+ _pressureCallBack.scheduleCallBack(kTriggerAtStart, 0, 0);
+ _typeMovie.stop();
+ _typeMovie.setSegment(0, _typeMovie.getDuration());
+ _typeMovie.setTime(kDecreasingPressureTime * _typeScale);
+ _typeMovie.redrawMovieWorld();
+ _typeMovie.show();
+ _downButton.show();
+ _downButton.setCurrentFrameIndex(1);
+ _gameState = kGameOver;
+ allowInput(false);
+ _levelsMovie.setRate(Common::Rational(0x5555, 0x10000) - 1); // Should match door tracker.
+ break;
+ case kRobotDead:
+ allowInput(true);
+ ((NoradDelta *)owner)->playerBeatRobotWithDoor();
+ owner->requestDeleteCurrentInteraction();
+ break;
+ }
+ }
+
+ if ((flags & (kDelayCompletedFlag | kSpotSoundCompletedFlag)) != 0) {
+ switch (_gameState) {
+ case kPlayingPressureMessage:
+ _typeMovie.setTime(kEqualizeTime * _typeScale);
+ _typeMovie.redrawMovieWorld();
+ owner->requestDelay(1, 5, kFilterNoInput, 0);
+ owner->requestSpotSound(_equalizeSoundIn, _equalizeSoundOut, kFilterNoInput, 0);
+ owner->requestDelay(1, 5, kFilterNoInput, kDelayCompletedFlag);
+ _gameState = kPlayingEqualizeMessage;
+ break;
+ case kPlayingEqualizeMessage:
+ _gameState = kWaitingForPlayer;
+ stopChangingPressure();
+ break;
+ case kPlayingDoneMessage:
+ _gameState = kWaitingForPlayer;
+ _typeMovie.stop();
+ _typeMovie.setFlags(0);
+ _typeMovie.hide();
+ if (!_playingAgainstRobot)
+ ((Norad *)_owner)->doneWithPressureDoor();
+ break;
+ }
+ }
+ } else if (notification == &_pressureNotification) {
+ switch (flags) {
+ case kSplashFinished:
+ _levelsMovie.stop();
+ _levelsMovie.setSegment(0, _levelsMovie.getDuration());
+ _levelsMovie.setTime((GameState.getNoradSubRoomPressure() + kPressureBase) * _levelsScale);
+ _levelsMovie.redrawMovieWorld();
+
+ if (GameState.getNoradSubRoomPressure() != kNormalSubRoomPressure) {
+ _typeMovie.show();
+ owner->requestDelay(1, 5, kFilterNoInput, 0);
+ owner->requestSpotSound(_pressureSoundIn, _pressureSoundOut, kFilterNoInput, 0);
+ owner->requestDelay(1, 5, kFilterNoInput, kDelayCompletedFlag);
+ _gameState = kPlayingPressureMessage;
+ } else {
+ _gameState = kWaitingForPlayer;
+ }
+ break;
+ case kPressureDroppingFlag:
+ _levelsMovie.stop();
+ _levelsMovie.hide();
+ _typeMovie.stop();
+ _typeMovie.hide();
+ _upButton.hide();
+ _downButton.hide();
+ owner->startExtraSequence(kN59PlayerWins2, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ }
+ } else if (notification == &_utilityNotification) {
+ switch (flags) {
+ case kDoorJumpsUpFlag:
+ _utilityCallBack.setCallBackFlag(kDoorJumpsBackFlag);
+ _utilityCallBack.scheduleCallBack(kTriggerTimeFwd, _punchInTime + kNavTimePerFrame, kNavTimeScale);
+ _levelsMovie.hide();
+ _typePunched = _typeMovie.isVisible();
+ if (_typePunched == true)
+ _typeMovie.hide();
+ _upButton.hide();
+ _downButton.hide();
+ break;
+ case kDoorJumpsBackFlag:
+ _levelsMovie.show();
+ _upButton.show();
+ _downButton.show();
+ if (_typePunched)
+ _typeMovie.show();
+ break;
+ case kDoorCrushedFlag:
+ _levelsMovie.hide();
+ _typeMovie.hide();
+ _upButton.hide();
+ _downButton.hide();
+ break;
+ }
+ }
+}
+
+void PressureDoor::activateHotspots() {
+ GameInteraction::activateHotspots();
+
+ switch (_gameState) {
+ case kWaitingForPlayer:
+ g_allHotspots.activateOneHotspot(_upHotspotID);
+ g_allHotspots.activateOneHotspot(_downHotspotID);
+ if (!_playingAgainstRobot)
+ g_allHotspots.activateOneHotspot(_outHotspotID);
+ break;
+ default:
+ break;
+ }
+}
+
+void PressureDoor::clickInHotspot(const Input &input, const Hotspot *spot) {
+ HotSpotID id = spot->getObjectID();
+
+ if (id == _upHotspotID || id == _downHotspotID) {
+ if (id == _upHotspotID)
+ _doorTracker.setTrackParameters(spot, &_upButton);
+ else
+ _doorTracker.setTrackParameters(spot, &_downButton);
+
+ _doorTracker.startTracking(input);
+ } else {
+ GameInteraction::clickInHotspot(input, spot);
+ }
+}
+
+void PressureDoor::incrementPressure(const HotSpotID id) {
+ _typeMovie.stop();
+ _typeMovie.setSegment(0, _typeMovie.getDuration());
+ _typeMovie.setFlags(0);
+
+ if (id == _upHotspotID) {
+ if (GameState.getNoradSubRoomPressure() < kMaxPressure) {
+ GameState.setNoradSubRoomPressure(GameState.getNoradSubRoomPressure() + 1);
+ _levelsMovie.setTime((GameState.getNoradSubRoomPressure() + kPressureBase) * _levelsScale);
+ _levelsMovie.redrawMovieWorld();
+ _typeMovie.setTime(kIncreasingPressureTime * _typeScale);
+ _typeMovie.redrawMovieWorld();
+ _typeMovie.show();
+ g_AIArea->checkMiddleArea();
+ } else {
+ _typeMovie.hide();
+ }
+ } else if (id == _downHotspotID) {
+ if (GameState.getNoradSubRoomPressure() > kMinPressure) {
+ GameState.setNoradSubRoomPressure(GameState.getNoradSubRoomPressure() - 1);
+ _levelsMovie.setTime((GameState.getNoradSubRoomPressure() + kPressureBase) * _levelsScale);
+ _levelsMovie.redrawMovieWorld();
+ _typeMovie.setTime(kDecreasingPressureTime * _typeScale);
+ _typeMovie.redrawMovieWorld();
+ _typeMovie.show();
+ g_AIArea->checkMiddleArea();
+ } else {
+ _typeMovie.hide();
+ }
+ }
+}
+
+void PressureDoor::stopChangingPressure() {
+ Neighborhood *owner;
+
+ switch (GameState.getNoradSubRoomPressure()) {
+ case 11:
+ _typeMovie.setSegment(kMaxPressureLoopStart * _typeScale, kMaxPressureLoopStop * _typeScale);
+ _typeMovie.setFlags(kLoopTimeBase);
+ _typeMovie.show();
+ _typeMovie.start();
+ break;
+ case 10:
+ _typeMovie.setSegment(kCautionLoopStart * _typeScale, kCautionLoopStop * _typeScale);
+ _typeMovie.setFlags(kLoopTimeBase);
+ _typeMovie.show();
+ _typeMovie.start();
+ break;
+ case kNormalSubRoomPressure:
+ owner = getOwner();
+ _typeMovie.setSegment(kOpeningDoorLoopStart * _typeScale, kOpeningDoorLoopStop * _typeScale);
+ _typeMovie.setFlags(kLoopTimeBase);
+ _typeMovie.show();
+ _gameState = kPlayingDoneMessage;
+ owner->requestDelay(2, 1, kFilterNoInput, kDelayCompletedFlag);
+ _typeMovie.start();
+ break;
+ default:
+ _typeMovie.hide();
+ break;
+ }
+}
+
+bool PressureDoor::canSolve() {
+ if (_playingAgainstRobot)
+ return GameState.getNoradSubRoomPressure() < 11;
+
+ return GameState.getNoradSubRoomPressure() != kNormalSubRoomPressure;
+}
+
+void PressureDoor::doSolve() {
+ if (_playingAgainstRobot) {
+ GameState.setNoradSubRoomPressure(11);
+ _levelsMovie.setTime((11 + kPressureBase) * _levelsScale);
+ _levelsMovie.redrawMovieWorld();
+ _typeMovie.setSegment(kMaxPressureLoopStart * _typeScale, kMaxPressureLoopStop * _typeScale);
+ _typeMovie.setFlags(kLoopTimeBase);
+ _typeMovie.show();
+ _typeMovie.start();
+ g_AIArea->checkMiddleArea();
+ } else {
+ GameState.setNoradSubRoomPressure(kNormalSubRoomPressure);
+ _levelsMovie.setTime((kNormalSubRoomPressure + kPressureBase) * _levelsScale);
+ _levelsMovie.redrawMovieWorld();
+ _typeMovie.setSegment(kOpeningDoorLoopStart * _typeScale, kOpeningDoorLoopStop * _typeScale);
+ _typeMovie.setFlags(kLoopTimeBase);
+ _typeMovie.show();
+ Neighborhood *owner = getOwner();
+ owner->requestDelay(2, 1, kFilterNoInput, kDelayCompletedFlag);
+ _gameState = kPlayingDoneMessage;
+ _typeMovie.start();
+ g_AIArea->checkMiddleArea();
+ }
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/norad/pressuredoor.h b/engines/pegasus/neighborhood/norad/pressuredoor.h
new file mode 100644
index 0000000000..b2018bfcf7
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/pressuredoor.h
@@ -0,0 +1,93 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_NORAD_PRESSUREDOOR_H
+#define PEGASUS_NEIGHBORHOOD_NORAD_PRESSUREDOOR_H
+
+#include "pegasus/interaction.h"
+#include "pegasus/movie.h"
+#include "pegasus/notification.h"
+#include "pegasus/neighborhood/norad/pressuretracker.h"
+
+namespace Pegasus {
+
+static const short kNormalSubRoomPressure = 2;
+
+class PressureDoor : public GameInteraction, public NotificationReceiver {
+public:
+ PressureDoor(Neighborhood *, bool isUpperDoor, const HotSpotID, const HotSpotID,
+ const HotSpotID, TimeValue pressureSoundIn, TimeValue pressureSoundOut,
+ TimeValue equalizeSoundIn, TimeValue equalizeSoundOut);
+ virtual ~PressureDoor() {}
+
+ void incrementPressure(const HotSpotID);
+ void stopChangingPressure();
+
+ void playAgainstRobot();
+
+ bool canSolve();
+ void doSolve();
+
+protected:
+ virtual void openInteraction();
+ virtual void initInteraction();
+ virtual void closeInteraction();
+
+ virtual void activateHotspots();
+ virtual void clickInHotspot(const Input &, const Hotspot *);
+
+ virtual void receiveNotification(Notification *, const NotificationFlags);
+
+ Movie _levelsMovie;
+ TimeScale _levelsScale;
+ Movie _typeMovie;
+ TimeScale _typeScale;
+ Sprite _upButton;
+ Sprite _downButton;
+ Notification _pressureNotification;
+ NotificationCallBack _pressureCallBack;
+ Notification *_neighborhoodNotification;
+ int _gameState;
+ HotSpotID _upHotspotID;
+ HotSpotID _downHotspotID;
+ HotSpotID _outHotspotID;
+ PressureTracker _doorTracker;
+ TimeValue _pressureSoundIn;
+ TimeValue _pressureSoundOut;
+ TimeValue _equalizeSoundIn;
+ TimeValue _equalizeSoundOut;
+ bool _isUpperDoor;
+
+ bool _playingAgainstRobot, _typePunched;
+ int _robotState, _punchCount;
+ TimeBase _utilityTimer;
+ Notification _utilityNotification;
+ NotificationCallBack _utilityCallBack;
+ TimeValue _punchInTime;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/norad/pressuretracker.cpp b/engines/pegasus/neighborhood/norad/pressuretracker.cpp
new file mode 100644
index 0000000000..5aac19dcbe
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/pressuretracker.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/hotspot.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/neighborhood/norad/pressuredoor.h"
+#include "pegasus/neighborhood/norad/pressuretracker.h"
+
+namespace Pegasus {
+
+PressureTracker::PressureTracker(PressureDoor *pressureDoor) {
+ _pressureDoor = pressureDoor;
+ _trackSpot = 0;
+ _trackTime = 0;
+}
+
+void PressureTracker::setTrackParameters(const Hotspot *trackSpot, Sprite *trackButton) {
+ _trackSpot = trackSpot;
+ _trackButton = trackButton;
+ _trackTime = 0;
+}
+
+void PressureTracker::activateHotspots() {
+ Tracker::activateHotspots();
+
+ if (_trackSpot)
+ g_allHotspots.activateOneHotspot(_trackSpot->getObjectID());
+}
+
+// For click-hold dragging.
+bool PressureTracker::stopTrackingInput(const Input &input) {
+ return !JMPPPInput::isPressingInput(input);
+}
+
+void PressureTracker::continueTracking(const Input &input) {
+ Common::Point where;
+ input.getInputLocation(where);
+
+ if (g_allHotspots.findHotspot(where) == _trackSpot) {
+ trackPressure();
+ _trackButton->setCurrentFrameIndex(1);
+ } else {
+ _trackButton->setCurrentFrameIndex(0);
+ }
+}
+
+void PressureTracker::startTracking(const Input &input) {
+ Tracker::startTracking(input);
+ trackPressure();
+}
+
+void PressureTracker::stopTracking(const Input &input) {
+ _trackButton->setCurrentFrameIndex(0);
+ _pressureDoor->stopChangingPressure();
+ Tracker::stopTracking(input);
+}
+
+void PressureTracker::trackPressure() {
+ if (g_system->getMillis() - _trackTime > kPressureDoorTrackInterval * 1000 / 60) {
+ _pressureDoor->incrementPressure(_trackSpot->getObjectID());
+ _trackTime = g_system->getMillis();
+ }
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/norad/pressuretracker.h b/engines/pegasus/neighborhood/norad/pressuretracker.h
new file mode 100644
index 0000000000..6ca7252e22
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/pressuretracker.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_NORAD_PRESSURETRACKER_H
+#define PEGASUS_NEIGHBORHOOD_NORAD_PRESSURETRACKER_H
+
+#include "pegasus/input.h"
+
+namespace Pegasus {
+
+// This class assumes that the globe movie is built at 15 frames per second with a
+// time scale of 600, yielding 40 time unit per frame.
+
+enum PressureTrackDirection {
+ kTrackPressureUp,
+ kTrackPressureDown
+};
+
+static const int kPressureDoorTrackInterval = 45;
+
+class PressureDoor;
+class Sprite;
+
+class PressureTracker : public Tracker {
+public:
+ PressureTracker(PressureDoor *);
+ virtual ~PressureTracker() {}
+
+ void setTrackParameters(const Hotspot *, Sprite *);
+ void continueTracking(const Input &);
+ void startTracking(const Input &);
+ void stopTracking(const Input &);
+ void activateHotspots();
+ bool stopTrackingInput(const Input &);
+
+protected:
+ void trackPressure();
+
+ PressureDoor *_pressureDoor;
+ const Hotspot *_trackSpot;
+ Sprite *_trackButton;
+ long _trackTime;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/norad/subcontrolroom.cpp b/engines/pegasus/neighborhood/norad/subcontrolroom.cpp
new file mode 100644
index 0000000000..d48481e925
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/subcontrolroom.cpp
@@ -0,0 +1,1178 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/neighborhood/norad/constants.h"
+#include "pegasus/neighborhood/norad/norad.h"
+#include "pegasus/neighborhood/norad/subcontrolroom.h"
+#include "pegasus/neighborhood/norad/delta/noraddelta.h"
+
+namespace Pegasus {
+
+// Right Monitor times
+
+static const TimeValue kAlphaClawSplashStart = 0;
+static const TimeValue kAlphaClawSplashStop = 4000;
+
+static const TimeValue kDeltaClawSplashStart = 4000;
+static const TimeValue kDeltaClawSplashStop = 8000;
+
+static const TimeValue kClawAtATime = 8000;
+static const TimeValue kClawAtAPinchedTime = 8600;
+static const TimeValue kClawAtATurnedTime = 9200;
+static const TimeValue kClawAtAWithRobotPinchedTime = 9800;
+
+static const TimeValue kClawAtBTime = 10400;
+static const TimeValue kClawAtBPinchedTime = 11000;
+static const TimeValue kClawAtBTurnedTime = 11600;
+static const TimeValue kClawAtBWithRobotTime = 12200;
+static const TimeValue kClawAtBWithRobotPinchedTime = 12800;
+
+static const TimeValue kClawAtCTime = 13400;
+static const TimeValue kClawAtCPinchedTime = 14000;
+static const TimeValue kClawAtCTurnedTime = 14600;
+
+static const TimeValue kClawAtDTime = 15200;
+static const TimeValue kClawAtDPinchedTime = 15800;
+static const TimeValue kClawAtDTurnedTime = 16400;
+
+static const TimeValue kAToBStart = 17000;
+static const TimeValue kAToBStop = 18680;
+static const TimeValue kAPinchStart = 18680;
+static const TimeValue kAPinchStop = 20200;
+static const TimeValue kACCWStart = 20200;
+static const TimeValue kACCWStop = 21600;
+static const TimeValue kACWStart = 21600;
+static const TimeValue kACWStop = 23000;
+
+static const TimeValue kBToAStart = 23000;
+static const TimeValue kBToAStop = 24680;
+static const TimeValue kBToCStart = 24680;
+static const TimeValue kBToCStop = 26520;
+static const TimeValue kBToDStart = 26520;
+static const TimeValue kBToDStop = 28320;
+static const TimeValue kBPinchStart = 28320;
+static const TimeValue kBPinchStop = 29680;
+static const TimeValue kBCCWStart = 29680;
+static const TimeValue kBCCWStop = 31200;
+static const TimeValue kBCWStart = 31200;
+static const TimeValue kBCWStop = 32720;
+
+static const TimeValue kCToBStart = 32720;
+static const TimeValue kCToBStop = 34560;
+static const TimeValue kCPinchStart = 34560;
+static const TimeValue kCPinchStop = 36400;
+static const TimeValue kCCCWStart = 36400;
+static const TimeValue kCCCWStop = 37840;
+static const TimeValue kCCWStart = 37840;
+static const TimeValue kCCWStop = 39280;
+
+static const TimeValue kDToBStart = 39280;
+static const TimeValue kDToBStop = 41080;
+static const TimeValue kDPinchStart = 41080;
+static const TimeValue kDPinchStop = 42600;
+static const TimeValue kDCCWStart = 42600;
+static const TimeValue kDCCWStop = 44000;
+static const TimeValue kDCWStart = 44000;
+static const TimeValue kDCWStop = 45400;
+
+static const TimeValue kRobotApproachStart = 45400;
+static const TimeValue kRobotApproachStop = 56800;
+
+static const TimeValue kCToBWithRobotStart = 56800;
+static const TimeValue kCToBWithRobotStop = 58600;
+
+static const TimeValue kBPinchWithRobotStart = 58600;
+static const TimeValue kBPinchWithRobotStop = 60400;
+static const TimeValue kBToAWithRobotStart = 60400;
+static const TimeValue kBToAWithRobotStop = 62240;
+
+// As usual, times here are in seconds.
+
+// Left monitor times.
+
+static const TimeValue kAlphaSplashStart = 0;
+static const TimeValue kAlphaSplashStop = 2;
+
+static const TimeValue kMainMenuTime = 2;
+static const TimeValue kLaunchPrepRolloverTime = 3;
+static const TimeValue kLaunchPrepHighlightStart = 4;
+static const TimeValue kLaunchPrepHighlightStop = 5;
+static const TimeValue kClawControlRolloverTime = 5;
+static const TimeValue kClawControlHighlightStart = 6;
+static const TimeValue kClawControlHighlightStop = 7;
+
+static const TimeValue kAlphaLaunchPrepStart = 7;
+static const TimeValue kAlphaLaunchPrepStop = 17;
+
+static const TimeValue kClawMenuStart = 17;
+static const TimeValue kClawMenuStop = 18;
+
+static const TimeValue kClawMenuTime = 18;
+
+static const TimeValue kDeltaSplashStart = 19;
+static const TimeValue kDeltaSplashStop = 21;
+
+static const TimeValue kDeltaLaunchPrepStart = 21;
+static const TimeValue kDeltaLaunchPrepStop = 30;
+
+// Right monitor times.
+
+static const NotificationFlags kAlphaSplashFinished = 1;
+static const NotificationFlags kAlphaPrepFinished = kAlphaSplashFinished << 1;
+static const NotificationFlags kPrepHighlightFinished = kAlphaPrepFinished << 1;
+static const NotificationFlags kClawHighlightFinished = kPrepHighlightFinished << 1;
+static const NotificationFlags kClawMenuFinished = kClawHighlightFinished << 1;
+static const NotificationFlags kDeltaSplashFinished = kClawMenuFinished << 1;
+static const NotificationFlags kDeltaPrepFinished = kDeltaSplashFinished << 1;
+
+static const NotificationFlags kSubControlNotificationFlags = kAlphaSplashFinished |
+ kAlphaPrepFinished |
+ kPrepHighlightFinished |
+ kClawHighlightFinished |
+ kClawMenuFinished |
+ kDeltaSplashFinished |
+ kDeltaPrepFinished;
+
+static const NotificationFlags kOneSecondOfMoveFinished = 1;
+
+static const NotificationFlags kGreenBallNotificationFlags = kOneSecondOfMoveFinished;
+
+enum {
+ kButtonDimFrame,
+ kButtonActiveFrame,
+ kButtonHighlightedFrame
+};
+
+enum {
+ kAlphaSplash,
+ kAlphaMainMenu,
+ kDeltaSplash,
+ kDeltaMainMenu,
+ kClawMenu,
+ kPlayingHighlight,
+ kPuttingClawAway
+};
+
+// The owning neighborhood must provide an array of longs which hold the various
+// extra IDs for moving the claw around. In addition, the owner must tell the sub
+// control room interaction what position the claw starts out in (which is also the
+// position the claw must be in before leaving).
+
+// Standard array indices:
+enum {
+ kClawFromAToBIndex,
+ kClawALoopIndex,
+ kClawAPinchIndex,
+ kClawACounterclockwiseIndex,
+ kClawAClockwiseIndex,
+ kClawFromBToAIndex,
+ kClawFromBToCIndex,
+ kClawFromBToDIndex,
+ kClawBLoopIndex,
+ kClawBPinchIndex,
+ kClawBCounterclockwiseIndex,
+ kClawBClockwiseIndex,
+ kClawFromCToBIndex,
+ kClawCLoopIndex,
+ kClawCPinchIndex,
+ kClawCCounterclockwiseIndex,
+ kClawCClockwiseIndex,
+ kClawFromDToBIndex,
+ kClawDLoopIndex,
+ kClawDPinchIndex,
+ kClawDCounterclockwiseIndex,
+ kClawDClockwiseIndex
+};
+
+// Action indices for s_clawStateTable:
+// Can also be used as indices into _buttons (except for kNoActionIndex and kLoopActionIndex).
+enum {
+ kNoActionIndex = -1,
+ kPinchActionIndex = 0,
+ kMoveDownActionIndex,
+ kMoveRightActionIndex,
+ kMoveLeftActionIndex,
+ kMoveUpActionIndex,
+ kCCWActionIndex,
+ kCWActionIndex,
+ kLoopActionIndex
+};
+
+/*
+ _currentAction and _nextAction:
+
+ At any time, _currentAction contains an action index (defined above). The current
+ action index is what the claw is doing right now. If the player presses a button
+ before the current action completes, _nextAction saves the new action and input
+ is disabled. This has the effect of implementing a queue of commands for the claw
+ that can save at most one extra command.
+
+ The general strategy for using _currentAction and _nextAction are:
+ -- If the player presses a claw button and _currentAction is kNoActionIndex,
+ do the command immediately and set _currentAction accordingly.
+ -- If the player presses a claw button and _currentAction is not kNoActionIndex,
+ save the appropriate action index in _nextAction.
+ -- When a command animation completes, set _nextAction to kNoActionIndex, then
+ check if _nextAction has a command waiting in it. If so, play the appriate
+ animation, copy _nextAction into _currentAction and set _nextAction to
+ kNoActionIndex.
+ -- If the player tries to get up, disable input (including all claw buttons) until
+ the player rises. Then, if the claw is in its original position, play the
+ animation of the player rising.
+ -- If the claw needs to be put back, play the first move required to put the
+ claw back by setting _currentAction and playing the appropriate animation.
+ Leave _nextAction alone. When the animation, completes, check to see if the
+ claw is in its original position or not. If so, complete the player rising
+ sequence by playing the rising animation. If not, repeat this whole step.
+
+ Using this general strategy allows the use of a single function,
+ DispatchClawAction, which can both cause the claw to perform a command and saving
+ the next command in _nextAction.
+*/
+
+// Array indexed by [claw position] [action]
+// array yields an index into the neighborhood's extra id table for claw animation or -1.
+static const int s_clawStateTable[4][8] = {
+ {
+ kClawAPinchIndex,
+ kNoActionIndex,
+ kNoActionIndex,
+ kClawFromAToBIndex,
+ kNoActionIndex,
+ kClawACounterclockwiseIndex,
+ kClawAClockwiseIndex,
+ kClawALoopIndex
+ },
+ {
+ kClawBPinchIndex,
+ kNoActionIndex,
+ kClawFromBToAIndex,
+ kClawFromBToDIndex,
+ kClawFromBToCIndex,
+ kClawBCounterclockwiseIndex,
+ kClawBClockwiseIndex,
+ kClawBLoopIndex
+ },
+ {
+ kClawCPinchIndex,
+ kClawFromCToBIndex,
+ kNoActionIndex,
+ kNoActionIndex,
+ kNoActionIndex,
+ kClawCCounterclockwiseIndex,
+ kClawCClockwiseIndex,
+ kClawCLoopIndex
+ },
+ {
+ kClawDPinchIndex,
+ kNoActionIndex,
+ kClawFromDToBIndex,
+ kNoActionIndex,
+ kNoActionIndex,
+ kClawDCounterclockwiseIndex,
+ kClawDClockwiseIndex,
+ kClawDLoopIndex
+ }
+};
+
+// Move directions for s_clawMovieTable:
+enum {
+ kMoveClawDown,
+ kMoveClawRight,
+ kMoveClawLeft,
+ kMoveClawUp
+};
+
+static const int kClawNowhere = -1;
+
+// Array indexed by [claw position] [move direction]
+// array yields new claw position or -1.
+static const int s_clawMovieTable[4][4] = {
+ {
+ kClawNowhere,
+ kClawNowhere,
+ kClawAtB,
+ kClawNowhere
+ },
+ {
+ kClawNowhere,
+ kClawAtA,
+ kClawAtD,
+ kClawAtC
+ },
+ {
+ kClawAtB,
+ kClawNowhere,
+ kClawNowhere,
+ kClawNowhere
+ },
+ {
+ kClawNowhere,
+ kClawAtB,
+ kClawNowhere,
+ kClawNowhere
+ }
+};
+
+// Indexed by claw action index, claw position, plus 0 for start, 1 for stop.
+// (Never indexed with kLoopActionIndex.)
+static const TimeValue s_clawMonitorTable[7][4][2] = {
+ {
+ { kAPinchStart, kAPinchStop },
+ { kBPinchStart, kBPinchStop },
+ { kCPinchStart, kCPinchStop },
+ { kDPinchStart, kDPinchStop }
+ },
+ {
+ { 0xffffffff, 0xffffffff },
+ { 0xffffffff, 0xffffffff },
+ { kCToBStart, kCToBStop },
+ { 0xffffffff, 0xffffffff }
+ },
+ {
+ { 0xffffffff, 0xffffffff },
+ { kBToAStart, kBToAStop },
+ { 0xffffffff, 0xffffffff },
+ { kDToBStart, kDToBStop }
+ },
+ {
+ { kAToBStart, kAToBStop },
+ { kBToDStart, kBToDStop },
+ { 0xffffffff, 0xffffffff },
+ { 0xffffffff, 0xffffffff }
+ },
+ {
+ { 0xffffffff, 0xffffffff },
+ { kBToCStart, kBToCStop },
+ { 0xffffffff, 0xffffffff },
+ { 0xffffffff, 0xffffffff }
+ },
+ {
+ { kACCWStart, kACCWStop },
+ { kBCCWStart, kBCCWStop },
+ { kCCCWStart, kCCCWStop },
+ { kDCCWStart, kDCCWStop }
+ },
+ {
+ { kACWStart, kACWStop },
+ { kBCWStart, kBCWStop },
+ { kCCWStart, kCCWStop },
+ { kDCWStart, kDCWStop }
+ }
+};
+
+// Frame indices for the green ball sprite.
+enum {
+ kGreenBallAtA,
+ kGreenBallAtAWithClaw,
+ kGreenBallAtAWithClawAndRobot,
+ kGreenBallAtB,
+ kGreenBallAtBWithClaw,
+ kGreenBallAtBWithClawAndRobot,
+ kGreenBallAtCArmAtA,
+ kGreenBallAtCArmAtB,
+ kGreenBallAtCArmAtD,
+ kGreenBallAtCWithClaw,
+ kGreenBallAtD,
+ kGreenBallAtDWithClaw,
+ kNumClawGreenBalls
+};
+
+// State constants for _robotState.
+enum {
+ kNoRobot,
+ kRobotApproaching,
+ kPunchingOnce,
+ kPunchingTwice,
+ kPunchingThrice,
+ kCarriedToDoor,
+ kPlayerWon,
+ kRobotWon
+};
+
+// Sub Control Room button PICTs:
+static const ResIDType kSubControlButtonBaseID = 500;
+static const ResIDType kClawMonitorGreenBallBaseID = 600;
+
+// Constructor
+SubControlRoom::SubControlRoom(Neighborhood *handler) : GameInteraction(kNoradSubControlRoomInteractionID, handler),
+ _subControlMovie(kSubControlMonitorID), _subControlNotification(kSubControlNotificationID, (PegasusEngine *)g_engine),
+ _clawMonitorMovie(kClawMonitorID), _pinchButton(kSubControlPinchID), _downButton(kSubControlDownID),
+ _rightButton(kSubControlRightID), _leftButton(kSubControlLeftID), _upButton(kSubControlUpID),
+ _ccwButton(kSubControlCCWID), _cwButton(kSubControlCWID), _greenBall(kClawMonitorGreenBallID),
+ _greenBallNotification(kNoradGreenBallNotificationID, (PegasusEngine *)g_engine) {
+ _neighborhoodNotification = handler->getNeighborhoodNotification();
+ _playingAgainstRobot = false;
+ _robotState = kNoRobot;
+}
+
+void SubControlRoom::playAgainstRobot() {
+ _playingAgainstRobot = true;
+}
+
+void SubControlRoom::openInteraction() {
+ _currentAction = kNoActionIndex;
+ _nextAction = kNoActionIndex;
+
+ Norad *owner = (Norad *)getOwner();
+ owner->getClawInfo(_outSpotID, _prepSpotID, _clawControlSpotID, _clawButtonSpotIDs[0],
+ _clawButtonSpotIDs[1], _clawButtonSpotIDs[2], _clawButtonSpotIDs[3],
+ _clawButtonSpotIDs[4], _clawButtonSpotIDs[5], _clawButtonSpotIDs[6],
+ _clawStartPosition, _clawExtraIDs);
+
+ _clawPosition = _clawStartPosition;
+ _clawNextPosition = _clawPosition;
+ _subControlMovie.initFromMovieFile("Images/Norad Alpha/N22 Left Monitor Movie");
+ _subControlMovie.setVolume(((PegasusEngine *)g_engine)->getSoundFXLevel());
+ _subControlMovie.moveElementTo(kNoradSubControlLeft, kNoradSubControlTop);
+ _subControlScale = _subControlMovie.getScale();
+ _subControlMovie.setDisplayOrder(kSubControlOrder);
+ _subControlMovie.startDisplaying();
+ _subControlCallBack.setNotification(&_subControlNotification);
+ _subControlCallBack.initCallBack(&_subControlMovie, kCallBackAtExtremes);
+
+ _clawMonitorMovie.initFromMovieFile("Images/Norad Alpha/N22:N60 Right Monitor");
+ _clawMonitorMovie.moveElementTo(kNoradClawMonitorLeft, kNoradClawMonitorTop);
+ _clawMonitorMovie.setDisplayOrder(kClawMonitorOrder);
+ _clawMonitorMovie.startDisplaying();
+ _clawMonitorCallBack.setNotification(&_subControlNotification);
+ _clawMonitorCallBack.initCallBack(&_clawMonitorMovie, kCallBackAtExtremes);
+
+ _subControlNotification.notifyMe(this, kSubControlNotificationFlags, kSubControlNotificationFlags);
+
+ _neighborhoodNotification->notifyMe(this, kExtraCompletedFlag, kExtraCompletedFlag);
+
+ _buttons[0] = &_pinchButton;
+ _buttons[1] = &_downButton;
+ _buttons[2] = &_rightButton;
+ _buttons[3] = &_leftButton;
+ _buttons[4] = &_upButton;
+ _buttons[5] = &_ccwButton;
+ _buttons[6] = &_cwButton;
+
+ _pinchButton.setDisplayOrder(kSubControlPinchOrder);
+ _downButton.setDisplayOrder(kSubControlDownOrder);
+ _rightButton.setDisplayOrder(kSubControlRightOrder);
+ _leftButton.setDisplayOrder(kSubControlLeftOrder);
+ _upButton.setDisplayOrder(kSubControlUpOrder);
+ _ccwButton.setDisplayOrder(kSubControlCCWOrder);
+ _cwButton.setDisplayOrder(kSubControlCWOrder);
+
+ for (int i = 0; i < kNumClawButtons; i++) {
+ SpriteFrame *frame = new SpriteFrame();
+ frame->initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kSubControlButtonBaseID + i * 3, true);
+ _buttons[i]->addFrame(frame, 0, 0);
+
+ frame = new SpriteFrame();
+ frame->initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kSubControlButtonBaseID + i * 3 + 1, true);
+ _buttons[i]->addFrame(frame, 0, 0);
+
+ frame = new SpriteFrame();
+ frame->initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kSubControlButtonBaseID + i * 3 + 2, true);
+ _buttons[i]->addFrame(frame, 0, 0);
+
+ _buttons[i]->setCurrentFrameIndex(0);
+ _buttons[i]->startDisplaying();
+ }
+
+ _pinchButton.moveElementTo(kNoradSubControlPinchLeft, kNoradSubControlPinchTop);
+ _downButton.moveElementTo(kNoradSubControlDownLeft, kNoradSubControlDownTop);
+ _rightButton.moveElementTo(kNoradSubControlRightLeft, kNoradSubControlRightTop);
+ _leftButton.moveElementTo(kNoradSubControlLeftLeft, kNoradSubControlLeftTop);
+ _upButton.moveElementTo(kNoradSubControlUpLeft, kNoradSubControlUpTop);
+ _ccwButton.moveElementTo(kNoradSubControlCCWLeft, kNoradSubControlCCWTop);
+ _cwButton.moveElementTo(kNoradSubControlCWLeft, kNoradSubControlCWTop);
+
+ _greenBall.setDisplayOrder(kClawMonitorGreenBallOrder);
+
+ for (int i = 0; i < kNumClawGreenBalls; i++) {
+ SpriteFrame *frame = new SpriteFrame();
+ frame->initFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kClawMonitorGreenBallBaseID + i);
+ _greenBall.addFrame(frame, 0, 0);
+ }
+
+ _greenBall.setCurrentFrameIndex(0);
+ _greenBall.startDisplaying();
+
+ _greenBallTimer.setScale(owner->getNavMovie()->getScale());
+ _greenBallCallBack.setNotification(&_greenBallNotification);
+ _greenBallCallBack.initCallBack(&_greenBallTimer, kCallBackAtExtremes);
+ _greenBallCallBack.setCallBackFlag(kOneSecondOfMoveFinished);
+ _greenBallNotification.notifyMe(this, kGreenBallNotificationFlags, kGreenBallNotificationFlags);
+
+ _subControlMovie.show();
+ _clawMonitorMovie.show();
+}
+
+void SubControlRoom::initInteraction() {
+ if (GameState.getNoradSubPrepState() == kSubDamaged) {
+ playControlMonitorSection(kDeltaSplashStart * _subControlScale, kDeltaSplashStop * _subControlScale,
+ 0, kDeltaSplash, false);
+ playClawMonitorSection(kDeltaClawSplashStart, kDeltaClawSplashStop, kDeltaSplashFinished, _gameState, false);
+ } else {
+ playControlMonitorSection(kAlphaSplashStart * _subControlScale, kAlphaSplashStop * _subControlScale,
+ 0, kAlphaSplash, false);
+ playClawMonitorSection(kAlphaClawSplashStart, kAlphaClawSplashStop, kAlphaSplashFinished, _gameState, false);
+ }
+
+ _subControlMovie.redrawMovieWorld();
+ _clawMonitorMovie.redrawMovieWorld();
+}
+
+void SubControlRoom::closeInteraction() {
+ _subControlNotification.cancelNotification(this);
+ _subControlCallBack.releaseCallBack();
+ _greenBallNotification.cancelNotification(this);
+ _greenBallCallBack.releaseCallBack();
+ _neighborhoodNotification->cancelNotification(this);
+}
+
+void SubControlRoom::setSoundFXLevel(const uint16 fxLevel) {
+ _subControlMovie.setVolume(fxLevel);
+}
+
+void SubControlRoom::receiveNotification(Notification *notification, const NotificationFlags flags) {
+ Norad *owner = (Norad *)getOwner();
+
+ if (notification == &_subControlNotification) {
+ switch (flags) {
+ case kAlphaSplashFinished:
+ setControlMonitorToTime(kMainMenuTime * _subControlScale, kAlphaMainMenu, true);
+ break;
+ case kPrepHighlightFinished:
+ if (GameState.getNoradSubPrepState() == kSubDamaged)
+ playControlMonitorSection(kDeltaLaunchPrepStart * _subControlScale,
+ kDeltaLaunchPrepStop * _subControlScale, kDeltaPrepFinished, _gameState, false);
+ else
+ playControlMonitorSection(kAlphaLaunchPrepStart * _subControlScale,
+ kAlphaLaunchPrepStop * _subControlScale, kAlphaPrepFinished, _gameState, false);
+ break;
+ case kAlphaPrepFinished:
+ GameState.setNoradSubPrepState(kSubPrepped);
+ GameState.setScoringPreppedSub(true);
+ setControlMonitorToTime(kMainMenuTime * _subControlScale, kAlphaMainMenu, true);
+ break;
+ case kClawHighlightFinished:
+ playControlMonitorSection(kClawMenuStart * _subControlScale, kClawMenuStop * _subControlScale,
+ kClawMenuFinished, _gameState, false);
+ break;
+ case kClawMenuFinished:
+ owner->playClawMonitorIntro();
+ showButtons();
+ setControlMonitorToTime(kClawMenuTime * _subControlScale, kClawMenu, true);
+
+ if (!_playingAgainstRobot) {
+ updateClawMonitor();
+ owner->loopExtraSequence(_clawExtraIDs[s_clawStateTable[_clawPosition][kLoopActionIndex]]);
+ }
+ break;
+ case kDeltaSplashFinished:
+ setControlMonitorToTime(kMainMenuTime * _subControlScale, kDeltaMainMenu, true);
+
+ if (_playingAgainstRobot) {
+ _robotState = kRobotApproaching;
+ playClawMonitorSection(kRobotApproachStart, kRobotApproachStop, 0, _gameState, true);
+ owner->startExtraSequence(kN60RobotApproaches, kExtraCompletedFlag, kFilterAllInput);
+ }
+ break;
+ case kDeltaPrepFinished:
+ setControlMonitorToTime(kMainMenuTime * _subControlScale, kDeltaMainMenu, true);
+ break;
+ }
+ } else if (notification == &_greenBallNotification) {
+ if (_robotState == kRobotWon) {
+ // We are using the green ball notification to hide stuff when the robot comes through
+ // the glass.
+ hideEverything();
+ } else {
+ // We are now midway through a move, time to update the claw's position and the green
+ // ball.
+ _clawPosition = _clawNextPosition;
+ updateClawMonitor();
+ updateGreenBall();
+ }
+ } else if (notification == _neighborhoodNotification) {
+ _currentAction = kNoActionIndex;
+ if (_playingAgainstRobot) {
+ switch (_robotState) {
+ case kRobotApproaching:
+ if (_gameState == kClawMenu) {
+ _robotState = kPunchingOnce;
+ dispatchClawAction(kNoActionIndex);
+ } else {
+ robotKillsPlayer(kN60FirstMistake, owner);
+ }
+ break;
+ case kPunchingOnce:
+ if (_nextAction == kMoveDownActionIndex) {
+ _robotState = kPunchingTwice;
+ performActionImmediately(_nextAction, _clawExtraIDs[s_clawStateTable[_clawPosition][_nextAction]], owner);
+ } else {
+ robotKillsPlayer(kN60SecondMistake, owner);
+ }
+ break;
+ case kPunchingTwice:
+ if (_nextAction == kPinchActionIndex) {
+ _robotState = kPunchingThrice;
+ performActionImmediately(_nextAction, _clawExtraIDs[s_clawStateTable[_clawPosition][_nextAction]], owner);
+ } else {
+ robotKillsPlayer(kN60ThirdMistake, owner);
+ }
+ break;
+ case kPunchingThrice:
+ if (_nextAction == kMoveRightActionIndex) {
+ _robotState = kCarriedToDoor;
+ performActionImmediately(_nextAction, _clawExtraIDs[s_clawStateTable[_clawPosition][_nextAction]], owner);
+ } else {
+ robotKillsPlayer(kN60FourthMistake, owner);
+ }
+ break;
+ case kCarriedToDoor:
+ hideEverything();
+ _robotState = kPlayerWon;
+ owner->startExtraSequence(kN60PlayerFollowsRobotToDoor, kExtraCompletedFlag, kFilterAllInput);
+ break;
+ case kPlayerWon:
+ ((NoradDelta *)owner)->playerBeatRobotWithClaw();
+ owner->requestDeleteCurrentInteraction();
+ break;
+ case kRobotWon:
+ g_system->delayMillis(2 * 1000); // 120 ticks
+ ((PegasusEngine *)g_engine)->die(kDeathRobotSubControlRoom);
+ break;
+ }
+ } else {
+ if (_gameState == kPuttingClawAway && _nextAction == kNoActionIndex) {
+ if (_clawPosition == _clawStartPosition) {
+ Input scratch;
+ GameInteraction::clickInHotspot(scratch, g_allHotspots.findHotspotByID(_outSpotID));
+ } else {
+ switch (_clawPosition) {
+ case kClawAtA:
+ dispatchClawAction(kMoveLeftActionIndex);
+ break;
+ case kClawAtB:
+ if (_clawStartPosition == kClawAtD) // Norad Alpha
+ dispatchClawAction(kMoveLeftActionIndex);
+ else if (_clawStartPosition == kClawAtC) // Norad Delta
+ dispatchClawAction(kMoveUpActionIndex);
+ break;
+ case kClawAtC:
+ dispatchClawAction(kMoveDownActionIndex);
+ break;
+ case kClawAtD:
+ dispatchClawAction(kMoveRightActionIndex);
+ break;
+ }
+ }
+ } else {
+ dispatchClawAction(_nextAction);
+ }
+ }
+ }
+}
+
+void SubControlRoom::hideEverything() {
+ hideButtons();
+ _subControlMovie.hide();
+ _clawMonitorMovie.hide();
+ _greenBall.hide();
+}
+
+void SubControlRoom::robotKillsPlayer(const uint32 extraID, Neighborhood *owner) {
+ _robotState = kRobotWon;
+ owner->startExtraSequence(extraID, kExtraCompletedFlag, kFilterAllInput);
+ _greenBallTimer.stop();
+ _greenBallTimer.setSegment(0, 32 * _greenBallTimer.getScale() / 15);
+ _greenBallTimer.setTime(0);
+ _greenBallCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ _greenBallTimer.start();
+}
+
+void SubControlRoom::activateHotspots() {
+ if (_robotState == kRobotWon || _robotState == kPlayerWon)
+ return;
+
+ GameInteraction::activateHotspots();
+
+ switch (_gameState) {
+ case kAlphaMainMenu:
+ case kDeltaMainMenu:
+ g_allHotspots.activateOneHotspot(_prepSpotID);
+ g_allHotspots.activateOneHotspot(_clawControlSpotID);
+ break;
+ case kClawMenu:
+ // This could be called during a move, so use _clawNextPosition.
+ if (_playingAgainstRobot) {
+ g_allHotspots.deactivateOneHotspot(_outSpotID);
+ if (_robotState != kRobotApproaching && _nextAction == kNoActionIndex)
+ for (int i = 0; i < kNumClawButtons; i++)
+ if (s_clawStateTable[_clawNextPosition][i] != kNoActionIndex)
+ g_allHotspots.activateOneHotspot(_clawButtonSpotIDs[i]);
+ } else if (_nextAction == kNoActionIndex) {
+ for (int i = 0; i < kNumClawButtons; i++)
+ if (s_clawStateTable[_clawNextPosition][i] != kNoActionIndex)
+ g_allHotspots.activateOneHotspot(_clawButtonSpotIDs[i]);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void SubControlRoom::showButtons() {
+ if (_playingAgainstRobot && _robotState == kRobotApproaching) {
+ for (int i = 0; i < kNumClawButtons; i++) {
+ _buttons[i]->show();
+ _buttons[i]->setCurrentFrameIndex(kButtonDimFrame);
+ }
+ } else if (_nextAction != kNoActionIndex) {
+ for (int i = 0; i < kNumClawButtons; i++) {
+ _buttons[i]->show();
+ if (i == _currentAction || i == _nextAction)
+ _buttons[i]->setCurrentFrameIndex(kButtonHighlightedFrame);
+ else
+ _buttons[i]->setCurrentFrameIndex(kButtonDimFrame);
+ }
+ } else {
+ for (int i = 0; i < kNumClawButtons; i++) {
+ _buttons[i]->show();
+ if (i == _currentAction)
+ _buttons[i]->setCurrentFrameIndex(kButtonHighlightedFrame);
+ else if (s_clawStateTable[_clawNextPosition][i] != kNoActionIndex &&
+ _gameState != kPuttingClawAway) // this could be called during a move, so check _clawNextPosition
+ _buttons[i]->setCurrentFrameIndex(kButtonActiveFrame);
+ else
+ _buttons[i]->setCurrentFrameIndex(kButtonDimFrame);
+ }
+ }
+}
+
+void SubControlRoom::hideButtons() {
+ for (int i = 0; i < kNumClawButtons; i++)
+ _buttons[i]->hide();
+}
+
+int SubControlRoom::findActionIndex(HotSpotID id) {
+ for (int i = 0; i < kNumClawButtons; i++)
+ if (id == _clawButtonSpotIDs[i])
+ return i;
+
+ return kNoActionIndex;
+}
+
+void SubControlRoom::clickInHotspot(const Input &input, const Hotspot *spot) {
+ HotSpotID clickedID = spot->getObjectID();
+ int actionIndex = findActionIndex(clickedID);
+
+ if (actionIndex != kNoActionIndex) {
+ dispatchClawAction(actionIndex);
+ } else if (clickedID == _prepSpotID) {
+ playControlMonitorSection(kLaunchPrepHighlightStart * _subControlScale,
+ kLaunchPrepHighlightStop * _subControlScale,
+ kPrepHighlightFinished, kPlayingHighlight, false);
+ } else if (clickedID == _clawControlSpotID) {
+ playControlMonitorSection(kClawControlHighlightStart * _subControlScale,
+ kClawControlHighlightStop * _subControlScale,
+ kClawHighlightFinished, kPlayingHighlight, false);
+ } else if (clickedID == _outSpotID) {
+ _gameState = kPuttingClawAway;
+
+ if (_currentAction == kNoActionIndex) {
+ if (_clawPosition == _clawStartPosition) {
+ GameInteraction::clickInHotspot(input, spot);
+ } else {
+ switch (_clawPosition) {
+ case kClawAtA:
+ dispatchClawAction(kMoveLeftActionIndex);
+ break;
+ case kClawAtB:
+ if (_clawStartPosition == kClawAtD) // Norad Alpha
+ dispatchClawAction(kMoveLeftActionIndex);
+ else if (_clawStartPosition == kClawAtC) // Norad Delta
+ dispatchClawAction(kMoveUpActionIndex);
+ break;
+ case kClawAtC:
+ dispatchClawAction(kMoveDownActionIndex);
+ break;
+ case kClawAtD:
+ dispatchClawAction(kMoveRightActionIndex);
+ break;
+ }
+ }
+ }
+ } else {
+ GameInteraction::clickInHotspot(input, spot);
+ }
+}
+
+void SubControlRoom::dispatchClawAction(const int newAction) {
+ GameState.setScoringPlayedWithClaw(true);
+
+ Neighborhood *owner = getOwner();
+
+ if (newAction == kNoActionIndex) {
+ _currentAction = kNoActionIndex;
+ _nextAction = kNoActionIndex;
+ showButtons();
+ updateGreenBall();
+
+ if (_playingAgainstRobot)
+ owner->startExtraSequence(kN60ArmActivated, kExtraCompletedFlag, kFilterAllInput);
+ else
+ owner->loopExtraSequence(_clawExtraIDs[s_clawStateTable[_clawPosition][kLoopActionIndex]]);
+ } else {
+ if (_currentAction == kNoActionIndex) {
+ if (_playingAgainstRobot) {
+ _nextAction = newAction;
+ showButtons();
+ updateGreenBall();
+ } else {
+ performActionImmediately(newAction, _clawExtraIDs[s_clawStateTable[_clawPosition][newAction]], owner);
+ }
+ } else if (_nextAction == kNoActionIndex) {
+ _nextAction = newAction;
+ showButtons();
+ updateGreenBall();
+ }
+ }
+}
+
+void SubControlRoom::performActionImmediately(const int action, const uint32 extraID, Neighborhood *owner) {
+ _currentAction = action;
+ _nextAction = kNoActionIndex;
+ ExtraTable::Entry entry;
+
+ switch (action) {
+ case kMoveDownActionIndex:
+ case kMoveRightActionIndex:
+ case kMoveLeftActionIndex:
+ case kMoveUpActionIndex:
+ // Set up green ball callback.
+ owner->getExtraEntry(extraID, entry);
+ _greenBallTimer.stop();
+ _greenBallTimer.setSegment(entry.movieStart, entry.movieStart + owner->getNavMovie()->getScale());
+ _greenBallTimer.setTime(entry.movieStart);
+ _greenBallCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ // Start move.
+ _greenBallTimer.start();
+ break;
+ }
+
+ if (_playingAgainstRobot) {
+ switch (_robotState) {
+ case kPunchingTwice:
+ owner->startExtraSequence(kN60ArmToPositionB, kExtraCompletedFlag, kFilterAllInput);
+ break;
+ case kPunchingThrice:
+ owner->startExtraSequence(kN60ArmGrabsRobot, kExtraCompletedFlag, kFilterAllInput);
+ break;
+ case kCarriedToDoor:
+ owner->startExtraSequence(kN60ArmCarriesRobotToPositionA, kExtraCompletedFlag, kFilterAllInput);
+ break;
+ }
+ } else {
+ owner->startExtraSequence(extraID, kExtraCompletedFlag, kFilterAllInput);
+ }
+
+ switch (action) {
+ case kMoveDownActionIndex:
+ _clawNextPosition = s_clawMovieTable[_clawPosition][kMoveClawDown];
+ break;
+ case kMoveRightActionIndex:
+ _clawNextPosition = s_clawMovieTable[_clawPosition][kMoveClawRight];
+ break;
+ case kMoveLeftActionIndex:
+ _clawNextPosition = s_clawMovieTable[_clawPosition][kMoveClawLeft];
+ break;
+ case kMoveUpActionIndex:
+ _clawNextPosition = s_clawMovieTable[_clawPosition][kMoveClawUp];
+ break;
+ case kLoopActionIndex:
+ // Do nothing.
+ break;
+ default:
+ playClawMonitorSection(s_clawMonitorTable[action][_clawPosition][0],
+ s_clawMonitorTable[action][_clawPosition][1], 0, _gameState, true);
+ break;
+ }
+
+ showButtons();
+ updateGreenBall();
+}
+
+void SubControlRoom::setControlMonitorToTime(const TimeValue newTime, const int newState, const bool shouldAllowInput) {
+ _subControlMovie.stop();
+ _subControlMovie.setSegment(0, _subControlMovie.getDuration());
+ _subControlMovie.setTime(newTime);
+ _subControlMovie.redrawMovieWorld();
+ _gameState = newState;
+ allowInput(shouldAllowInput);
+}
+
+void SubControlRoom::playControlMonitorSection(const TimeValue in, const TimeValue out, const NotificationFlags flags,
+ const int newState, const bool shouldAllowInput) {
+ _subControlMovie.stop();
+ _subControlMovie.setSegment(in, out);
+ _subControlMovie.setTime(in);
+
+ if (flags != 0) {
+ _subControlCallBack.setCallBackFlag(flags);
+ _subControlCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ }
+
+ _gameState = newState;
+ allowInput(shouldAllowInput);
+ _subControlMovie.start();
+}
+
+void SubControlRoom::updateClawMonitor() {
+ switch (_clawPosition) {
+ case kClawAtA:
+ setClawMonitorToTime(kClawAtATime);
+ break;
+ case kClawAtB:
+ setClawMonitorToTime(kClawAtBTime);
+ break;
+ case kClawAtC:
+ setClawMonitorToTime(kClawAtCTime);
+ break;
+ case kClawAtD:
+ setClawMonitorToTime(kClawAtDTime);
+ break;
+ }
+}
+
+void SubControlRoom::setClawMonitorToTime(const TimeValue newTime) {
+ _clawMonitorMovie.stop();
+ _clawMonitorMovie.setSegment(0, _clawMonitorMovie.getDuration());
+ _clawMonitorMovie.setTime(newTime);
+ _clawMonitorMovie.redrawMovieWorld();
+}
+
+void SubControlRoom::playClawMonitorSection(const TimeValue in, const TimeValue out, const NotificationFlags flags,
+ const int newState, const bool shouldAllowInput) {
+ _clawMonitorMovie.stop();
+ _clawMonitorMovie.setSegment(in, out);
+ _clawMonitorMovie.setTime(in);
+
+ if (flags != 0) {
+ _clawMonitorCallBack.setCallBackFlag(flags);
+ _clawMonitorCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ }
+
+ _gameState = newState;
+ allowInput(shouldAllowInput);
+ _clawMonitorMovie.start();
+}
+
+void SubControlRoom::updateGreenBall() {
+ switch (_currentAction) {
+ case kMoveDownActionIndex:
+ switch (_nextAction) {
+ case kMoveRightActionIndex:
+ moveGreenBallToA();
+ break;
+ case kMoveLeftActionIndex:
+ moveGreenBallToD();
+ break;
+ case kMoveUpActionIndex:
+ moveGreenBallToC();
+ break;
+ default:
+ moveGreenBallToB();
+ break;
+ }
+ break;
+ case kMoveRightActionIndex:
+ if (_clawNextPosition == kClawAtA) {
+ switch (_nextAction) {
+ case kMoveLeftActionIndex:
+ moveGreenBallToB();
+ break;
+ default:
+ moveGreenBallToA();
+ break;
+ }
+ } else {
+ switch (_nextAction) {
+ case kMoveRightActionIndex:
+ moveGreenBallToA();
+ break;
+ case kMoveLeftActionIndex:
+ moveGreenBallToD();
+ break;
+ case kMoveUpActionIndex:
+ moveGreenBallToC();
+ break;
+ default:
+ moveGreenBallToB();
+ break;
+ }
+ }
+ break;
+ case kMoveLeftActionIndex:
+ if (_clawNextPosition == kClawAtB) {
+ switch (_nextAction) {
+ case kMoveRightActionIndex:
+ moveGreenBallToA();
+ break;
+ case kMoveLeftActionIndex:
+ moveGreenBallToD();
+ break;
+ case kMoveUpActionIndex:
+ moveGreenBallToC();
+ break;
+ default:
+ moveGreenBallToB();
+ break;
+ }
+ } else {
+ switch (_nextAction) {
+ case kMoveRightActionIndex:
+ moveGreenBallToB();
+ break;
+ default:
+ moveGreenBallToD();
+ break;
+ }
+ }
+ break;
+ case kMoveUpActionIndex:
+ switch (_nextAction) {
+ case kMoveDownActionIndex:
+ moveGreenBallToB();
+ break;
+ default:
+ moveGreenBallToC();
+ break;
+ }
+ break;
+ default:
+ switch (_nextAction) {
+ case kMoveDownActionIndex:
+ moveGreenBallToB();
+ break;
+ case kMoveRightActionIndex:
+ if (_clawPosition == kClawAtB)
+ moveGreenBallToA();
+ else
+ moveGreenBallToB();
+ break;
+ case kMoveLeftActionIndex:
+ if (_clawPosition == kClawAtB)
+ moveGreenBallToD();
+ else
+ moveGreenBallToB();
+ break;
+ case kMoveUpActionIndex:
+ moveGreenBallToC();
+ break;
+ default:
+ _greenBall.hide();
+ break;
+ }
+ break;
+ }
+}
+
+void SubControlRoom::moveGreenBallToA() {
+ if (_clawPosition == kClawAtA) {
+ if (_playingAgainstRobot)
+ _greenBall.setCurrentFrameIndex(kGreenBallAtAWithClawAndRobot);
+ else
+ _greenBall.setCurrentFrameIndex(kGreenBallAtAWithClaw);
+ } else {
+ _greenBall.setCurrentFrameIndex(kGreenBallAtA);
+ }
+
+ _greenBall.moveElementTo(kNoradGreenBallAtALeft, kNoradGreenBallAtATop);
+ _greenBall.show();
+}
+
+void SubControlRoom::moveGreenBallToB() {
+ if (_clawPosition == kClawAtB) {
+ if (_playingAgainstRobot)
+ _greenBall.setCurrentFrameIndex(kGreenBallAtBWithClawAndRobot);
+ else
+ _greenBall.setCurrentFrameIndex(kGreenBallAtBWithClaw);
+ } else {
+ _greenBall.setCurrentFrameIndex(kGreenBallAtB);
+ }
+
+ _greenBall.moveElementTo(kNoradGreenBallAtBLeft, kNoradGreenBallAtBTop);
+ _greenBall.show();
+}
+
+void SubControlRoom::moveGreenBallToC() {
+ switch (_clawPosition) {
+ case kClawAtA:
+ _greenBall.setCurrentFrameIndex(kGreenBallAtCArmAtA);
+ break;
+ case kClawAtB:
+ _greenBall.setCurrentFrameIndex(kGreenBallAtCArmAtB);
+ break;
+ case kClawAtC:
+ _greenBall.setCurrentFrameIndex(kGreenBallAtCWithClaw);
+ break;
+ case kClawAtD:
+ _greenBall.setCurrentFrameIndex(kGreenBallAtCArmAtD);
+ break;
+ }
+
+ _greenBall.moveElementTo(kNoradGreenBallAtCLeft, kNoradGreenBallAtCTop);
+ _greenBall.show();
+}
+
+void SubControlRoom::moveGreenBallToD() {
+ if (_clawPosition == kClawAtD)
+ _greenBall.setCurrentFrameIndex(kGreenBallAtDWithClaw);
+ else
+ _greenBall.setCurrentFrameIndex(kGreenBallAtD);
+
+ _greenBall.moveElementTo(kNoradGreenBallAtDLeft, kNoradGreenBallAtDTop);
+ _greenBall.show();
+}
+
+bool SubControlRoom::canSolve() {
+ return _playingAgainstRobot && _robotState < kCarriedToDoor;
+}
+
+void SubControlRoom::doSolve() {
+ _robotState = kCarriedToDoor;
+ hideEverything();
+ getOwner()->startExtraSequence(kN60ArmGrabsRobot, kExtraCompletedFlag, kFilterAllInput);
+}
+
+InputBits SubControlRoom::getInputFilter() {
+ if (_playingAgainstRobot)
+ return GameInteraction::getInputFilter() & ~kFilterDownButtonAny;
+
+ return GameInteraction::getInputFilter();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/norad/subcontrolroom.h b/engines/pegasus/neighborhood/norad/subcontrolroom.h
new file mode 100644
index 0000000000..6ce599db42
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/subcontrolroom.h
@@ -0,0 +1,133 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_NORAD_SUBCONTROLROOM_H
+#define PEGASUS_NEIGHBORHOOD_NORAD_SUBCONTROLROOM_H
+
+#include "pegasus/interaction.h"
+#include "pegasus/notification.h"
+
+namespace Pegasus {
+
+static const uint32 kClawAtA = 0;
+static const uint32 kClawAtB = 1;
+static const uint32 kClawAtC = 2;
+static const uint32 kClawAtD = 3;
+
+static const int kNumClawButtons = 7;
+
+class Norad;
+
+class SubControlRoom : public GameInteraction, public NotificationReceiver {
+public:
+ SubControlRoom(Neighborhood *);
+ virtual ~SubControlRoom() {}
+
+ void playAgainstRobot();
+
+ virtual void setSoundFXLevel(const uint16);
+
+ bool canSolve();
+ void doSolve();
+
+protected:
+ virtual void openInteraction();
+ virtual void initInteraction();
+ virtual void closeInteraction();
+
+ virtual void activateHotspots();
+ virtual void clickInHotspot(const Input &, const Hotspot *);
+
+ virtual void receiveNotification(Notification *, const NotificationFlags);
+
+ void robotKillsPlayer(const uint32, Neighborhood *);
+ InputBits getInputFilter();
+
+ int findActionIndex(HotSpotID);
+ void dispatchClawAction(const int);
+ void performActionImmediately(const int, const uint32, Neighborhood *);
+
+ void hideEverything();
+ void showButtons();
+ void hideButtons();
+
+ void updateGreenBall();
+ void moveGreenBallToA();
+ void moveGreenBallToB();
+ void moveGreenBallToC();
+ void moveGreenBallToD();
+
+ void setControlMonitorToTime(const TimeValue, const int, const bool);
+ void playControlMonitorSection(const TimeValue, const TimeValue, const NotificationFlags,
+ const int, const bool);
+
+ void updateClawMonitor();
+ void setClawMonitorToTime(const TimeValue);
+ void playClawMonitorSection(const TimeValue, const TimeValue, const NotificationFlags,
+ const int, const bool);
+
+ Movie _subControlMovie;
+ TimeScale _subControlScale;
+ Notification _subControlNotification;
+ NotificationCallBack _subControlCallBack;
+ Movie _clawMonitorMovie;
+ NotificationCallBack _clawMonitorCallBack;
+ int _gameState;
+ uint32 _clawStartPosition;
+ uint32 _clawPosition;
+ uint32 _clawNextPosition;
+ const uint32 *_clawExtraIDs;
+
+ int _currentAction;
+ int _nextAction;
+
+ Sprite *_buttons[kNumClawButtons];
+ Sprite _pinchButton;
+ Sprite _downButton;
+ Sprite _rightButton;
+ Sprite _leftButton;
+ Sprite _upButton;
+ Sprite _ccwButton;
+ Sprite _cwButton;
+
+ Sprite _greenBall;
+ TimeBase _greenBallTimer;
+ Notification _greenBallNotification;
+ NotificationCallBack _greenBallCallBack;
+
+ HotSpotID _outSpotID;
+ HotSpotID _prepSpotID;
+ HotSpotID _clawControlSpotID;
+ HotSpotID _clawButtonSpotIDs[kNumClawButtons];
+
+ Notification *_neighborhoodNotification;
+
+ bool _playingAgainstRobot;
+ int _robotState;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/norad/subplatform.cpp b/engines/pegasus/neighborhood/norad/subplatform.cpp
new file mode 100644
index 0000000000..97079a9f53
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/subplatform.cpp
@@ -0,0 +1,205 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/neighborhood/norad/constants.h"
+#include "pegasus/neighborhood/norad/norad.h"
+#include "pegasus/neighborhood/norad/subplatform.h"
+#include "pegasus/neighborhood/norad/alpha/noradalpha.h"
+
+namespace Pegasus {
+
+// As usual, times here are in seconds.
+
+static const TimeValue kNormalSplashStart = 0;
+static const TimeValue kNormalSplashStop = 5;
+
+static const TimeValue kPrepSubStart = 5;
+static const TimeValue kPrepSubStop = 15;
+
+static const TimeValue kPrepIncompleteStart = 15;
+static const TimeValue kPrepIncompleteStop = 19;
+
+static const TimeValue kDamagedStart = 19;
+static const TimeValue kDamagedStop = 28;
+
+static const NotificationFlags kNormalSplashFinished = 1;
+static const NotificationFlags kPrepSubFinished = kNormalSplashFinished << 1;
+static const NotificationFlags kPrepIncompleteFinished = kPrepSubFinished << 1;
+static const NotificationFlags kDamagedFinished = kPrepIncompleteFinished << 1;
+
+static const NotificationFlags kPlatformNotificationFlags = kNormalSplashFinished |
+ kPrepSubFinished |
+ kPrepIncompleteFinished |
+ kDamagedFinished;
+
+static const uint16 kSubPreppedBit = (1 << 0);
+static const uint16 kWaitingForPlayerBit = (1 << 1);
+
+SubPlatform::SubPlatform(Neighborhood *handler) : GameInteraction(kNoradSubPlatformInteractionID, handler),
+ _platformMovie(kPlatformMonitorID), _platformNotification(kNoradSubPlatformNotificationID, (PegasusEngine *)g_engine) {
+ _neighborhoodNotification = handler->getNeighborhoodNotification();
+}
+
+void SubPlatform::openInteraction() {
+ _stateBits = 0;
+
+ // TODO: These next two lines seem unused?
+ if (GameState.getNoradSubPrepState() == kSubPrepped)
+ _stateBits |= kSubPreppedBit;
+
+ _stateBits |= kWaitingForPlayerBit;
+ _platformMovie.initFromMovieFile("Images/Norad Alpha/Platform Monitor Movie");
+ _platformMovie.setVolume(((PegasusEngine *)g_engine)->getSoundFXLevel());
+ _platformMovie.moveElementTo(kNoradPlatformLeft, kNoradPlatformTop);
+ _platformScale = _platformMovie.getScale();
+ _platformMovie.setDisplayOrder(kPlatformOrder);
+ _platformMovie.startDisplaying();
+ _platformCallBack.setNotification(&_platformNotification);
+ _platformCallBack.initCallBack(&_platformMovie, kCallBackAtExtremes);
+
+ _platformNotification.notifyMe(this, kPlatformNotificationFlags, kPlatformNotificationFlags);
+}
+
+void SubPlatform::initInteraction() {
+ _neighborhoodNotification->notifyMe(this, kExtraCompletedFlag, kExtraCompletedFlag);
+}
+
+void SubPlatform::closeInteraction() {
+ _platformNotification.cancelNotification(this);
+ _platformCallBack.releaseCallBack();
+ _neighborhoodNotification->cancelNotification(this);
+}
+
+void SubPlatform::setSoundFXLevel(const uint16 fxLevel) {
+ _platformMovie.setVolume(fxLevel);
+}
+
+void SubPlatform::receiveNotification(Notification *notification, const NotificationFlags flags) {
+ FaderMoveSpec loop1Spec, loop2Spec;
+ ExtraTable::Entry entry;
+
+ Norad *owner = (Norad *)getOwner();
+
+ if (notification == &_platformNotification) {
+ switch (flags) {
+ case kNormalSplashFinished:
+ _platformMovie.stop();
+ switch (GameState.getNoradSubPrepState()) {
+ case kSubNotPrepped:
+ _platformMovie.setSegment(kPrepIncompleteStart * _platformScale, kPrepIncompleteStop * _platformScale);
+ _platformMovie.setTime(kPrepIncompleteStart * _platformScale);
+ _platformCallBack.setCallBackFlag(kPrepIncompleteFinished);
+ _platformCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ _platformMovie.start();
+ break;
+ case kSubPrepped:
+ _platformMovie.setSegment(kPrepSubStart * _platformScale, kPrepSubStop * _platformScale);
+ _platformMovie.setTime(kPrepSubStart * _platformScale);
+ _platformCallBack.setCallBackFlag(kPrepSubFinished);
+ _platformCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ owner->startExtraSequence(kNorad19PrepSub, 0, kFilterNoInput);
+ _platformMovie.start();
+ break;
+ case kSubDamaged:
+ // Shouldn't happen.
+ break;
+ }
+ break;
+ case kPrepSubFinished:
+ _platformMovie.stop();
+ _platformMovie.stopDisplaying();
+
+ owner->getExtraEntry(kNorad19ExitToSub, entry);
+
+ loop1Spec.makeTwoKnotFaderSpec(kNoradAlphaMovieScale, 0, kNoradWarningVolume,
+ entry.movieEnd - entry.movieStart, 0);
+ loop1Spec.insertFaderKnot(4560, kNoradWarningVolume);
+ loop1Spec.insertFaderKnot(5080, 0);
+
+ loop2Spec.makeTwoKnotFaderSpec(kNoradAlphaMovieScale, 0, kNoradSuckWindVolume,
+ entry.movieEnd - entry.movieStart, 0);
+ loop1Spec.insertFaderKnot(4560, kNoradSuckWindVolume);
+ loop1Spec.insertFaderKnot(5080, 0);
+
+ owner->startExtraSequence(kNorad19ExitToSub, kExtraCompletedFlag, kFilterNoInput);
+
+ owner->startLoop1Fader(loop1Spec);
+ owner->startLoop2Fader(loop2Spec);
+ break;
+ case kPrepIncompleteFinished:
+ ((NoradAlpha *)owner)->setSubPrepFailed(true);
+ g_AIArea->checkMiddleArea();
+ // Fall through...
+ case kDamagedFinished:
+ _platformMovie.stop();
+ _platformMovie.hide();
+ _stateBits |= kWaitingForPlayerBit;
+ allowInput(true);
+ break;
+ }
+ } else if (notification == _neighborhoodNotification) {
+ allowInput(true);
+ ((PegasusEngine *)g_engine)->jumpToNewEnvironment(kNoradSubChaseID, kNoRoomID, kNoDirection);
+ GameState.setScoringEnteredSub(true);
+ }
+}
+
+void SubPlatform::activateHotspots() {
+ if (_stateBits & kWaitingForPlayerBit)
+ g_allHotspots.activateOneHotspot(kNorad19ActivateMonitorSpotID);
+
+ GameInteraction::activateHotspots();
+}
+
+void SubPlatform::clickInHotspot(const Input &input, const Hotspot *spot) {
+ if (spot->getObjectID() == kNorad19ActivateMonitorSpotID) {
+ if (GameState.getNoradSubPrepState() == kSubDamaged) {
+ _platformMovie.setSegment(kDamagedStart * _platformScale, kDamagedStop * _platformScale);
+ _platformMovie.setTime(kDamagedStart * _platformScale);
+ _platformCallBack.setCallBackFlag(kDamagedFinished);
+ } else {
+ _platformMovie.setSegment(kNormalSplashStart * _platformScale, kNormalSplashStop * _platformScale);
+ _platformMovie.setTime(kNormalSplashStart * _platformScale);
+ _platformCallBack.setCallBackFlag(kNormalSplashFinished);
+ }
+
+ _platformCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+
+ _platformMovie.show();
+ _platformMovie.start();
+ _platformMovie.redrawMovieWorld();
+
+ _stateBits &= ~kWaitingForPlayerBit;
+
+ allowInput(false);
+ } else {
+ GameInteraction::clickInHotspot(input, spot);
+ }
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/norad/subplatform.h b/engines/pegasus/neighborhood/norad/subplatform.h
new file mode 100644
index 0000000000..82e86ecae2
--- /dev/null
+++ b/engines/pegasus/neighborhood/norad/subplatform.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_NORAD_SUBPLATFORM_H
+#define PEGASUS_NEIGHBORHOOD_NORAD_SUBPLATFORM_H
+
+#include "pegasus/interaction.h"
+#include "pegasus/movie.h"
+#include "pegasus/notification.h"
+#include "pegasus/timers.h"
+
+namespace Pegasus {
+
+class SubPlatform : public GameInteraction, public NotificationReceiver {
+public:
+ SubPlatform(Neighborhood *);
+ virtual ~SubPlatform() {}
+
+ virtual void setSoundFXLevel(const uint16);
+
+protected:
+ virtual void openInteraction();
+ virtual void initInteraction();
+ virtual void closeInteraction();
+
+ virtual void activateHotspots();
+ virtual void clickInHotspot(const Input &, const Hotspot *);
+
+ virtual void receiveNotification(Notification *, const NotificationFlags);
+
+ Movie _platformMovie;
+ TimeScale _platformScale;
+ Notification _platformNotification;
+ NotificationCallBack _platformCallBack;
+ Notification *_neighborhoodNotification;
+ uint16 _stateBits;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/prehistoric/prehistoric.cpp b/engines/pegasus/neighborhood/prehistoric/prehistoric.cpp
new file mode 100644
index 0000000000..814d7717de
--- /dev/null
+++ b/engines/pegasus/neighborhood/prehistoric/prehistoric.cpp
@@ -0,0 +1,689 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/compass.h"
+#include "pegasus/energymonitor.h"
+#include "pegasus/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/ai/ai_action.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/ai/ai_condition.h"
+#include "pegasus/ai/ai_rule.h"
+#include "pegasus/neighborhood/prehistoric/prehistoric.h"
+
+namespace Pegasus {
+
+static const int16 s_prehistoricCompass[kPrehistoric25 + 1][4] = {
+ { 0, 170, 90, 270 }, // kPrehistoric01
+ { 0, 180, 90, 270 }, // kPrehistoric02
+ { 10, 180, 90, 270 }, // kPrehistoric03
+ { 10, 190, 90, 270 }, // kPrehistoric04
+ { 10, 195, 90, 270 }, // kPrehistoric05
+ { 20, 210, 90, 270 }, // kPrehistoric06
+ { 20, 200, 130, 276 }, // kPrehistoric07
+ { 20, 176, 110, 260 }, // kPrehistoric08
+ { 20, 200, 100, 270 }, // kPrehistoric09
+ { 14, 186, 100, 280 }, // kPrehistoric10
+ { 26, 206, 116, 296 }, // kPrehistoric11
+ { 60, 226, 140, 320 }, // kPrehistoric12
+ { 0, 180, 80, 270 }, // kPrehistoric13
+ { 14, 200, 106, 286 }, // kPrehistoric14
+ { -10, 174, 80, 260 }, // kPrehistoric15
+ { 54, 236, 140, 210 }, // kPrehistoric16
+ { -24, 160, 70, 250 }, // kPrehistoric17
+ { 26, 206, 140, 296 }, // kPrehistoric18
+ { -16, 160, 70, 250 }, // kPrehistoric19
+ { -16, 160, 70, 250 }, // kPrehistoric20
+ { -10, 160, 90, 250 }, // kPrehistoric21
+ { -20, 160, 70, 244 }, // kPrehistoric22
+ { -20, 160, 70, 244 }, // kPrehistoric22North
+ { 60, 234, 150, 330 }, // kPrehistoric23
+ { 50, 230, 140, 320 }, // kPrehistoric24
+ { 60, 240, 140, 330 } // kPrehistoric25
+};
+
+static const TimeValue kPrehistoricFlashlightClickIn = 0;
+static const TimeValue kPrehistoricFlashlightClickOut = 138;
+
+static const TimeValue kPrehistoricBumpIntoWallIn = 138;
+static const TimeValue kPrehistoricBumpIntoWallOut = 291;
+
+static const TimeValue kBridgeRetractIn = 291;
+static const TimeValue kBridgeRetractOut = 1499;
+
+static const TimeValue kPrehistoricWarningTimeLimit = kTenMinutes;
+
+Prehistoric::Prehistoric(InputHandler *nextHandler, PegasusEngine *owner) : Neighborhood(nextHandler, owner, "Prehistoric", kPrehistoricID) {
+ setIsItemTaken(kHistoricalLog);
+}
+
+uint16 Prehistoric::getDateResID() const {
+ return kDatePrehistoricID;
+}
+
+void Prehistoric::init() {
+ Neighborhood::init();
+
+ // Forces a stop so the flashlight can turn off...
+ forceStridingStop(kPrehistoric12, kSouth, kNoAlternateID);
+}
+
+void Prehistoric::start() {
+ if (g_energyMonitor) {
+ g_energyMonitor->stopEnergyDraining();
+ g_energyMonitor->restoreLastEnergyValue();
+ _vm->resetEnergyDeathReason();
+ g_energyMonitor->startEnergyDraining();
+ }
+
+ Neighborhood::start();
+}
+
+class FinishPrehistoricAction : public AIPlayMessageAction {
+public:
+ FinishPrehistoricAction() : AIPlayMessageAction("Images/AI/Prehistoric/XP25W", false) {}
+ ~FinishPrehistoricAction() {}
+
+ void performAIAction(AIRule *);
+
+};
+
+void FinishPrehistoricAction::performAIAction(AIRule *rule) {
+ AIPlayMessageAction::performAIAction(rule);
+ ((PegasusEngine *)g_engine)->die(kPlayerWonGame);
+}
+
+void Prehistoric::setUpAIRules() {
+ Neighborhood::setUpAIRules();
+
+ if (g_AIArea) {
+ if (_vm->isDemo()) {
+ FinishPrehistoricAction *doneAction = new FinishPrehistoricAction();
+ AIHasItemCondition *hasLogCondition = new AIHasItemCondition(kHistoricalLog);
+ AIRule *rule = new AIRule(hasLogCondition, doneAction);
+ g_AIArea->addAIRule(rule);
+ } else {
+ AIPlayMessageAction *messageAction = new AIPlayMessageAction("Images/AI/Prehistoric/XP1NB", false);
+ AILocationCondition *locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kPrehistoric16, kNorth));
+ AIRule *rule = new AIRule(locCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Prehistoric/XP2SB", false);
+ locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kPrehistoric01, kSouth));
+ rule = new AIRule(locCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Prehistoric/XP2SB", false);
+ locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kPrehistoric08, kEast));
+ rule = new AIRule(locCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Prehistoric/XP2SB", false);
+ locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kPrehistoric25, kWest));
+ rule = new AIRule(locCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Prehistoric/XP16NB", false);
+ locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kPrehistoric23, kNorth));
+ rule = new AIRule(locCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Prehistoric/XP18NB", false);
+ AITimerCondition *timerCondition = new AITimerCondition(kPrehistoricWarningTimeLimit, 1, true);
+ rule = new AIRule(timerCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Prehistoric/XP25W", false);
+ AIHasItemCondition *hasLogCondition = new AIHasItemCondition(kHistoricalLog);
+ rule = new AIRule(hasLogCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+ }
+ }
+}
+
+TimeValue Prehistoric::getViewTime(const RoomID room, const DirectionConstant direction) {
+ ExtraTable::Entry extra;
+ uint32 extraID = 0xffffffff;
+
+ switch (MakeRoomView(room, direction)) {
+ case MakeRoomView(kPrehistoric02, kSouth):
+ if (!GameState.getPrehistoricSeenTimeStream()) {
+ getExtraEntry(kPreArrivalFromTSA, extra);
+ return extra.movieStart;
+ }
+ break;
+ case MakeRoomView(kPrehistoric25, kEast):
+ if (_privateFlags.getFlag(kPrehistoricPrivateVaultOpenFlag)) {
+ if (_vm->itemInLocation(kHistoricalLog, kPrehistoricID, kPrehistoric25, kEast))
+ extraID = kPre25EastViewWithLog;
+ else
+ extraID = kPre25EastViewNoLog;
+ }
+ break;
+ }
+
+ if (extraID == 0xffffffff)
+ return Neighborhood::getViewTime(room, direction);
+
+ getExtraEntry(extraID, extra);
+ return extra.movieEnd - 1;
+}
+
+
+void Prehistoric::findSpotEntry(const RoomID room, const DirectionConstant direction, SpotFlags flags, SpotTable::Entry &entry) {
+ Neighborhood::findSpotEntry(room, direction, flags, entry);
+
+ switch (MakeRoomView(room, direction)) {
+ case MakeRoomView(kPrehistoric01, kSouth):
+ case MakeRoomView(kPrehistoric25, kSouth):
+ entry.clear();
+ break;
+ case MakeRoomView(kPrehistoric01, kEast):
+ if (GameState.getPrehistoricSeenFlyer1())
+ entry.clear();
+ else
+ GameState.setPrehistoricSeenFlyer1(true);
+ break;
+ case MakeRoomView(kPrehistoric08, kEast):
+ if (GameState.getPrehistoricSeenFlyer2())
+ entry.clear();
+ else
+ GameState.setPrehistoricSeenFlyer2(true);
+ break;
+ }
+}
+
+int16 Prehistoric::getStaticCompassAngle(const RoomID room, const DirectionConstant dir) {
+ if (room == kPrehistoricDeath)
+ return g_compass->getFaderValue();
+
+ return s_prehistoricCompass[room][dir];
+}
+
+void Prehistoric::getExitCompassMove(const ExitTable::Entry &exitEntry, FaderMoveSpec &compassMove) {
+ uint32 angle;
+ Neighborhood::getExitCompassMove(exitEntry, compassMove);
+
+ switch (MakeRoomView(exitEntry.room, exitEntry.direction)) {
+ case MakeRoomView(kPrehistoric01, kNorth):
+ compassMove.insertFaderKnot(exitEntry.movieStart + (exitEntry.movieEnd - exitEntry.movieStart) / 2, -10);
+ break;
+ case MakeRoomView(kPrehistoric06, kEast):
+ compassMove.insertFaderKnot(exitEntry.movieStart + (exitEntry.movieEnd - exitEntry.movieStart) / 4, 95);
+ compassMove.insertFaderKnot(exitEntry.movieStart + (exitEntry.movieEnd - exitEntry.movieStart) / 4 * 1, 100);
+ break;
+ case MakeRoomView(kPrehistoric18, kEast):
+ if (getCurrentAlternate() == kAltPrehistoricBridgeSet) {
+ compassMove.insertFaderKnot(exitEntry.movieStart + kPrehistoricFrameDuration * 11, 145);
+ compassMove.insertFaderKnot(exitEntry.movieStart + kPrehistoricFrameDuration * 26, 145);
+ compassMove.insertFaderKnot(exitEntry.movieStart + kPrehistoricFrameDuration * 39, 148);
+ compassMove.insertFaderKnot(exitEntry.movieStart + kPrehistoricFrameDuration * 114, 140);
+ } else {
+ compassMove.insertFaderKnot(exitEntry.movieStart + kPrehistoricFrameDuration * 10, 140);
+ compassMove.insertFaderKnot(exitEntry.movieStart + kPrehistoricFrameDuration * 16, 145);
+ compassMove.insertFaderKnot(exitEntry.movieEnd, 145);
+ }
+ break;
+ case MakeRoomView(kPrehistoric23, kWest):
+ angle = compassMove.getNthKnotValue(0);
+ compassMove.insertFaderKnot(exitEntry.movieStart + kPrehistoricFrameDuration * 17, angle);
+ compassMove.insertFaderKnot(exitEntry.movieStart + kPrehistoricFrameDuration * 32, angle - 90);
+ compassMove.insertFaderKnot(exitEntry.movieEnd, angle - 90);
+ break;
+ }
+}
+
+void Prehistoric::turnTo(const DirectionConstant newDirection) {
+ setCurrentAlternate(kAltPrehistoricNormal);
+ _privateFlags.setFlag(kPrehistoricPrivateVaultOpenFlag, false);
+ Neighborhood::turnTo(newDirection);
+
+ Item *keyCard;
+
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kPrehistoric18, kEast):
+ zoomToVault();
+ break;
+ case MakeRoomView(kPrehistoric18, kNorth):
+ case MakeRoomView(kPrehistoric18, kSouth):
+ if (_privateFlags.getFlag(kPrehistoricPrivateExtendedBridgeFlag)) {
+ playSpotSoundSync(kBridgeRetractIn, kBridgeRetractOut);
+ _privateFlags.setFlag(kPrehistoricPrivateExtendedBridgeFlag, false);
+ loadAmbientLoops();
+ }
+ // fall through
+ case MakeRoomView(kPrehistoric25, kEast):
+ setCurrentActivation(kActivationVaultClosed);
+ break;
+ case MakeRoomView(kPrehistoric16, kNorth):
+ case MakeRoomView(kPrehistoric21, kWest):
+ keyCard = _vm->getAllItems().findItemByID(kKeyCard);
+ if (keyCard->getItemState() == kFlashlightOff) {
+ keyCard->setItemState(kFlashlightOn);
+ playSpotSoundSync(kPrehistoricFlashlightClickIn, kPrehistoricFlashlightClickOut);
+ }
+ break;
+ case MakeRoomView(kPrehistoric16, kEast):
+ case MakeRoomView(kPrehistoric16, kWest):
+ case MakeRoomView(kPrehistoric21, kNorth):
+ case MakeRoomView(kPrehistoric21, kSouth):
+ keyCard = _vm->getAllItems().findItemByID(kKeyCard);
+ if (keyCard->getItemState() == kFlashlightOn) {
+ keyCard->setItemState(kFlashlightOff);
+ playSpotSoundSync(kPrehistoricFlashlightClickIn, kPrehistoricFlashlightClickOut);
+ }
+ break;
+ }
+}
+
+void Prehistoric::zoomToVault() {
+ if (!GameState.getPrehistoricSeenBridgeZoom())
+ startExtraSequence(kPre18EastZoom, kExtraCompletedFlag, kFilterNoInput);
+}
+
+void Prehistoric::checkContinuePoint(const RoomID room, const DirectionConstant direction) {
+ switch (MakeRoomView(room, direction)) {
+ case MakeRoomView(kPrehistoric08, kEast):
+ case MakeRoomView(kPrehistoric18, kSouth):
+ case MakeRoomView(kPrehistoric16, kNorth):
+ case MakeRoomView(kPrehistoric21, kNorth):
+ case MakeRoomView(kPrehistoric25, kNorth):
+ makeContinuePoint();
+ break;
+ }
+}
+
+void Prehistoric::arriveAt(const RoomID room, const DirectionConstant direction) {
+ Item *keyCard;
+
+ if (MakeRoomView(room, direction) == MakeRoomView(kPrehistoric25, kEast) &&
+ _privateFlags.getFlag(kPrehistoricPrivateExtendedBridgeFlag)) {
+ _navMovie.stop();
+ playSpotSoundSync(kBridgeRetractIn, kBridgeRetractOut);
+ _privateFlags.setFlag(kPrehistoricPrivateExtendedBridgeFlag, false);
+ }
+
+ Neighborhood::arriveAt(room, direction);
+
+ switch (MakeRoomView(room, direction)) {
+ case MakeRoomView(kPrehistoricDeath, kNorth):
+ case MakeRoomView(kPrehistoricDeath, kSouth):
+ case MakeRoomView(kPrehistoricDeath, kEast):
+ case MakeRoomView(kPrehistoricDeath, kWest):
+ if (GameState.getLastRoom() == kPrehistoric23)
+ die(kDeathEatenByDinosaur);
+ else
+ die(kDeathFallOffCliff);
+ break;
+ case MakeRoomView(kPrehistoric02, kSouth):
+ if (!GameState.getPrehistoricSeenTimeStream()) {
+ GameState.setPrehistoricTriedToExtendBridge(false);
+ GameState.setPrehistoricSeenFlyer1(false);
+ GameState.setPrehistoricSeenFlyer2(false);
+ GameState.setPrehistoricSeenBridgeZoom(false);
+ GameState.setPrehistoricBreakerThrown(false);
+ startExtraSequence(kPreArrivalFromTSA, kExtraCompletedFlag, kFilterNoInput);
+ }
+ break;
+ case MakeRoomView(kPrehistoric18, kEast):
+ zoomToVault();
+ break;
+ case MakeRoomView(kPrehistoric16, kNorth):
+ keyCard = _vm->getAllItems().findItemByID(kKeyCard);
+
+ if (keyCard->getItemState() == kFlashlightOff) {
+ keyCard->setItemState(kFlashlightOn);
+ playSpotSoundSync(kPrehistoricFlashlightClickIn, kPrehistoricFlashlightClickOut);
+ }
+
+ if (g_AIArea)
+ g_AIArea->checkRules();
+ break;
+ case MakeRoomView(kPrehistoric01, kSouth):
+ case MakeRoomView(kPrehistoric23, kNorth):
+ if (g_AIArea)
+ g_AIArea->checkRules();
+ break;
+ case MakeRoomView(kPrehistoric08, kSouth):
+ case MakeRoomView(kPrehistoric10, kSouth):
+ case MakeRoomView(kPrehistoric12, kSouth):
+ case MakeRoomView(kPrehistoric13, kNorth):
+ case MakeRoomView(kPrehistoric14, kSouth):
+ case MakeRoomView(kPrehistoric15, kNorth):
+ case MakeRoomView(kPrehistoric16, kSouth):
+ case MakeRoomView(kPrehistoric17, kNorth):
+ case MakeRoomView(kPrehistoric18, kSouth):
+ case MakeRoomView(kPrehistoric19, kNorth):
+ case MakeRoomView(kPrehistoric20, kNorth):
+ case MakeRoomView(kPrehistoric21, kEast):
+ keyCard = _vm->getAllItems().findItemByID(kKeyCard);
+
+ if (keyCard->getItemState() == kFlashlightOn) {
+ keyCard->setItemState(kFlashlightOff);
+ playSpotSoundSync(kPrehistoricFlashlightClickIn, kPrehistoricFlashlightClickOut);
+ }
+ break;
+ case MakeRoomView(kPrehistoric25, kEast):
+ setCurrentActivation(kActivationVaultClosed);
+ break;
+ }
+}
+
+void Prehistoric::loadAmbientLoops() {
+ RoomID room = GameState.getCurrentRoom();
+
+ switch (room) {
+ case kPrehistoric02:
+ // 1/4 volume.
+ if (GameState.getPrehistoricSeenTimeStream())
+ loadLoopSound1("Sounds/Prehistoric/P02SAL00.22k.AIFF", 64);
+ break;
+ case kPrehistoric01:
+ case kPrehistoric03:
+ case kPrehistoric04:
+ case kPrehistoric05:
+ case kPrehistoric06:
+ case kPrehistoric07:
+ case kPrehistoric09:
+ case kPrehistoric11:
+ case kPrehistoric13:
+ case kPrehistoric15:
+ case kPrehistoric17:
+ case kPrehistoric19:
+ case kPrehistoric20:
+ // 1/4 volume.
+ loadLoopSound1("Sounds/Prehistoric/P02SAL00.22k.AIFF", 64);
+ break;
+ case kPrehistoric08:
+ case kPrehistoric10:
+ case kPrehistoric12:
+ case kPrehistoric14:
+ case kPrehistoric16:
+ case kPrehistoric18:
+ case kPrehistoric21:
+ // 3/16 volume.
+ loadLoopSound1("Sounds/Prehistoric/P02SAL00.22k.AIFF", 48);
+ break;
+ case kPrehistoric25:
+ // 1/8 volume.
+ loadLoopSound1("Sounds/Prehistoric/P02SAL00.22k.AIFF", 32);
+ break;
+ case kPrehistoric22:
+ case kPrehistoric22North:
+ case kPrehistoric23:
+ case kPrehistoric24:
+ case kPrehistoricDeath:
+ // 0 volume.
+ loadLoopSound1("");
+ break;
+ }
+
+ switch (room) {
+ case kPrehistoric02:
+ case kPrehistoric03:
+ case kPrehistoric04:
+ case kPrehistoric05:
+ case kPrehistoric06:
+ case kPrehistoric07:
+ case kPrehistoric08:
+ case kPrehistoric09:
+ case kPrehistoric10:
+ case kPrehistoric11:
+ case kPrehistoric12:
+ case kPrehistoric13:
+ case kPrehistoric14:
+ case kPrehistoric15:
+ case kPrehistoric16:
+ case kPrehistoric17:
+ case kPrehistoric19:
+ case kPrehistoric20:
+ case kPrehistoric21:
+ case kPrehistoricDeath:
+ loadLoopSound2("");
+ break;
+ case kPrehistoric01:
+ case kPrehistoric25:
+ loadLoopSound2("Sounds/Prehistoric/VolcLoop.22K.AIFF", 64);
+ break;
+ case kPrehistoric18:
+ if (_privateFlags.getFlag(kPrehistoricPrivateExtendedBridgeFlag))
+ loadLoopSound2("Sounds/Prehistoric/P18EAL00.22k.AIFF", 0x100, 0, 0);
+ else
+ loadLoopSound2("");
+ break;
+ case kPrehistoric23:
+ case kPrehistoric24:
+ case kPrehistoric22:
+ case kPrehistoric22North:
+ loadLoopSound2("Sounds/Prehistoric/P24NAL00.22k.AIFF", 64);
+ break;
+ }
+}
+
+void Prehistoric::activateHotspots() {
+ Neighborhood::activateHotspots();
+
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kPrehistoric18, kEast):
+ if (!_privateFlags.getFlag(kPrehistoricPrivateExtendedBridgeFlag))
+ _vm->getAllHotspots().activateOneHotspot(kPre18EastSpotID);
+ break;
+ case MakeRoomView(kPrehistoric22North, kNorth):
+ _vm->getAllHotspots().activateOneHotspot(kPre22NorthBreakerSpotID);
+ break;
+ }
+}
+
+void Prehistoric::clickInHotspot(const Input &input, const Hotspot *spot) {
+ switch (spot->getObjectID()) {
+ case kPre18EastSpotID:
+ if (GameState.getPrehistoricBreakerThrown())
+ startExtraSequence(kPre18EastBridgeOn, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraSequence(kPre18EastBridgeOut, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kPre22NorthBreakerSpotID:
+ startExtraSequence(kPre22ThrowBreaker, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ default:
+ Neighborhood::clickInHotspot(input, spot);
+ break;
+ }
+}
+
+void Prehistoric::receiveNotification(Notification *notification, const NotificationFlags flags) {
+ Neighborhood::receiveNotification(notification, flags);
+
+ if ((flags & kExtraCompletedFlag) != 0) {
+ _interruptionFilter = kFilterAllInput;
+
+ switch (_lastExtra) {
+ case kPreArrivalFromTSA:
+ GameState.setPrehistoricSeenTimeStream(true);
+ loadAmbientLoops();
+ makeContinuePoint();
+ break;
+ case kPre18EastZoom:
+ startExtraSequence(kPre18EastZoomOut, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kPre18EastZoomOut:
+ GameState.setPrehistoricSeenBridgeZoom(true);
+ break;
+ case kPre18EastBridgeOn:
+ _privateFlags.setFlag(kPrehistoricPrivateExtendedBridgeFlag, true);
+ setCurrentAlternate(kAltPrehistoricBridgeSet);
+ GameState.setPrehistoricTriedToExtendBridge(false);
+ loadAmbientLoops();
+ GameState.setScoringExtendedBridge(true);
+ break;
+ case kPre18EastBridgeOut:
+ GameState.setPrehistoricTriedToExtendBridge(true);
+ if (g_AIArea)
+ g_AIArea->checkMiddleArea();
+ break;
+ case kPre22ThrowBreaker:
+ GameState.setPrehistoricBreakerThrown(true);
+ GameState.setScoringThrewBreaker(true);
+ break;
+ case kPre25EastUnlockingVaultNoLog:
+ case kPre25EastUnlockingVaultWithLog:
+ _vm->addItemToInventory((InventoryItem *)_vm->getAllItems().findItemByID(kJourneymanKey));
+ break;
+ }
+ }
+
+ g_AIArea->checkMiddleArea();
+}
+
+Common::String Prehistoric::getBriefingMovie() {
+ Common::String movieName = Neighborhood::getBriefingMovie();
+
+ if (movieName.empty())
+ movieName = "Images/AI/Prehistoric/XPE";
+
+ return movieName;
+}
+
+Common::String Prehistoric::getEnvScanMovie() {
+ Common::String movieName = Neighborhood::getEnvScanMovie();
+
+ if (movieName.empty()) {
+ if (!_vm->isDemo()) {
+ switch (GameState.getCurrentRoom()) {
+ case kPrehistoric16:
+ case kPrehistoric23:
+ case kPrehistoric24:
+ return "Images/AI/Prehistoric/XP7WB";
+ }
+ }
+
+ return "Images/AI/Prehistoric/XP17NB";
+ }
+
+ return movieName;
+}
+
+uint Prehistoric::getNumHints() {
+ uint numHints = Neighborhood::getNumHints();
+
+ if (numHints == 0) {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kPrehistoric18, kEast):
+ if (!GameState.getPrehistoricBreakerThrown() && GameState.getPrehistoricTriedToExtendBridge() &&
+ !_privateFlags.getFlag(kPrehistoricPrivateExtendedBridgeFlag))
+ numHints = 1;
+ break;
+ case MakeRoomView(kPrehistoric25, kEast):
+ if (!_privateFlags.getFlag(kPrehistoricPrivateVaultOpenFlag))
+ numHints = 1;
+ break;
+ }
+ }
+
+ return numHints;
+}
+
+Common::String Prehistoric::getHintMovie(uint hintNum) {
+ Common::String movieName = Neighborhood::getHintMovie(hintNum);
+
+ if (movieName.empty()) {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kPrehistoric18, kEast):
+ return "Images/AI/Prehistoric/XP18WD";
+ case MakeRoomView(kPrehistoric25, kEast):
+ return "Images/AI/Globals/XGLOB1A";
+ }
+ }
+
+ return movieName;
+}
+
+bool Prehistoric::canSolve() {
+ return GameState.getCurrentRoomAndView() == MakeRoomView(kPrehistoric18, kEast) &&
+ !GameState.getPrehistoricBreakerThrown() &&
+ GameState.getPrehistoricTriedToExtendBridge() &&
+ !_privateFlags.getFlag(kPrehistoricPrivateExtendedBridgeFlag);
+}
+
+void Prehistoric::doSolve() {
+ GameState.setPrehistoricBreakerThrown(true);
+ startExtraSequence(kPre18EastBridgeOn, kExtraCompletedFlag, kFilterNoInput);
+}
+
+Hotspot *Prehistoric::getItemScreenSpot(Item *item, DisplayElement *element) {
+ if (item->getObjectID() == kHistoricalLog)
+ return _vm->getAllHotspots().findHotspotByID(kPrehistoricHistoricalLogSpotID);
+
+ return Neighborhood::getItemScreenSpot(item, element);
+}
+
+void Prehistoric::pickedUpItem(Item *item) {
+ switch (item->getObjectID()) {
+ case kHistoricalLog:
+ GameState.setScoringGotHistoricalLog(true);
+ break;
+ }
+
+ Neighborhood::pickedUpItem(item);
+}
+
+void Prehistoric::dropItemIntoRoom(Item *item, Hotspot *dropSpot) {
+ switch (item->getObjectID()) {
+ case kJourneymanKey:
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+
+ if (GameState.isTakenItemID(kHistoricalLog))
+ startExtraLongSequence(kPre25EastUnlockingVaultNoLog, kPre25EastVaultOpenNoLog, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraLongSequence(kPre25EastUnlockingVaultWithLog, kPre25EastVaultOpenWithLog, kExtraCompletedFlag, kFilterNoInput);
+
+ _privateFlags.setFlag(kPrehistoricPrivateVaultOpenFlag, true);
+ setCurrentActivation(kActivationVaultOpen);
+ break;
+ default:
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ break;
+ }
+}
+
+void Prehistoric::bumpIntoWall() {
+ requestSpotSound(kPrehistoricBumpIntoWallIn, kPrehistoricBumpIntoWallOut, kFilterAllInput, 0);
+ Neighborhood::bumpIntoWall();
+}
+
+Common::String Prehistoric::getNavMovieName() {
+ return "Images/Prehistoric/Prehistoric.movie";
+}
+
+Common::String Prehistoric::getSoundSpotsName() {
+ return "Sounds/Prehistoric/Prehistoric Spots";
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/prehistoric/prehistoric.h b/engines/pegasus/neighborhood/prehistoric/prehistoric.h
new file mode 100644
index 0000000000..17f9993014
--- /dev/null
+++ b/engines/pegasus/neighborhood/prehistoric/prehistoric.h
@@ -0,0 +1,158 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_PREHISTORIC_H
+#define PEGASUS_NEIGHBORHOOD_PREHISTORIC_H
+
+#include "pegasus/neighborhood/neighborhood.h"
+
+namespace Pegasus {
+
+static const TimeScale kPrehistoricMovieScale = 600;
+static const TimeScale kPrehistoricFramesPerSecond = 15;
+static const TimeScale kPrehistoricFrameDuration = 40;
+
+// Alternate IDs.
+
+static const AlternateID kAltPrehistoricNormal = 0;
+static const AlternateID kAltPrehistoricBridgeSet = 1;
+
+// Room IDs.
+
+static const RoomID kPrehistoric01 = 0;
+static const RoomID kPrehistoric02 = 1;
+static const RoomID kPrehistoric03 = 2;
+static const RoomID kPrehistoric04 = 3;
+static const RoomID kPrehistoric05 = 4;
+static const RoomID kPrehistoric06 = 5;
+static const RoomID kPrehistoric07 = 6;
+static const RoomID kPrehistoric08 = 7;
+static const RoomID kPrehistoric09 = 8;
+static const RoomID kPrehistoric10 = 9;
+static const RoomID kPrehistoric11 = 10;
+static const RoomID kPrehistoric12 = 11;
+static const RoomID kPrehistoric13 = 12;
+static const RoomID kPrehistoric14 = 13;
+static const RoomID kPrehistoric15 = 14;
+static const RoomID kPrehistoric16 = 15;
+static const RoomID kPrehistoric17 = 16;
+static const RoomID kPrehistoric18 = 17;
+static const RoomID kPrehistoric19 = 18;
+static const RoomID kPrehistoric20 = 19;
+static const RoomID kPrehistoric21 = 20;
+static const RoomID kPrehistoric22 = 21;
+static const RoomID kPrehistoric22North = 22;
+static const RoomID kPrehistoric23 = 23;
+static const RoomID kPrehistoric24 = 24;
+static const RoomID kPrehistoric25 = 25;
+static const RoomID kPrehistoricDeath = 26;
+
+// Hot Spot Activation IDs.
+
+static const HotSpotActivationID kActivationVaultClosed = 1;
+static const HotSpotActivationID kActivationVaultOpen = 2;
+
+// Hot Spot IDs.
+
+static const HotSpotID kPre18EastSpotID = 5000;
+static const HotSpotID kPre22NorthSpotID = 5001;
+static const HotSpotID kPre22NorthOutSpotID = 5002;
+static const HotSpotID kPre22NorthBreakerSpotID = 5003;
+static const HotSpotID kPrehistoricKeyDropSpotID = 5004;
+static const HotSpotID kPrehistoricHistoricalLogSpotID = 5005;
+
+// Extra sequence IDs.
+
+static const ExtraID kPreArrivalFromTSA = 0;
+static const ExtraID kPre18EastBridgeOut = 1;
+static const ExtraID kPre18EastBridgeOn = 2;
+static const ExtraID kPre18EastZoom = 3;
+static const ExtraID kPre18EastZoomOut = 4;
+static const ExtraID kPre22ThrowBreaker = 5;
+static const ExtraID kPre25EastUnlockingVaultWithLog = 6;
+static const ExtraID kPre25EastVaultOpenWithLog = 7;
+static const ExtraID kPre25EastViewWithLog = 8;
+static const ExtraID kPre25EastUnlockingVaultNoLog = 9;
+static const ExtraID kPre25EastVaultOpenNoLog = 10;
+static const ExtraID kPre25EastViewNoLog = 11;
+
+class PegasusEngine;
+
+class Prehistoric : public Neighborhood {
+public:
+ Prehistoric(InputHandler *, PegasusEngine *);
+ virtual ~Prehistoric() {}
+
+ virtual uint16 getDateResID() const;
+ virtual void init();
+
+ virtual void arriveAt(const RoomID, const DirectionConstant);
+ virtual void activateHotspots();
+ virtual void clickInHotspot(const Input &, const Hotspot *);
+ Common::String getBriefingMovie();
+ Common::String getEnvScanMovie();
+ uint getNumHints();
+ Common::String getHintMovie(uint);
+
+ Hotspot *getItemScreenSpot(Item *, DisplayElement *);
+ void dropItemIntoRoom(Item *, Hotspot *);
+ void pickedUpItem(Item *);
+
+ void start();
+
+ void bumpIntoWall();
+
+ void checkContinuePoint(const RoomID, const DirectionConstant);
+
+ bool canSolve();
+ void doSolve();
+
+protected:
+ enum {
+ kPrehistoricPrivateVaultOpenFlag,
+ kPrehistoricPrivateExtendedBridgeFlag,
+ kNumPrehistoricPrivateFlags
+ };
+
+ void setUpAIRules();
+ int16 getStaticCompassAngle(const RoomID, const DirectionConstant);
+ void getExitCompassMove(const ExitTable::Entry &, FaderMoveSpec &);
+ virtual void receiveNotification(Notification *, const NotificationFlags);
+ void turnTo(const DirectionConstant);
+ void zoomToVault();
+ TimeValue getViewTime(const RoomID, const DirectionConstant);
+ void findSpotEntry(const RoomID, const DirectionConstant, SpotFlags, SpotTable::Entry &);
+
+ void loadAmbientLoops();
+
+ FlagsArray<byte, kNumPrehistoricPrivateFlags> _privateFlags;
+
+ Common::String getNavMovieName();
+ Common::String getSoundSpotsName();
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/spot.cpp b/engines/pegasus/neighborhood/spot.cpp
new file mode 100644
index 0000000000..f285bf9bc2
--- /dev/null
+++ b/engines/pegasus/neighborhood/spot.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/textconsole.h"
+
+#include "pegasus/neighborhood/spot.h"
+
+namespace Pegasus {
+
+void SpotTable::loadFromStream(Common::SeekableReadStream *stream) {
+ uint32 count = stream->readUint32BE();
+ _entries.resize(count);
+
+ for (uint32 i = 0; i < count; i++) {
+ _entries[i].room = stream->readUint16BE();
+ _entries[i].direction = stream->readByte();
+ _entries[i].srcFlags = stream->readByte();
+ _entries[i].altCode = stream->readByte();
+ stream->readByte(); // alignment
+ _entries[i].movieStart = stream->readUint32BE();
+ _entries[i].movieEnd = stream->readUint32BE();
+ _entries[i].dstFlags = stream->readByte();
+ stream->readByte(); // alignment
+ debug(0, "Spot[%d]: %d %d %d %d %d %d %d", i, _entries[i].room, _entries[i].direction,
+ _entries[i].srcFlags, _entries[i].altCode, _entries[i].movieStart,
+ _entries[i].movieEnd, _entries[i].dstFlags);
+ }
+}
+
+void SpotTable::clear() {
+ _entries.clear();
+}
+
+// Two SpotTable::Entries are equal if
+// In addition to having their rooms, directions and alt codes identical...
+// They are both either loops or once only animations AND
+// They overlap in at least one of the on arrival, on turn and on door open bits.
+SpotTable::Entry SpotTable::findEntry(RoomID room, DirectionConstant direction, SpotFlags srcFlags, AlternateID altCode) {
+ for (uint32 i = 0; i < _entries.size(); i++)
+ if (_entries[i].room == room && _entries[i].direction == direction && _entries[i].altCode == altCode && (_entries[i].srcFlags & kSpotLoopsMask) == (srcFlags & kSpotLoopsMask) && ((_entries[i].srcFlags & srcFlags) & kSpotTriggers) != 0)
+ return _entries[i];
+
+ return Entry();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/spot.h b/engines/pegasus/neighborhood/spot.h
new file mode 100644
index 0000000000..a985420b7c
--- /dev/null
+++ b/engines/pegasus/neighborhood/spot.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_SPOT_H
+#define PEGASUS_NEIGHBORHOOD_SPOT_H
+
+#include "common/array.h"
+#include "common/endian.h"
+
+#include "pegasus/constants.h"
+
+namespace Common {
+ class SeekableReadStream;
+}
+
+namespace Pegasus {
+
+typedef byte SpotFlags;
+
+enum {
+ kSpotLoopsBit, // Loop or once only?
+ kSpotOnArrivalBit,
+ kSpotOnTurnBit,
+ kSpotOnDoorOpenBit
+};
+
+static const SpotFlags kNoSpotFlags = 0;
+static const SpotFlags kSpotLoopsMask = 1 << kSpotLoopsBit;
+static const SpotFlags kSpotOnArrivalMask = 1 << kSpotOnArrivalBit;
+static const SpotFlags kSpotOnTurnMask = 1 << kSpotOnTurnBit;
+static const SpotFlags kSpotOnDoorOpenMask = 1 << kSpotOnDoorOpenBit;
+
+static const SpotFlags kSpotTriggers = kSpotOnArrivalMask | kSpotOnTurnMask | kSpotOnDoorOpenMask;
+
+class SpotTable {
+public:
+ SpotTable() {}
+ ~SpotTable() {}
+
+ static uint32 getResTag() { return MKTAG('S', 'p', 'o', 't'); }
+
+ void loadFromStream(Common::SeekableReadStream *stream);
+ void clear();
+
+ struct Entry {
+ Entry() { clear(); }
+ bool isEmpty() { return movieStart == 0xffffffff; }
+ void clear() {
+ room = kNoRoomID;
+ direction = kNoDirection;
+ srcFlags = kNoSpotFlags;
+ altCode = kNoAlternateID;
+ movieStart = 0xffffffff;
+ movieEnd = 0xffffffff;
+ dstFlags = kNoSpotFlags;
+ }
+
+ RoomID room;
+ DirectionConstant direction;
+ SpotFlags srcFlags;
+ AlternateID altCode;
+ TimeValue movieStart;
+ TimeValue movieEnd;
+ SpotFlags dstFlags;
+ };
+
+ Entry findEntry(RoomID room, DirectionConstant direction, SpotFlags srcFlags, AlternateID altCode);
+
+private:
+ Common::Array<Entry> _entries;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/tsa/fulltsa.cpp b/engines/pegasus/neighborhood/tsa/fulltsa.cpp
new file mode 100644
index 0000000000..b598841b45
--- /dev/null
+++ b/engines/pegasus/neighborhood/tsa/fulltsa.cpp
@@ -0,0 +1,3023 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/cursor.h"
+#include "pegasus/energymonitor.h"
+#include "pegasus/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/biochips/aichip.h"
+#include "pegasus/items/biochips/opticalchip.h"
+#include "pegasus/neighborhood/caldoria/caldoria.h"
+#include "pegasus/neighborhood/norad/constants.h"
+#include "pegasus/neighborhood/prehistoric/prehistoric.h"
+#include "pegasus/neighborhood/mars/constants.h"
+#include "pegasus/neighborhood/tsa/fulltsa.h"
+#include "pegasus/neighborhood/wsc/wsc.h"
+
+namespace Pegasus {
+
+// TSA PICTs:
+
+static const ResIDType kTBPCloseBoxPICTID = 800;
+static const ResIDType kTBPRewindPICTID = 801;
+static const ResIDType kUnresolvedPICTID = 802;
+static const ResIDType kResolvedPICTID = 803;
+static const ResIDType kJumpMenuPICTID = 804;
+static const ResIDType kJumpMenuHilitedPICTID = 805;
+static const ResIDType kExitPICTID = 806;
+static const ResIDType kExitHilitedPICTID = 807;
+static const ResIDType kLeftRipPICTID = 808;
+static const ResIDType kComparisonCloseBoxPICTID = 809;
+static const ResIDType kComparisonLeftRewindPICTID = 810;
+static const ResIDType kComparisonRightRewindPICTID = 811;
+static const ResIDType kComparisonHiliteNoradPICTID = 812;
+static const ResIDType kComparisonHiliteMarsPICTID = 813;
+static const ResIDType kComparisonHiliteCaldoriaPICTID = 814;
+static const ResIDType kComparisonHiliteWSCPICTID = 815;
+static const ResIDType kComparisonChancesNoradPICTID = 816;
+static const ResIDType kComparisonChancesMarsPICTID = 817;
+static const ResIDType kComparisonChancesCaldoriaPICTID = 818;
+static const ResIDType kComparisonChancesWSCPICTID = 819;
+static const ResIDType kRedirectionCCRolloverPICTID = 820;
+static const ResIDType kRedirectionRRRolloverPICTID = 821;
+static const ResIDType kRedirectionFDRolloverPICTID = 822;
+static const ResIDType kRedirectionCCDoorPICTID = 823;
+static const ResIDType kRedirectionRRDoorPICTID = 824;
+static const ResIDType kRedirectionFDDoorPICTID = 825;
+static const ResIDType kRedirectionSecuredPICTID = 826;
+static const ResIDType kRedirectionNewTargetPICTID = 827;
+static const ResIDType kRedirectionClosePICTID = 828;
+
+static const int16 kCompassShift = 15;
+
+static const TimeScale kFullTSAMovieScale = 600;
+static const TimeScale kFullTSAFramesPerSecond = 15;
+static const TimeScale kFullTSAFrameDuration = 40;
+
+// Alternate IDs.
+static const AlternateID kAltTSANormal = 0;
+static const AlternateID kAltTSARobotsAtReadyRoom = 1;
+static const AlternateID kAltTSARobotsAtFrontDoor = 2;
+static const AlternateID kAltTSARedAlert = 3;
+
+// Room IDs.
+static const RoomID kTSA01 = 1;
+static const RoomID kTSA02 = 2;
+static const RoomID kTSA03 = 3;
+static const RoomID kTSA04 = 4;
+static const RoomID kTSA05 = 5;
+static const RoomID kTSA0A = 6;
+static const RoomID kTSA06 = 7;
+static const RoomID kTSA07 = 8;
+static const RoomID kTSA08 = 9;
+static const RoomID kTSA09 = 10;
+static const RoomID kTSA10 = 11;
+static const RoomID kTSA11 = 12;
+static const RoomID kTSA12 = 13;
+static const RoomID kTSA13 = 14;
+static const RoomID kTSA14 = 15;
+static const RoomID kTSA15 = 16;
+static const RoomID kTSA16 = 17;
+static const RoomID kTSA17 = 18;
+static const RoomID kTSA18 = 19;
+static const RoomID kTSA19 = 20;
+static const RoomID kTSA0B = 21;
+static const RoomID kTSA21Cyan = 22;
+static const RoomID kTSA22Cyan = 23;
+static const RoomID kTSA23Cyan = 24;
+static const RoomID kTSA24Cyan = 25;
+static const RoomID kTSA25Cyan = 26;
+static const RoomID kTSA21Red = 27;
+static const RoomID kTSA23Red = 29;
+static const RoomID kTSA24Red = 30;
+static const RoomID kTSA25Red = 31;
+static const RoomID kTSA26 = 32;
+static const RoomID kTSA27 = 33;
+static const RoomID kTSA28 = 34;
+static const RoomID kTSA29 = 35;
+static const RoomID kTSA30 = 36;
+static const RoomID kTSA31 = 37;
+static const RoomID kTSA32 = 38;
+static const RoomID kTSA33 = 39;
+static const RoomID kTSA34 = 40;
+static const RoomID kTSA35 = 41;
+static const RoomID kTSADeathRoom = 43;
+
+// Hot Spot Activation IDs.
+static const HotSpotActivationID kActivateTSAReadyForCard = 1;
+static const HotSpotActivationID kActivateTSAReadyToTransport = 2;
+static const HotSpotActivationID kActivateTSARobotsAwake = 3;
+static const HotSpotActivationID kActivateTSA0BZoomedOut = 4;
+static const HotSpotActivationID kActivateTSA0BZoomedIn = 5;
+static const HotSpotActivationID kActivateTSA0BComparisonVideo = 6;
+static const HotSpotActivationID kActivationLogReaderOpen = 7;
+static const HotSpotActivationID kActivateTSA0BTBPVideo = 8;
+static const HotSpotActivationID kActivationDoesntHaveKey = 9;
+static const HotSpotActivationID kActivationKeyVaultOpen = 10;
+static const HotSpotActivationID kActivationDoesntHaveChips = 11;
+static const HotSpotActivationID kActivationChipVaultOpen = 12;
+static const HotSpotActivationID kActivationJumpToPrehistoric = 13;
+static const HotSpotActivationID kActivationJumpToNorad = 14;
+static const HotSpotActivationID kActivationJumpToMars = 15;
+static const HotSpotActivationID kActivationJumpToWSC = 16;
+static const HotSpotActivationID kActivationReadyToExit = 17;
+static const HotSpotActivationID kActivationReadyForJumpMenu = 18;
+static const HotSpotActivationID kActivationMainJumpMenu = 19;
+
+// Hot Spot IDs.
+static const HotSpotID kTSAGTCardDropSpotID = 5000;
+static const HotSpotID kTSAGTTokyoSpotID = 5001;
+static const HotSpotID kTSAGTCaldoriaSpotID = 5002;
+static const HotSpotID kTSAGTBeachSpotID = 5003;
+static const HotSpotID kTSAGTOtherSpotID = 5004;
+static const HotSpotID kTSA02DoorSpotID = 5005;
+static const HotSpotID kTSA03EastJimenezSpotID = 5006;
+static const HotSpotID kTSA03WestCrenshawSpotID = 5007;
+static const HotSpotID kTSA04EastMatsumotoSpotID = 5008;
+static const HotSpotID kTSA04WestCastilleSpotID = 5009;
+static const HotSpotID kTSA05EastSinclairSpotID = 5010;
+static const HotSpotID kTSA05WestWhiteSpotID = 5011;
+static const HotSpotID kTSA0AEastSpotID = 5012;
+static const HotSpotID kTSA0AWastSpotID = 5013;
+static const HotSpotID kTSA0BEastMonitorSpotID = 5014;
+static const HotSpotID kTSA0BEastMonitorOutSpotID = 5015;
+static const HotSpotID kTSA0BEastCompareNoradSpotID = 5016;
+static const HotSpotID kTSA0BEastCompareMarsSpotID = 5017;
+static const HotSpotID kTSA0BEastCompareCaldoriaSpotID = 5018;
+static const HotSpotID kTSA0BEastCompareWSCSpotID = 5019;
+static const HotSpotID kTSA0BEastLeftRewindSpotID = 5020;
+static const HotSpotID kTSA0BEastLeftPlaySpotID = 5021;
+static const HotSpotID kTSA0BEastRightRewindSpotID = 5022;
+static const HotSpotID kTSA0BEastRightPlaySpotID = 5023;
+static const HotSpotID kTSA0BEastCloseVideoSpotID = 5024;
+static const HotSpotID kTSA0BNorthMonitorSpotID = 5025;
+static const HotSpotID kTSA0BNorthMonitorOutSpotID = 5026;
+static const HotSpotID kTSA0BNorthHistLogSpotID = 5027;
+static const HotSpotID kTSA0BNorthRobotsToCommandCenterSpotID = 5028;
+static const HotSpotID kTSA0BNorthRobotsToReadyRoomSpotID = 5029;
+static const HotSpotID kTSA0BNorthRobotsToFrontDoorSpotID = 5030;
+static const HotSpotID kTSA0BWestMonitorSpotID = 5031;
+static const HotSpotID kTSA0BWestMonitorOutSpotID = 5032;
+static const HotSpotID kTSA0BWestTheorySpotID = 5033;
+static const HotSpotID kTSA0BWestBackgroundSpotID = 5034;
+static const HotSpotID kTSA0BWestProcedureSpotID = 5035;
+static const HotSpotID kTSA0BWestCloseVideoSpotID = 5036;
+static const HotSpotID kTSA0BWestPlayVideoSpotID = 5037;
+static const HotSpotID kTSA0BWestRewindVideoSpotID = 5038;
+static const HotSpotID kTSA22EastMonitorSpotID = 5039;
+static const HotSpotID kTSA22EastKeySpotID = 5040;
+static const HotSpotID kTSA23WestMonitorSpotID = 5041;
+static const HotSpotID kTSA23WestChipsSpotID = 5042;
+static const HotSpotID kTSA34NorthDoorSpotID = 5043;
+static const HotSpotID kTSA37NorthJumpToPrehistoricSpotID = 5044;
+static const HotSpotID kTSA37NorthJumpToNoradSpotID = 5045;
+static const HotSpotID kTSA37NorthCancelNoradSpotID = 5046;
+static const HotSpotID kTSA37NorthJumpToMarsSpotID = 5047;
+static const HotSpotID kTSA37NorthCancelMarsSpotID = 5048;
+static const HotSpotID kTSA37NorthJumpToWSCSpotID = 5049;
+static const HotSpotID kTSA37NorthCancelWSCSpotID = 5050;
+static const HotSpotID kTSA37NorthExitSpotID = 5051;
+static const HotSpotID kTSA37NorthJumpMenuSpotID = 5052;
+static const HotSpotID kTSA37NorthNoradMenuSpotID = 5053;
+static const HotSpotID kTSA37NorthMarsMenuSpotID = 5054;
+static const HotSpotID kTSA37NorthWSCMenuSpotID = 5055;
+
+// Extra sequence IDs.
+static const ExtraID kTSATransporterArrowLoop = 0;
+static const ExtraID kTSAArriveFromCaldoria = 1;
+static const ExtraID kTSAGTOtherChoice = 2;
+static const ExtraID kTSAGTCardSwipe = 3;
+static const ExtraID kTSAGTSelectCaldoria = 4;
+static const ExtraID kTSAGTGoToCaldoria = 5;
+static const ExtraID kTSAGTSelectBeach = 6;
+static const ExtraID kTSAGTGoToBeach = 7;
+static const ExtraID kTSAGTArriveAtBeach = 8;
+static const ExtraID kTSAGTSelectTokyo = 9;
+static const ExtraID kTSAGTGoToTokyo = 10;
+static const ExtraID kTSAGTArriveAtTokyo = 11;
+static const ExtraID kTSA02NorthZoomIn = 12;
+static const ExtraID kTSA02NorthTenSecondDoor = 13;
+static const ExtraID kTSA02NorthZoomOut = 14;
+static const ExtraID kTSA02NorthDoorWithAgent3 = 15;
+static const ExtraID kTSA03JimenezZoomIn = 16;
+static const ExtraID kTSA03JimenezSpeech = 17;
+static const ExtraID kTSA03JimenezZoomOut = 18;
+static const ExtraID kTSA03CrenshawZoomIn = 19;
+static const ExtraID kTSA03CrenshawSpeech = 20;
+static const ExtraID kTSA03CrenshawZoomOut = 21;
+static const ExtraID kTSA03SouthRobotDeath = 22;
+static const ExtraID kTSA04NorthRobotGreeting = 23;
+static const ExtraID kTSA04MatsumotoZoomIn = 24;
+static const ExtraID kTSA04MatsumotoSpeech = 25;
+static const ExtraID kTSA04MatsumotoZoomOut = 26;
+static const ExtraID kTSA04CastilleZoomIn = 27;
+static const ExtraID kTSA04CastilleSpeech = 28;
+static const ExtraID kTSA04CastilleZoomOut = 29;
+static const ExtraID kTSA05SinclairZoomIn = 30;
+static const ExtraID kTSA05SinclairSpeech = 31;
+static const ExtraID kTSA05SinclairZoomOut = 32;
+static const ExtraID kTSA05WhiteZoomIn = 33;
+static const ExtraID kTSA05WhiteSpeech = 34;
+static const ExtraID kTSA05WhiteZoomOut = 35;
+static const ExtraID kTSA0AEastRobot = 36;
+static const ExtraID kTSA0AWestRobot = 37;
+static const ExtraID kTSA16NorthRobotDeath = 38;
+static const ExtraID kTSA0BEastZoomIn = 39;
+static const ExtraID kTSA0BEastZoomedView = 40;
+static const ExtraID kTSA0BEastZoomOut = 41;
+static const ExtraID kTSA0BEastTurnLeft = 42;
+static const ExtraID kTSA0BComparisonStartup = 43;
+static const ExtraID kTSA0BComparisonView0000 = 44;
+static const ExtraID kTSA0BComparisonView0002 = 45;
+static const ExtraID kTSA0BComparisonView0020 = 46;
+static const ExtraID kTSA0BComparisonView0022 = 47;
+static const ExtraID kTSA0BComparisonView0200 = 48;
+static const ExtraID kTSA0BComparisonView0202 = 49;
+static const ExtraID kTSA0BComparisonView0220 = 50;
+static const ExtraID kTSA0BComparisonView0222 = 51;
+static const ExtraID kTSA0BComparisonView2000 = 52;
+static const ExtraID kTSA0BComparisonView2002 = 53;
+static const ExtraID kTSA0BComparisonView2020 = 54;
+static const ExtraID kTSA0BComparisonView2022 = 55;
+static const ExtraID kTSA0BComparisonView2200 = 56;
+static const ExtraID kTSA0BComparisonView2202 = 57;
+static const ExtraID kTSA0BComparisonView2220 = 58;
+static const ExtraID kTSA0BComparisonView2222 = 59;
+static const ExtraID kTSA0BNoradComparisonView = 60;
+static const ExtraID kTSA0BNoradUnaltered = 61;
+static const ExtraID kTSA0BNoradAltered = 62;
+static const ExtraID kTSA0BMarsComparisonView = 63;
+static const ExtraID kTSA0BMarsUnaltered = 64;
+static const ExtraID kTSA0BMarsAltered = 65;
+static const ExtraID kTSA0BWSCComparisonView = 66;
+static const ExtraID kTSA0BWSCUnaltered = 67;
+static const ExtraID kTSA0BWSCAltered = 68;
+static const ExtraID kTSA0BCaldoriaComparisonView = 69;
+static const ExtraID kTSA0BCaldoriaUnaltered = 70;
+static const ExtraID kTSA0BCaldoriaAltered = 71;
+static const ExtraID kTSA0BNorthZoomIn = 72;
+static const ExtraID kTSA0BNorthZoomedView = 73;
+static const ExtraID kTSA0BNorthZoomOut = 74;
+static const ExtraID kTSA0BNorthTurnLeft = 75;
+static const ExtraID kTSA0BNorthTurnRight = 76;
+static const ExtraID kTSA0BNorthHistLogOpen = 77;
+static const ExtraID kTSA0BNorthHistLogClose = 78;
+static const ExtraID kTSA0BNorthHistLogCloseWithLog = 79;
+static const ExtraID kTSA0BNorthCantChangeHistory = 80;
+static const ExtraID kTSA0BNorthYoureBusted = 81;
+static const ExtraID kTSA0BNorthFinallyHappened = 82;
+static const ExtraID kTSA0BShowRip1 = 83;
+static const ExtraID kTSA0BNorthRipView1 = 84;
+static const ExtraID kTSA0BShowRip2 = 85;
+static const ExtraID kTSA0BShowGuardRobots = 86;
+static const ExtraID kTSA0BAIInterruption = 87;
+static const ExtraID kTSA0BRobotsToCommandCenter = 88;
+static const ExtraID kTSA0BNorthRobotsAtCCView = 89;
+static const ExtraID kTSA0BNorthRobotsAtRRView = 90;
+static const ExtraID kTSA0BNorthRobotsAtFDView = 91;
+static const ExtraID kTSA0BRobotsFromCommandCenterToReadyRoom = 92;
+static const ExtraID kTSA0BRobotsFromReadyRoomToCommandCenter = 93;
+static const ExtraID kTSA0BRobotsFromCommandCenterToFrontDoor = 94;
+static const ExtraID kTSA0BRobotsFromFrontDoorToCommandCenter = 95;
+static const ExtraID kTSA0BRobotsFromFrontDoorToReadyRoom = 96;
+static const ExtraID kTSA0BRobotsFromReadyRoomToFrontDoor = 97;
+static const ExtraID kTSA0BWestZoomIn = 98;
+static const ExtraID kTSA0BWestZoomedView = 99;
+static const ExtraID kTSA0BWestZoomOut = 100;
+static const ExtraID kTSA0BWestTurnRight = 101;
+static const ExtraID kTSA0BTBPTheoryHighlight = 102;
+static const ExtraID kTSA0BTBPBackgroundHighlight = 103;
+static const ExtraID kTSA0BTBPProcedureHighlight = 104;
+static const ExtraID kTSA0BTBPTheory = 105;
+static const ExtraID kTSA0BTBPBackground = 106;
+static const ExtraID kTSA0BTBPProcedure = 107;
+static const ExtraID kTSA0BRipAlarmScreen = 108;
+static const ExtraID kTSA22RedEastZoomInSequence = 109;
+static const ExtraID kTSA22RedEastVaultViewWithKey = 110;
+static const ExtraID kTSA22RedEastVaultViewNoKey = 111;
+static const ExtraID kTSA23RedWestVaultZoomInSequence = 112;
+static const ExtraID kTSA23RedWestVaultViewWithChips = 113;
+static const ExtraID kTSA23RedWestVaultViewNoChips = 114;
+static const ExtraID kTSA25NorthDeniedNoKey = 115;
+static const ExtraID kTSA25NorthDeniedNoChip = 116;
+static const ExtraID kTSA25NorthPutOnSuit = 117;
+static const ExtraID kTSA25NorthAlreadyHaveSuit = 118;
+static const ExtraID kTSA25NorthDescending1 = 119;
+static const ExtraID kTSA25NorthDescending2 = 120;
+static const ExtraID kTSA37HorseToAI1 = 121;
+static const ExtraID kTSA37PegasusAI1 = 122;
+static const ExtraID kTSA37AI1ToCommissioner1 = 123;
+static const ExtraID kTSA37Commissioner1 = 124;
+static const ExtraID kTSA37Commissioner1ToZoom = 125;
+static const ExtraID kTSA37ZoomToPrehistoric = 126;
+static const ExtraID kTSA37PrehistoricToAI2 = 127;
+static const ExtraID kTSA37PegasusAI2 = 128;
+static const ExtraID kTSA37AI2ToPrehistoric = 129;
+static const ExtraID kTSA37PrehistoricToDepart = 130;
+static const ExtraID kTSA37PegasusDepart = 131;
+static const ExtraID kTSA37TimeJumpToPegasus = 132;
+static const ExtraID kTSA37RecallToDownload = 133;
+static const ExtraID kTSA37DownloadToColonel1 = 134;
+static const ExtraID kTSA37Colonel1 = 135;
+static const ExtraID kTSA37Colonel1ToReviewRequired = 136;
+static const ExtraID kTSA37ReviewRequiredToExit = 137;
+static const ExtraID kTSA37ExitHilited = 138;
+static const ExtraID kTSA37ExitToHorse = 139;
+static const ExtraID kTSA37HorseToColonel2 = 140;
+static const ExtraID kTSA37Colonel2 = 141;
+static const ExtraID kTSA37PegasusAI3 = 142;
+static const ExtraID kTSA37AI3ToHorse = 143;
+static const ExtraID kTSA37HorseToZoom = 144;
+static const ExtraID kTSA37ZoomToMainMenu = 145;
+static const ExtraID kTSA37MainMenuToAI4 = 146;
+static const ExtraID kTSA37PegasusAI4 = 147;
+static const ExtraID kTSA37AI4ToMainMenu = 148;
+static const ExtraID kTSA37JumpMenu000 = 149;
+static const ExtraID kTSA37JumpMenu001 = 150;
+static const ExtraID kTSA37JumpMenu010 = 151;
+static const ExtraID kTSA37JumpMenu011 = 152;
+static const ExtraID kTSA37JumpMenu100 = 153;
+static const ExtraID kTSA37JumpMenu101 = 154;
+static const ExtraID kTSA37JumpMenu110 = 155;
+static const ExtraID kTSA37JumpMenu111 = 156;
+static const ExtraID kTSA37JumpToWSCMenu = 157;
+static const ExtraID kTSA37CancelWSC = 158;
+static const ExtraID kTSA37JumpToWSC = 159;
+static const ExtraID kTSA37WSCToAI5 = 160;
+static const ExtraID kTSA37PegasusAI5 = 161;
+static const ExtraID kTSA37AI5ToWSC = 162;
+static const ExtraID kTSA37WSCToDepart = 163;
+static const ExtraID kTSA37JumpToMarsMenu = 164;
+static const ExtraID kTSA37CancelMars = 165;
+static const ExtraID kTSA37JumpToMars = 166;
+static const ExtraID kTSA37MarsToAI6 = 167;
+static const ExtraID kTSA37PegasusAI6 = 168;
+static const ExtraID kTSA37AI6ToMars = 169;
+static const ExtraID kTSA37MarsToDepart = 170;
+static const ExtraID kTSA37JumpToNoradMenu = 171;
+static const ExtraID kTSA37CancelNorad = 172;
+static const ExtraID kTSA37JumpToNorad = 173;
+static const ExtraID kTSA37NoradToAI7 = 174;
+static const ExtraID kTSA37PegasusAI7 = 175;
+static const ExtraID kTSA37AI7ToNorad = 176;
+static const ExtraID kTSA37NoradToDepart = 177;
+static const ExtraID kTSA37EnvironmentalScan = 178;
+static const ExtraID kTSA37DownloadToMainMenu = 179;
+static const ExtraID kTSA37DownloadToOpMemReview = 180;
+static const ExtraID kTSA37OpMemReviewToMainMenu = 181;
+static const ExtraID kTSA37OpMemReviewToAllClear = 182;
+static const ExtraID kTSA37AllClearToCongratulations = 183;
+static const ExtraID kTSA37Congratulations = 184;
+static const ExtraID kTSA37CongratulationsToExit = 185;
+
+const DisplayOrder kRipTimerOrder = kMonitorLayer;
+
+
+const CoordType kUnresolvedLeft = kNavAreaLeft + 14;
+const CoordType kUnresolvedTop = kNavAreaTop + 236;
+
+const CoordType kResolvedLeft = kNavAreaLeft + 36;
+const CoordType kResolvedTop = kNavAreaTop + 236;
+
+const CoordType kJumpMenuLeft = kNavAreaLeft + 360;
+const CoordType kJumpMenuTop = kNavAreaTop + 202;
+
+const CoordType kJumpMenuHilitedLeft = kNavAreaLeft + 354;
+const CoordType kJumpMenuHilitedTop = kNavAreaTop + 196;
+
+const CoordType kExitLeft = kNavAreaLeft + 360;
+const CoordType kExitTop = kNavAreaTop + 216;
+
+const CoordType kExitHilitedLeft = kNavAreaLeft + 354;
+const CoordType kExitHilitedTop = kNavAreaTop + 210;
+
+const CoordType kRipTimerLeft = kNavAreaLeft + 95;
+const CoordType kRipTimerTop = kNavAreaTop + 87;
+
+const CoordType kTBPCloseLeft = kNavAreaLeft + 30;
+const CoordType kTBPCloseTop = kNavAreaTop + 16;
+
+const CoordType kTBPRewindLeft = kNavAreaLeft + 86;
+const CoordType kTBPRewindTop = kNavAreaTop + 218;
+
+const CoordType kComparisonCloseLeft = kNavAreaLeft + 50;
+const CoordType kComparisonCloseTop = kNavAreaTop + 14;
+
+const CoordType kComparisonLeftRewindLeft = kNavAreaLeft + 96;
+const CoordType kComparisonLeftRewindTop = kNavAreaTop + 190;
+
+const CoordType kComparisonRightRewindLeft = kNavAreaLeft + 282;
+const CoordType kComparisonRightRewindTop = kNavAreaTop + 190;
+
+const CoordType kComparisonHiliteSpriteLeft = kNavAreaLeft + 45;
+const CoordType kComparisonHiliteSpriteTop = kNavAreaTop + 65;
+
+const CoordType kComparisonHiliteNoradLeft = kNavAreaLeft + 45;
+const CoordType kComparisonHiliteNoradTop = kNavAreaTop + 65;
+
+const CoordType kComparisonHiliteMarsLeft = kNavAreaLeft + 45 + 4;
+const CoordType kComparisonHiliteMarsTop = kNavAreaTop + 65 + 23;
+
+const CoordType kComparisonHiliteCaldoriaLeft = kNavAreaLeft + 45 + 7;
+const CoordType kComparisonHiliteCaldoriaTop = kNavAreaTop + 65 + 46;
+
+const CoordType kComparisonHiliteWSCLeft = kNavAreaLeft + 45 + 11;
+const CoordType kComparisonHiliteWSCTop = kNavAreaTop + 65 + 68;
+
+const CoordType kComparisonChancesSpriteLeft = kNavAreaLeft + 148;
+const CoordType kComparisonChancesSpriteTop = kNavAreaTop + 162;
+
+const CoordType kComparisonChancesNoradLeft = kNavAreaLeft + 148;
+const CoordType kComparisonChancesNoradTop = kNavAreaTop + 162;
+
+const CoordType kComparisonChancesMarsLeft = kNavAreaLeft + 148;
+const CoordType kComparisonChancesMarsTop = kNavAreaTop + 162;
+
+const CoordType kComparisonChancesCaldoriaLeft = kNavAreaLeft + 148;
+const CoordType kComparisonChancesCaldoriaTop = kNavAreaTop + 162 + 1;
+
+const CoordType kComparisonChancesWSCLeft = kNavAreaLeft + 148;
+const CoordType kComparisonChancesWSCTop = kNavAreaTop + 162;
+
+const CoordType kRedirectionSprite1Left = kNavAreaLeft + 58;
+const CoordType kRedirectionSprite1Top = kNavAreaTop + 16;
+
+const CoordType kRedirectionSprite2Left = kNavAreaLeft + 36;
+const CoordType kRedirectionSprite2Top = kNavAreaTop + 166;
+
+const CoordType kRedirectionCCRolloverLeft = kNavAreaLeft + 58;
+const CoordType kRedirectionCCRolloverTop = kNavAreaTop + 16;
+
+const CoordType kRedirectionRRRolloverLeft = kNavAreaLeft + 430;
+const CoordType kRedirectionRRRolloverTop = kNavAreaTop + 30;
+
+const CoordType kRedirectionFDRolloverLeft = kNavAreaLeft + 278;
+const CoordType kRedirectionFDRolloverTop = kNavAreaTop + 160;
+
+const CoordType kRedirectionCCDoorLeft = kNavAreaLeft + 174;
+const CoordType kRedirectionCCDoorTop = kNavAreaTop + 36;
+
+const CoordType kRedirectionRRDoorLeft = kNavAreaLeft + 418;
+const CoordType kRedirectionRRDoorTop = kNavAreaTop + 32;
+
+const CoordType kRedirectionFDDoorLeft = kNavAreaLeft + 298;
+const CoordType kRedirectionFDDoorTop = kNavAreaTop + 240;
+
+const CoordType kRedirectionSecuredLeft = kNavAreaLeft + 36;
+const CoordType kRedirectionSecuredTop = kNavAreaTop + 166;
+
+const CoordType kRedirectionNewTargetLeft = kNavAreaLeft + 36;
+const CoordType kRedirectionNewTargetTop = kNavAreaTop + 166;
+
+const CoordType kRedirectionCloseLeft = kNavAreaLeft + 56;
+const CoordType kRedirectionCloseTop = kNavAreaTop + 220;
+
+static const TimeValue kTSABumpIntoWallIn = 0;
+static const TimeValue kTSABumpIntoWallOut = 148;
+
+static const TimeValue kTSAGTDoorCloseIn = 148;
+static const TimeValue kTSAGTDoorCloseOut = 1570;
+
+static const TimeValue kTSANoOtherDestinationIn = 1570;
+static const TimeValue kTSANoOtherDestinationOut = 3601;
+
+static const TimeValue kTSAEntryDoorCloseIn = 3601;
+static const TimeValue kTSAEntryDoorCloseOut = 4200;
+
+static const TimeValue kTSAInsideDoorCloseIn = 4200;
+static const TimeValue kTSAInsideDoorCloseOut = 4800;
+
+static const TimeValue kTSAVaultCloseIn = 4800;
+static const TimeValue kTSAVaultCloseOut = 5388;
+
+static const TimeValue kTSAPegasusDoorCloseIn = 5388;
+static const TimeValue kTSAPegasusDoorCloseOut = 6457;
+
+static const bool kPegasusUnresolved = false;
+static const bool kPegasusResolved = true;
+static const bool kPegasusCantExit = false;
+static const bool kPegasusCanExit = true;
+
+// Monitor modes
+enum {
+ kMonitorNeutral = 0,
+ kMonitorTheory = 1,
+ kMonitorProcedure = 2,
+ kMonitorBackground = 3,
+ kMonitorNoradComparison = 4,
+ kMonitorMarsComparison = 5,
+ kMonitorCaldoriaComparison = 6,
+ kMonitorWSCComparison = 7,
+
+ kRawModeMask = 0x0F,
+ kPlayingTBPMask = 0x10,
+ kPlayingLeftComparisonMask = 0x20,
+ kPlayingRightComparisonMask = 0x40,
+
+ kPlayingAnyMask = kPlayingTBPMask |
+ kPlayingLeftComparisonMask |
+ kPlayingRightComparisonMask,
+
+ kMonitorPlayingTheory = kMonitorTheory | kPlayingTBPMask,
+ kMonitorPlayingProcedure = kMonitorProcedure | kPlayingTBPMask,
+ kMonitorPlayingBackground = kMonitorBackground | kPlayingTBPMask,
+
+ kMonitorPlayingLeftNoradComparison = kMonitorNoradComparison |
+ kPlayingLeftComparisonMask,
+ kMonitorPlayingRightNoradComparison = kMonitorNoradComparison |
+ kPlayingRightComparisonMask,
+ kMonitorPlayingLeftMarsComparison = kMonitorMarsComparison |
+ kPlayingLeftComparisonMask,
+ kMonitorPlayingRightMarsComparison = kMonitorMarsComparison |
+ kPlayingRightComparisonMask,
+ kMonitorPlayingLeftCaldoriaComparison = kMonitorCaldoriaComparison |
+ kPlayingLeftComparisonMask,
+ kMonitorPlayingRightCaldoriaComparison = kMonitorCaldoriaComparison |
+ kPlayingRightComparisonMask,
+ kMonitorPlayingLeftWSCComparison = kMonitorWSCComparison |
+ kPlayingLeftComparisonMask,
+ kMonitorPlayingRightWSCComparison = kMonitorWSCComparison |
+ kPlayingRightComparisonMask
+};
+
+static const ExtraID s_historicalLogViews[16] = {
+ kTSA0BComparisonView0000,
+ kTSA0BComparisonView0002,
+ kTSA0BComparisonView0020,
+ kTSA0BComparisonView0022,
+ kTSA0BComparisonView0200,
+ kTSA0BComparisonView0202,
+ kTSA0BComparisonView0220,
+ kTSA0BComparisonView0222,
+ kTSA0BComparisonView2000,
+ kTSA0BComparisonView2002,
+ kTSA0BComparisonView2020,
+ kTSA0BComparisonView2022,
+ kTSA0BComparisonView2200,
+ kTSA0BComparisonView2202,
+ kTSA0BComparisonView2220,
+ kTSA0BComparisonView2222
+};
+
+static const int kRedirectionCCRolloverSprite = 0;
+static const int kRedirectionRRRolloverSprite = 1;
+static const int kRedirectionFDRolloverSprite = 2;
+static const int kRedirectionCCDoorSprite = 3;
+static const int kRedirectionRRDoorSprite = 4;
+static const int kRedirectionFDDoorSprite = 5;
+static const int kRedirectionCloseSprite = 6;
+static const int kRedirectionSecuredSprite = 0;
+static const int kRedirectionNewTargetSprite = 1;
+
+void RipTimer::initImage() {
+ _middle = -1;
+
+ _timerImage.getImageFromPICTResource(((PegasusEngine *)g_engine)->_resFork, kLeftRipPICTID);
+
+ Common::Rect r;
+ _timerImage.getSurfaceBounds(r);
+ setBounds(r);
+}
+
+void RipTimer::releaseImage() {
+ _timerImage.deallocateSurface();
+}
+
+void RipTimer::draw(const Common::Rect &updateRect) {
+ Common::Rect bounds;
+ getBounds(bounds);
+
+ Common::Rect r1 = bounds;
+ r1.right = _middle;
+ r1 = updateRect.findIntersectingRect(r1);
+
+ if (!r1.isEmpty()) {
+ Common::Rect r2 = r1;
+ r2.moveTo(r1.left - _bounds.left, r1.top - bounds.top);
+ _timerImage.copyToCurrentPort(r2, r1);
+ }
+}
+
+void RipTimer::timeChanged(const TimeValue newTime) {
+ Common::Rect bounds;
+ getBounds(bounds);
+
+ CoordType newMiddle = bounds.left + bounds.width() * newTime / getDuration();
+
+ if (newMiddle != _middle) {
+ _middle = newMiddle;
+ triggerRedraw();
+ }
+
+ if (newTime == getStop())
+ ((PegasusEngine *)g_engine)->die(kDeathUncreatedInTSA);
+}
+
+FullTSA::FullTSA(InputHandler *nextHandler, PegasusEngine *owner) : Neighborhood(nextHandler, owner, "Full TSA", kFullTSAID),
+ _ripTimer(kNoDisplayElement), _sprite1(kNoDisplayElement), _sprite2(kNoDisplayElement), _sprite3(kNoDisplayElement) {
+ setIsItemTaken(kJourneymanKey);
+ setIsItemTaken(kPegasusBiochip);
+ setIsItemTaken(kMapBiochip);
+}
+
+void FullTSA::init() {
+ Neighborhood::init();
+ _ripTimer.setDisplayOrder(kRipTimerOrder);
+ _ripTimer.startDisplaying();
+
+ if (!GameState.getTSASeenRobotGreeting())
+ forceStridingStop(kTSA03, kNorth, kNoAlternateID);
+
+ _sprite1.setDisplayOrder(kMonitorLayer);
+ _sprite1.startDisplaying();
+ _sprite2.setDisplayOrder(kMonitorLayer);
+ _sprite2.startDisplaying();
+ _sprite3.setDisplayOrder(kMonitorLayer);
+ _sprite3.startDisplaying();
+
+ // Fix a mistake in the world builder tables.
+ HotspotInfoTable::Entry *entry = findHotspotEntry(kTSA23WestChipsSpotID);
+ entry->hotspotItem = kPegasusBiochip;
+}
+
+void FullTSA::dieUncreatedInTSA() {
+ die(kDeathUncreatedInTSA);
+}
+
+void FullTSA::start() {
+ g_energyMonitor->stopEnergyDraining();
+
+ if (!GameState.getScoringEnterTSA()) {
+ _utilityFuse.primeFuse(GameState.getTSAFuseTimeLimit());
+ _utilityFuse.setFunctor(new Common::Functor0Mem<void, FullTSA>(this, &FullTSA::dieUncreatedInTSA));
+ _utilityFuse.lightFuse();
+ } else if (GameState.getTSAState() == kTSAPlayerDetectedRip || GameState.getTSAState() == kTSAPlayerNeedsHistoricalLog) {
+ _ripTimer.initImage();
+ _ripTimer.moveElementTo(kRipTimerLeft, kRipTimerTop);
+ _ripTimer.setSegment(0, kRipTimeLimit, kRipTimeScale);
+ _ripTimer.setTime(GameState.getRipTimerTime());
+ _ripTimer.start();
+ }
+
+ Neighborhood::start();
+}
+
+void FullTSA::flushGameState() {
+ GameState.setRipTimerTime(_ripTimer.getTime());
+ GameState.setTSAFuseTimeLimit(_utilityFuse.getTimeRemaining());
+}
+
+Common::String FullTSA::getBriefingMovie() {
+ Common::String movieName = Neighborhood::getBriefingMovie();
+
+ if (movieName.empty()) {
+ RoomID room = GameState.getCurrentRoom();
+
+ switch (GameState.getTSAState()) {
+ case kTSAPlayerNotArrived:
+ case kTSAPlayerForcedReview:
+ if (room >= kTSA16 && room <= kTSA0B)
+ return "Images/AI/TSA/XT01A";
+
+ return "Images/AI/TSA/XT01";
+ case kTSAPlayerDetectedRip:
+ case kTSAPlayerNeedsHistoricalLog:
+ return "Images/AI/TSA/XT02";
+ case kTSAPlayerGotHistoricalLog:
+ case kTSAPlayerInstalledHistoricalLog:
+ return "Images/AI/TSA/XT03";
+ default:
+ switch (getCurrentActivation()) {
+ case kActivationJumpToPrehistoric:
+ g_AIChip->showBriefingClicked();
+ startExtraSequenceSync(kTSA37PegasusAI2, kHintInterruption);
+ startExtraSequenceSync(kTSA37AI2ToPrehistoric, kFilterNoInput);
+ g_AIChip->clearClicked();
+ break;
+ case kActivationJumpToNorad:
+ g_AIChip->showBriefingClicked();
+ startExtraSequenceSync(kTSA37PegasusAI7, kHintInterruption);
+ startExtraSequenceSync(kTSA37AI7ToNorad, kFilterNoInput);
+ g_AIChip->clearClicked();
+ break;
+ case kActivationJumpToMars:
+ g_AIChip->showBriefingClicked();
+ startExtraSequenceSync(kTSA37PegasusAI6, kHintInterruption);
+ startExtraSequenceSync(kTSA37AI6ToMars, kFilterNoInput);
+ g_AIChip->clearClicked();
+ break;
+ case kActivationJumpToWSC:
+ g_AIChip->showBriefingClicked();
+ startExtraSequenceSync(kTSA37PegasusAI5, kHintInterruption);
+ startExtraSequenceSync(kTSA37AI5ToWSC, kFilterNoInput);
+ g_AIChip->clearClicked();
+ break;
+ default:
+ if (GameState.allTimeZonesFinished())
+ return "Images/AI/TSA/XT05";
+
+ return "Images/AI/TSA/XT04";
+ }
+ break;
+ }
+ }
+
+ return movieName;
+}
+
+Common::String FullTSA::getEnvScanMovie() {
+ Common::String movieName = Neighborhood::getEnvScanMovie();
+
+ if (movieName.empty()) {
+ switch (GameState.getTSAState()) {
+ case kTSAPlayerNotArrived:
+ case kTSAPlayerForcedReview:
+ case kTSAPlayerDetectedRip:
+ case kTSAPlayerNeedsHistoricalLog:
+ return "Images/AI/TSA/XTE1";
+ default:
+ if (GameState.getCurrentRoom() == kTSA37) {
+ g_AIChip->showEnvScanClicked();
+ startExtraSequenceSync(kTSA37EnvironmentalScan, kHintInterruption);
+
+ switch (getCurrentActivation()) {
+ case kActivationJumpToPrehistoric:
+ startExtraSequenceSync(kTSA37AI2ToPrehistoric, kFilterNoInput);
+ break;
+ case kActivationJumpToNorad:
+ startExtraSequenceSync(kTSA37AI7ToNorad, kFilterNoInput);
+ showExtraView(kTSA37JumpToNoradMenu);
+ break;
+ case kActivationJumpToMars:
+ startExtraSequenceSync(kTSA37AI6ToMars, kFilterNoInput);
+ showExtraView(kTSA37JumpToMarsMenu);
+ break;
+ case kActivationJumpToWSC:
+ startExtraSequenceSync(kTSA37AI5ToWSC, kFilterNoInput);
+ showExtraView(kTSA37JumpToWSCMenu);
+ break;
+ default:
+ startExtraSequenceSync(kTSA37AI4ToMainMenu, kFilterNoInput);
+ break;
+ }
+
+ g_AIChip->clearClicked();
+ } else if (GameState.allTimeZonesFinished()) {
+ return "Images/AI/TSA/XTE1";
+ } else {
+ return "Images/AI/TSA/XTE2";
+ }
+ break;
+ }
+ }
+
+ return movieName;
+}
+
+uint FullTSA::getNumHints() {
+ uint numHints = Neighborhood::getNumHints();
+
+ if (numHints == 0) {
+ switch (GameState.getTSAState()) {
+ case kRobotsAtCommandCenter:
+ case kRobotsAtFrontDoor:
+ case kRobotsAtReadyRoom:
+ if (GameState.getCurrentRoom() == kTSA0B && GameState.getTSA0BZoomedIn())
+ numHints = 3;
+ break;
+ }
+ }
+
+ return numHints;
+}
+
+Common::String FullTSA::getHintMovie(uint hintNum) {
+ Common::String movieName = Neighborhood::getHintMovie(hintNum);
+
+ if (movieName.empty())
+ movieName = Common::String::format("Images/AI/TSA/XT20NH%d", hintNum);
+
+ return movieName;
+}
+
+void FullTSA::loadAmbientLoops() {
+ RoomID room = GameState.getCurrentRoom();
+
+ switch (GameState.getTSAState()) {
+ case kTSAPlayerDetectedRip:
+ case kTSAPlayerNeedsHistoricalLog:
+ if ((room >= kTSA16 && room <= kTSA0B) || (room >= kTSA21Cyan && room <= kTSA24Cyan) || (room >= kTSA21Red && room <= kTSA24Red))
+ loadLoopSound1("Sounds/TSA/TSA CLAXON.22K.AIFF", 0x100 / 4, 0, 0);
+ else if (room == kTSA25Cyan || room == kTSA25Red)
+ loadLoopSound1("Sounds/TSA/TSA CLAXON.22K.AIFF", 0x100 / 6, 0, 0);
+ else
+ loadLoopSound1("Sounds/TSA/TSA EchoClaxon.22K.AIFF", 0x100 / 4, 0, 0);
+ break;
+ default:
+ if (room >= kTSA00 && room <= kTSA02)
+ loadLoopSound1("Sounds/TSA/T01NAE.NEW.22K.AIFF");
+ else if (room >= kTSA03 && room <= kTSA15)
+ loadLoopSound1("Sounds/TSA/T01NAE.NEW.22K.AIFF");
+ else if (room >= kTSA16 && room <= kTSA0B)
+ loadLoopSound1("Sounds/TSA/T14SAEO1.22K.AIFF");
+ else if (room >= kTSA21Cyan && room <= kTSA25Red)
+ loadLoopSound1("Sounds/TSA/T15SAE01.22K.AIFF");
+ else if (room >= kTSA26 && room <= kTSA37)
+ loadLoopSound1("Sounds/TSA/T01NAE.NEW.22K.AIFF");
+ break;
+ }
+}
+
+short FullTSA::getStaticCompassAngle(const RoomID room, const DirectionConstant dir) {
+ int16 result = Neighborhood::getStaticCompassAngle(room, dir);
+
+ switch (room) {
+ case kTSA08:
+ result += kCompassShift;
+ break;
+ case kTSA09:
+ result -= kCompassShift;
+ break;
+ case kTSA10:
+ result += kCompassShift * 2;
+ break;
+ case kTSA11:
+ case kTSA22Cyan:
+ case kTSA22Red:
+ result -= kCompassShift * 2;
+ break;
+ case kTSA12:
+ result += kCompassShift * 3;
+ break;
+ case kTSA13:
+ result -= kCompassShift * 3;
+ break;
+ case kTSA14:
+ case kTSA16:
+ case kTSA17:
+ case kTSA18:
+ case kTSA19:
+ result += kCompassShift * 4;
+ break;
+ case kTSA0B:
+ result += kCompassShift * 4;
+
+ if (dir == kWest)
+ result += 30;
+ else if (dir == kEast)
+ result -= 30;
+ break;
+ case kTSA33:
+ result += kCompassShift * 4;
+ break;
+ case kTSA15:
+ case kTSA21Cyan:
+ case kTSA24Cyan:
+ case kTSA25Cyan:
+ case kTSA21Red:
+ case kTSA24Red:
+ case kTSA25Red:
+ case kTSA26:
+ case kTSA27:
+ case kTSA28:
+ case kTSA29:
+ case kTSA30:
+ result -= kCompassShift * 4;
+ break;
+ case kTSA23Cyan:
+ case kTSA23Red:
+ result -= kCompassShift * 6;
+ break;
+ case kTSA32:
+ result -= kCompassShift * 8;
+ break;
+ case kTSA34:
+ result -= kCompassShift * 12;
+ break;
+ case kTSA35:
+ result += kCompassShift * 8;
+ break;
+ case kTSA37:
+ result -= kCompassShift * 2;
+ break;
+ }
+
+ return result;
+}
+
+void FullTSA::getExitCompassMove(const ExitTable::Entry &exitEntry, FaderMoveSpec &compassMove) {
+ Neighborhood::getExitCompassMove(exitEntry, compassMove);
+
+ switch (MakeRoomView(exitEntry.room, exitEntry.direction)) {
+ case MakeRoomView(kTSA01, kSouth):
+ compassMove.insertFaderKnot(exitEntry.movieStart, -180);
+ compassMove.insertFaderKnot(exitEntry.movieStart + kFullTSAFrameDuration * 3, -180);
+ compassMove.insertFaderKnot(exitEntry.movieStart + kFullTSAFrameDuration * 33,
+ getStaticCompassAngle(exitEntry.exitRoom, exitEntry.exitDirection));
+ break;
+ case MakeRoomView(kTSA11, kEast):
+ if (getCurrentAlternate() == kAltTSARobotsAtReadyRoom) {
+ compassMove.makeTwoKnotFaderSpec(kFullTSAMovieScale, exitEntry.movieStart,
+ getStaticCompassAngle(kTSA11, kEast), exitEntry.movieEnd,
+ getStaticCompassAngle(kTSA13, kEast));
+ compassMove.insertFaderKnot(exitEntry.movieStart + kFullTSAFrameDuration * 13, compassMove.getNthKnotValue(1));
+ }
+ break;
+ case MakeRoomView(kTSA34, kNorth):
+ compassMove.insertFaderKnot(exitEntry.movieStart + kFullTSAFrameDuration * 48,
+ getStaticCompassAngle(exitEntry.room, exitEntry.direction));
+ compassMove.insertFaderKnot(exitEntry.movieStart + kFullTSAFrameDuration * 68,
+ getStaticCompassAngle(exitEntry.exitRoom, exitEntry.exitDirection));
+ break;
+ case MakeRoomView(kTSA37, kNorth):
+ compassMove.insertFaderKnot(exitEntry.movieStart + kFullTSAFrameDuration * 38,
+ getStaticCompassAngle(exitEntry.room, exitEntry.direction));
+ compassMove.insertFaderKnot(exitEntry.movieStart + kFullTSAFrameDuration * 64,
+ getStaticCompassAngle(exitEntry.room, exitEntry.direction) + kCompassShift * 3 / 2);
+ compassMove.insertFaderKnot(exitEntry.movieStart + kFullTSAFrameDuration * 105,
+ getStaticCompassAngle(exitEntry.exitRoom, exitEntry.exitDirection));
+ break;
+ }
+}
+
+void FullTSA::getExtraCompassMove(const ExtraTable::Entry &extraEntry, FaderMoveSpec &compassMove) {
+ int16 angle;
+
+ switch (extraEntry.extra) {
+ case kTSA0BEastTurnLeft:
+ case kTSA0BNorthTurnLeft:
+ angle =getStaticCompassAngle(GameState.getCurrentRoom(), GameState.getCurrentDirection());
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), extraEntry.movieStart, angle,
+ extraEntry.movieEnd, angle - 60);
+ break;
+ case kTSA0BNorthTurnRight:
+ case kTSA0BWestTurnRight:
+ angle = getStaticCompassAngle(GameState.getCurrentRoom(), GameState.getCurrentDirection());
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), extraEntry.movieStart, angle,
+ extraEntry.movieEnd, angle + 60);
+ break;
+ case kTSA22RedEastZoomInSequence:
+ angle = getStaticCompassAngle(GameState.getCurrentRoom(), GameState.getCurrentDirection());
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), extraEntry.movieStart, angle,
+ extraEntry.movieEnd, angle);
+ compassMove.insertFaderKnot(extraEntry.movieStart + 1200, angle - kCompassShift * 2);
+ compassMove.insertFaderKnot(extraEntry.movieStart + 8160, angle - kCompassShift * 2);
+ compassMove.insertFaderKnot(extraEntry.movieStart + 9840, angle);
+ break;
+ case kTSA23RedWestVaultZoomInSequence:
+ angle = getStaticCompassAngle(GameState.getCurrentRoom(), GameState.getCurrentDirection());
+ compassMove.makeTwoKnotFaderSpec(_navMovie.getScale(), extraEntry.movieStart, angle,
+ extraEntry.movieEnd, angle);
+ compassMove.insertFaderKnot(extraEntry.movieStart + 1200, angle - kCompassShift * 2);
+ compassMove.insertFaderKnot(extraEntry.movieStart + 10100, angle - kCompassShift * 2);
+ compassMove.insertFaderKnot(extraEntry.movieStart + 11880, angle);
+ break;
+ default:
+ Neighborhood::getExtraCompassMove(extraEntry, compassMove);
+ break;
+ }
+}
+
+uint16 FullTSA::getDateResID() const {
+ return kDate2318ID;
+}
+
+TimeValue FullTSA::getViewTime(const RoomID room, const DirectionConstant direction) {
+ ExtraID extraID = 0xffffffff;
+
+ switch (MakeRoomView(room, direction)) {
+ case MakeRoomView(kTSA0B, kEast):
+ if (GameState.getTSA0BZoomedIn())
+ switch (GameState.getTSAState()) {
+ case kTSAPlayerInstalledHistoricalLog:
+ case kTSABossSawHistoricalLog:
+ case kRobotsAtCommandCenter:
+ case kRobotsAtFrontDoor:
+ case kRobotsAtReadyRoom:
+ extraID = s_historicalLogViews[getHistoricalLogIndex()];
+ break;
+ default:
+ extraID = kTSA0BEastZoomedView;
+ break;
+ }
+ break;
+ case MakeRoomView(kTSA0B, kNorth):
+ if (GameState.getTSA0BZoomedIn())
+ switch (GameState.getTSAState()) {
+ case kTSAPlayerNeedsHistoricalLog:
+ extraID = kTSA0BNorthRipView1;
+ break;
+ default:
+ extraID = kTSA0BNorthZoomedView;
+ break;
+ }
+ break;
+ case MakeRoomView(kTSA0B, kWest):
+ if (GameState.getTSA0BZoomedIn())
+ extraID = kTSA0BWestZoomedView;
+ break;
+ case MakeRoomView(kTSA22Red, kEast):
+ if (_privateFlags.getFlag(kTSAPrivateKeyVaultOpenFlag)) {
+ if (_vm->itemInLocation(kJourneymanKey, kFullTSAID, kTSA22Red, kEast))
+ extraID = kTSA22RedEastVaultViewWithKey;
+ else
+ extraID = kTSA22RedEastVaultViewNoKey;
+ }
+ break;
+ case MakeRoomView(kTSA23Red, kWest):
+ if (_privateFlags.getFlag(kTSAPrivateChipVaultOpenFlag)) {
+ if (_vm->itemInLocation(kPegasusBiochip, kFullTSAID, kTSA23Red, kWest))
+ extraID = kTSA23RedWestVaultViewWithChips;
+ else
+ extraID = kTSA23RedWestVaultViewNoChips;
+ }
+ break;
+ case MakeRoomView(kTSA37, kNorth):
+ switch (GameState.getTSAState()) {
+ case kTSAPlayerGotHistoricalLog:
+ extraID = kTSA37ReviewRequiredToExit;
+ break;
+ case kPlayerFinishedWithTSA:
+ extraID = kTSA37CongratulationsToExit;
+ break;
+ default:
+ extraID = kTSA37AI3ToHorse;
+ break;
+ }
+ break;
+ }
+
+ if (extraID != 0xffffffff) {
+ ExtraTable::Entry entry;
+ getExtraEntry(extraID, entry);
+ return entry.movieEnd - 1;
+ }
+
+ return Neighborhood::getViewTime(room, direction);
+}
+
+void FullTSA::findSpotEntry(const RoomID room, const DirectionConstant direction, SpotFlags flags, SpotTable::Entry &entry) {
+ switch (MakeRoomView(room, direction)) {
+ case MakeRoomView(kTSA0B, kNorth):
+ case MakeRoomView(kTSA0B, kEast):
+ case MakeRoomView(kTSA0B, kWest):
+ if (!GameState.getTSA0BZoomedIn())
+ Neighborhood::findSpotEntry(room, direction, flags, entry);
+ break;
+ default:
+ Neighborhood::findSpotEntry(room, direction, flags, entry);
+ break;
+ }
+}
+
+void FullTSA::getExtraEntry(const uint32 id, ExtraTable::Entry &extraEntry) {
+ Neighborhood::getExtraEntry(id, extraEntry);
+
+ if (id == kTSA0BShowGuardRobots)
+ extraEntry.movieStart += kFullTSAFrameDuration * 3;
+}
+
+void FullTSA::pickedUpItem(Item *item) {
+ BiochipItem *biochip;
+
+ switch (item->getObjectID()) {
+ case kJourneymanKey:
+ GameState.setScoringGotJourneymanKey(true);
+ break;
+ case kPegasusBiochip:
+ biochip = (BiochipItem *)_vm->getAllItems().findItemByID(kMapBiochip);
+ _vm->addItemToBiochips(biochip);
+ GameState.setScoringGotPegasusBiochip(true);
+ break;
+ }
+}
+
+void FullTSA::playExtraMovie(const ExtraTable::Entry &extraEntry, const NotificationFlags flags, const InputBits interruptionInput) {
+ switch (extraEntry.extra) {
+ case kTSA0BNorthZoomIn:
+ if (_privateFlags.getFlag(kTSAPrivateLogReaderOpenFlag)) {
+ _privateFlags.setFlag(kTSAPrivateLogReaderOpenFlag, false);
+ requestExtraSequence(kTSA0BNorthHistLogClose, 0, kFilterNoInput);
+ requestExtraSequence(kTSA0BNorthZoomIn, kExtraCompletedFlag, kFilterNoInput);
+ } else {
+ Neighborhood::playExtraMovie(extraEntry, flags, interruptionInput);
+ }
+ break;
+ case kTSA0BNorthZoomOut:
+ if (_ripTimer.isVisible())
+ _ripTimer.hide();
+
+ shutDownRobotMonitor();
+ Neighborhood::playExtraMovie(extraEntry, flags, interruptionInput);
+ break;
+ case kTSA0BEastZoomOut:
+ shutDownComparisonMonitor();
+ Neighborhood::playExtraMovie(extraEntry, flags, interruptionInput);
+ break;
+ default:
+ Neighborhood::playExtraMovie(extraEntry, flags, interruptionInput);
+ break;
+ }
+}
+
+void FullTSA::startDoorOpenMovie(const TimeValue startTime, const TimeValue stopTime) {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kTSA00, kNorth):
+ if (GameState.getLastNeighborhood() != kFullTSAID) {
+ startExtraSequence(kTSAArriveFromCaldoria, kDoorOpenCompletedFlag, kFilterNoInput);
+ return;
+ }
+ break;
+ case MakeRoomView(kTSA02, kNorth):
+ if (!GameState.getTSAIDedAtDoor()) {
+ GameState.setTSAIDedAtDoor(true);
+ requestExtraSequence(kTSA02NorthZoomIn, 0, kFilterNoInput);
+ requestExtraSequence(kTSA02NorthTenSecondDoor, 0, kFilterNoInput);
+
+ if (GameState.getTSASeenAgent3AtDoor()) {
+ requestExtraSequence(kTSA02NorthZoomOut, kExtraCompletedFlag, kFilterNoInput);
+ } else {
+ GameState.setTSASeenAgent3AtDoor(true);
+ requestExtraSequence(kTSA02NorthZoomOut, 0, kFilterNoInput);
+ requestExtraSequence(kTSA02NorthDoorWithAgent3, kDoorOpenCompletedFlag, kFilterNoInput);
+ }
+ return;
+ }
+ break;
+ case MakeRoomView(kTSA03, kSouth):
+ if (GameState.getTSAState() == kRobotsAtFrontDoor) {
+ playDeathExtra(kTSA03SouthRobotDeath, kDeathShotByTSARobots);
+ return;
+ }
+ break;
+ case MakeRoomView(kTSA16, kNorth):
+ if (GameState.getTSAState() == kRobotsAtCommandCenter) {
+ playDeathExtra(kTSA16NorthRobotDeath, kDeathShotByTSARobots);
+ return;
+ }
+ break;
+ }
+
+ Neighborhood::startDoorOpenMovie(startTime, stopTime);
+}
+
+InputBits FullTSA::getInputFilter() {
+ InputBits result = Neighborhood::getInputFilter();
+
+ switch (GameState.getCurrentRoom()) {
+ case kTSA0B:
+ if (GameState.getT0BMonitorMode() != kMonitorNeutral)
+ // Only allow a click.
+ result &= JMPPPInput::getClickInputFilter();
+ break;
+ case kTSA37:
+ // Can't move forward in Pegasus. Only press the exit button.
+ result &= ~(kFilterUpButton | kFilterUpAuto);
+ break;
+ }
+
+ return result;
+}
+
+void FullTSA::turnLeft() {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kTSA15, kNorth):
+ if (GameState.getTSAState() == kTSAPlayerNeedsHistoricalLog)
+ setCurrentAlternate(kAltTSANormal);
+ break;
+ case MakeRoomView(kTSA0B, kNorth):
+ if (_ripTimer.isVisible())
+ _ripTimer.hide();
+ releaseSprites();
+ break;
+ case MakeRoomView(kTSA0B, kEast):
+ shutDownComparisonMonitor();
+ break;
+ }
+
+ Neighborhood::turnLeft();
+}
+
+void FullTSA::turnRight() {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kTSA15, kSouth):
+ if (GameState.getTSAState() == kTSAPlayerNeedsHistoricalLog)
+ setCurrentAlternate(kAltTSANormal);
+ break;
+ case MakeRoomView(kTSA0B, kNorth):
+ if (_ripTimer.isVisible())
+ _ripTimer.hide();
+ releaseSprites();
+ break;
+ case MakeRoomView(kTSA0B, kEast):
+ shutDownComparisonMonitor();
+ break;
+ }
+
+ Neighborhood::turnRight();
+}
+
+void FullTSA::openDoor() {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kTSA15, kSouth):
+ if (GameState.getTSAState() == kTSAPlayerNeedsHistoricalLog || GameState.getTSAState() == kRobotsAtFrontDoor)
+ setCurrentAlternate(kAltTSARedAlert);
+ break;
+ }
+
+ Neighborhood::openDoor();
+}
+
+CanMoveForwardReason FullTSA::canMoveForward(ExitTable::Entry &entry) {
+ if (GameState.getCurrentRoomAndView() == MakeRoomView(kTSA25Red, kNorth))
+ return kCantMoveBlocked;
+
+ return Neighborhood::canMoveForward(entry);
+}
+
+CanOpenDoorReason FullTSA::canOpenDoor(DoorTable::Entry &entry) {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kTSA02, kNorth):
+ if (!GameState.getTSAFrontDoorUnlockedOutside())
+ return kCantOpenLocked;
+ break;
+ case MakeRoomView(kTSA03, kSouth):
+ if (!GameState.getTSAFrontDoorUnlockedInside())
+ return kCantOpenLocked;
+ break;
+ case MakeRoomView(kTSA16, kNorth):
+ if (GameState.getTSACommandCenterLocked())
+ return kCantOpenLocked;
+ break;
+ }
+
+ return Neighborhood::canOpenDoor(entry);
+}
+
+void FullTSA::bumpIntoWall() {
+ requestSpotSound(kTSABumpIntoWallIn, kTSABumpIntoWallOut, kFilterAllInput, 0);
+ Neighborhood::bumpIntoWall();
+}
+
+void FullTSA::downButton(const Input &input) {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kTSA0B, kEast):
+ if (GameState.getTSA0BZoomedIn())
+ startExtraSequence(kTSA0BEastZoomOut, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case MakeRoomView(kTSA0B, kNorth):
+ if (GameState.getTSA0BZoomedIn())
+ startExtraSequence(kTSA0BNorthZoomOut, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case MakeRoomView(kTSA0B, kWest):
+ if (GameState.getTSA0BZoomedIn() && GameState.getT0BMonitorMode() == kMonitorNeutral)
+ startExtraSequence(kTSA0BWestZoomOut, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ default:
+ Neighborhood::downButton(input);
+ }
+}
+
+void FullTSA::activateOneHotspot(HotspotInfoTable::Entry &entry, Hotspot *spot) {
+ switch (spot->getObjectID()) {
+ case kTSA0BEastLeftRewindSpotID:
+ case kTSA0BEastLeftPlaySpotID:
+ if (_privateFlags.getFlag(kTSAPrivatePlayingRightComparisonFlag))
+ spot->setInactive();
+ else
+ Neighborhood::activateOneHotspot(entry, spot);
+ break;
+ case kTSA0BEastRightRewindSpotID:
+ case kTSA0BEastRightPlaySpotID:
+ if (_privateFlags.getFlag(kTSAPrivatePlayingLeftComparisonFlag))
+ spot->setInactive();
+ else
+ Neighborhood::activateOneHotspot(entry, spot);
+ break;
+ default:
+ Neighborhood::activateOneHotspot(entry, spot);
+ break;
+ }
+}
+
+void FullTSA::activateHotspots() {
+ Neighborhood::activateHotspots();
+
+ switch (MakeRoomView(GameState.getCurrentRoom(), GameState.getCurrentDirection())) {
+ case MakeRoomView(kTSA02, kNorth):
+ if (!GameState.getTSAFrontDoorUnlockedOutside())
+ _vm->getAllHotspots().activateOneHotspot(kTSA02DoorSpotID);
+ break;
+ case MakeRoomView(kTSA0B, kEast):
+ if (GameState.getTSA0BZoomedIn())
+ switch (GameState.getTSAState()) {
+ case kTSAPlayerInstalledHistoricalLog:
+ case kTSABossSawHistoricalLog:
+ case kRobotsAtCommandCenter:
+ case kRobotsAtFrontDoor:
+ case kRobotsAtReadyRoom:
+ if (getCurrentActivation() != kActivateTSA0BComparisonVideo) {
+ _vm->getAllHotspots().activateOneHotspot(kTSA0BEastCompareNoradSpotID);
+ _vm->getAllHotspots().activateOneHotspot(kTSA0BEastCompareMarsSpotID);
+ _vm->getAllHotspots().activateOneHotspot(kTSA0BEastCompareCaldoriaSpotID);
+ _vm->getAllHotspots().activateOneHotspot(kTSA0BEastCompareWSCSpotID);
+ }
+ break;
+ }
+ break;
+ case MakeRoomView(kTSA0B, kNorth):
+ if (GameState.getTSA0BZoomedIn())
+ switch (GameState.getTSAState()) {
+ case kRobotsAtCommandCenter:
+ case kRobotsAtFrontDoor:
+ case kRobotsAtReadyRoom:
+ _vm->getAllHotspots().activateOneHotspot(kTSA0BNorthRobotsToCommandCenterSpotID);
+ _vm->getAllHotspots().activateOneHotspot(kTSA0BNorthRobotsToReadyRoomSpotID);
+ _vm->getAllHotspots().activateOneHotspot(kTSA0BNorthRobotsToFrontDoorSpotID);
+ break;
+ }
+ break;
+ }
+}
+
+void FullTSA::clickInHotspot(const Input &input, const Hotspot *clickedSpot) {
+ switch (clickedSpot->getObjectID()) {
+ case kTSAGTOtherSpotID:
+ showExtraView(kTSAGTOtherChoice);
+ playSpotSoundSync(kTSANoOtherDestinationIn, kTSANoOtherDestinationOut);
+ showExtraView(kTSAGTCardSwipe);
+ break;
+ case kTSA02DoorSpotID:
+ GameState.setTSAFrontDoorUnlockedOutside(true);
+ Neighborhood::clickInHotspot(input, clickedSpot);
+ break;
+ case kTSA03EastJimenezSpotID:
+ startExtraLongSequence(kTSA03JimenezZoomIn, kTSA03JimenezZoomOut, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kTSA03WestCrenshawSpotID:
+ startExtraLongSequence(kTSA03CrenshawZoomIn, kTSA03CrenshawZoomOut, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kTSA04EastMatsumotoSpotID:
+ startExtraLongSequence(kTSA04MatsumotoZoomIn, kTSA04MatsumotoZoomOut, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kTSA04WestCastilleSpotID:
+ startExtraLongSequence(kTSA04CastilleZoomIn, kTSA04CastilleZoomOut, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kTSA05EastSinclairSpotID:
+ startExtraLongSequence(kTSA05SinclairZoomIn, kTSA05SinclairZoomOut, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kTSA05WestWhiteSpotID:
+ startExtraLongSequence(kTSA05WhiteZoomIn, kTSA05WhiteZoomOut, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kTSA0BEastCompareNoradSpotID:
+ initializeComparisonMonitor(kMonitorNoradComparison, kTSA0BNoradComparisonView);
+ break;
+ case kTSA0BEastCompareMarsSpotID:
+ initializeComparisonMonitor(kMonitorMarsComparison, kTSA0BMarsComparisonView);
+ break;
+ case kTSA0BEastCompareCaldoriaSpotID:
+ initializeComparisonMonitor(kMonitorCaldoriaComparison, kTSA0BCaldoriaComparisonView);
+ break;
+ case kTSA0BEastCompareWSCSpotID:
+ initializeComparisonMonitor(kMonitorWSCComparison, kTSA0BWSCComparisonView);
+ break;
+ case kTSA0BEastCloseVideoSpotID:
+ _navMovie.stop();
+ _sprite3.show();
+ _vm->delayShell(1, 2);
+ _sprite3.hide();
+ initializeComparisonMonitor(kMonitorNeutral, 0);
+ break;
+ case kTSA0BEastLeftPlaySpotID:
+ playLeftComparison();
+ break;
+ case kTSA0BEastRightPlaySpotID:
+ playRightComparison();
+ break;
+
+ // Command center
+ case kTSA0BWestTheorySpotID:
+ initializeTBPMonitor(kMonitorTheory, kTSA0BTBPTheoryHighlight);
+ break;
+ case kTSA0BWestBackgroundSpotID:
+ initializeTBPMonitor(kMonitorBackground, kTSA0BTBPBackgroundHighlight);
+ break;
+ case kTSA0BWestProcedureSpotID:
+ initializeTBPMonitor(kMonitorProcedure, kTSA0BTBPProcedureHighlight);
+ break;
+ case kTSA0BWestCloseVideoSpotID:
+ _navMovie.stop();
+ _sprite2.show();
+ _vm->delayShell(1, 2);
+ _sprite2.hide();
+ initializeTBPMonitor(kMonitorNeutral, 0);
+ break;
+ case kTSA0BWestPlayVideoSpotID:
+ playTBPMonitor();
+ break;
+ case kTSA0BEastLeftRewindSpotID:
+ case kTSA0BEastRightRewindSpotID:
+ case kTSA0BWestRewindVideoSpotID:
+ if ((GameState.getT0BMonitorMode() & kPlayingAnyMask) != 0) {
+ bool playing = _navMovie.isRunning();
+ if (playing)
+ _navMovie.stop();
+
+ if (clickedSpot->getObjectID() == kTSA0BEastRightRewindSpotID)
+ _sprite2.show();
+ else
+ _sprite1.show();
+
+ _vm->delayShell(1, 2);
+
+ if (clickedSpot->getObjectID() == kTSA0BEastRightRewindSpotID)
+ _sprite2.hide();
+ else
+ _sprite1.hide();
+
+ _navMovie.setTime(GameState.getT0BMonitorStart());
+
+ if (playing) {
+ _navMovie.start();
+ } else {
+ _privateFlags.setFlag(kTSAPrivatePlayingLeftComparisonFlag, false);
+ _privateFlags.setFlag(kTSAPrivatePlayingRightComparisonFlag, false);
+ }
+ }
+ break;
+ case kTSA22EastMonitorSpotID:
+ requestExtraSequence(kTSA22RedEastZoomInSequence, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kTSA23WestMonitorSpotID:
+ requestExtraSequence(kTSA23RedWestVaultZoomInSequence, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kTSA0BNorthRobotsToCommandCenterSpotID:
+ _sprite1.setCurrentFrameIndex(kRedirectionCCDoorSprite);
+ _sprite1.show();
+ _vm->delayShell(1, 2);
+ _sprite1.hide();
+
+ switch (GameState.getTSAState()) {
+ case kRobotsAtCommandCenter:
+ // Nothing
+ break;
+ case kRobotsAtFrontDoor:
+ GameState.setTSAState(kRobotsAtCommandCenter);
+ _sprite2.setCurrentFrameIndex(kRedirectionNewTargetSprite);
+ startExtraSequence(kTSA0BRobotsFromFrontDoorToCommandCenter, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kRobotsAtReadyRoom:
+ GameState.setTSAState(kRobotsAtCommandCenter);
+ _sprite2.setCurrentFrameIndex(kRedirectionNewTargetSprite);
+ startExtraSequence(kTSA0BRobotsFromReadyRoomToCommandCenter, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ }
+ break;
+ case kTSA0BNorthRobotsToReadyRoomSpotID:
+ _sprite1.setCurrentFrameIndex(kRedirectionRRDoorSprite);
+ _sprite1.show();
+ _vm->delayShell(1, 2);
+ _sprite1.hide();
+
+ switch (GameState.getTSAState()) {
+ case kRobotsAtCommandCenter:
+ GameState.setTSAState(kRobotsAtReadyRoom);
+ _sprite2.setCurrentFrameIndex(kRedirectionNewTargetSprite);
+ startExtraSequence(kTSA0BRobotsFromCommandCenterToReadyRoom, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kRobotsAtFrontDoor:
+ GameState.setTSAState(kRobotsAtReadyRoom);
+ _sprite2.setCurrentFrameIndex(kRedirectionNewTargetSprite);
+ startExtraSequence(kTSA0BRobotsFromFrontDoorToReadyRoom, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kRobotsAtReadyRoom:
+ // Nothing
+ break;
+ }
+ break;
+ case kTSA0BNorthRobotsToFrontDoorSpotID:
+ _sprite1.setCurrentFrameIndex(kRedirectionFDDoorSprite);
+ _sprite1.show();
+ _vm->delayShell(1, 2);
+ _sprite1.hide();
+
+ switch (GameState.getTSAState()) {
+ case kRobotsAtCommandCenter:
+ GameState.setTSAState(kRobotsAtFrontDoor);
+ _sprite2.setCurrentFrameIndex(kRedirectionNewTargetSprite);
+ startExtraSequence(kTSA0BRobotsFromCommandCenterToFrontDoor, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kRobotsAtFrontDoor:
+ // Nothing
+ break;
+ case kRobotsAtReadyRoom:
+ GameState.setTSAState(kRobotsAtFrontDoor);
+ _sprite2.setCurrentFrameIndex(kRedirectionNewTargetSprite);
+ startExtraSequence(kTSA0BRobotsFromReadyRoomToFrontDoor, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ }
+ break;
+
+ // Pegasus
+ case kTSA37NorthJumpToPrehistoricSpotID:
+ startExtraSequence(kTSA37PegasusDepart, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kTSA37NorthExitSpotID:
+ _sprite2.setCurrentFrameIndex(1);
+ _vm->delayShell(1, 2);
+ releaseSprites();
+ moveForward();
+ break;
+ case kTSA37NorthJumpMenuSpotID:
+ _sprite2.setCurrentFrameIndex(1);
+ _vm->delayShell(1, 2);
+ releaseSprites();
+ break;
+ case kTSA37NorthJumpToNoradSpotID:
+ GameState.setTSAState(kPlayerOnWayToNorad);
+ requestExtraSequence(kTSA37JumpToNorad, 0, kFilterNoInput);
+
+ if (!GameState.getBeenToNorad()) {
+ requestExtraSequence(kTSA37NoradToAI7, 0, kFilterNoInput);
+ requestExtraSequence(kTSA37PegasusAI7, 0, kFilterNoInput);
+ requestExtraSequence(kTSA37AI7ToNorad, 0, kFilterNoInput);
+ GameState.setBeenToNorad(true);
+ }
+
+ requestExtraSequence(kTSA37NoradToDepart, 0, kFilterNoInput);
+ requestExtraSequence(kTSA37PegasusDepart, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kTSA37NorthJumpToMarsSpotID:
+ GameState.setTSAState(kPlayerOnWayToMars);
+ requestExtraSequence(kTSA37JumpToMars, 0, kFilterNoInput);
+
+ if (!GameState.getBeenToMars()) {
+ requestExtraSequence(kTSA37MarsToAI6, 0, kFilterNoInput);
+ requestExtraSequence(kTSA37PegasusAI6, 0, kFilterNoInput);
+ requestExtraSequence(kTSA37AI6ToMars, 0, kFilterNoInput);
+ GameState.setBeenToMars(true);
+ }
+
+ requestExtraSequence(kTSA37MarsToDepart, 0, kFilterNoInput);
+ requestExtraSequence(kTSA37PegasusDepart, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kTSA37NorthJumpToWSCSpotID:
+ GameState.setTSAState(kPlayerOnWayToWSC);
+ requestExtraSequence(kTSA37JumpToWSC, 0, kFilterNoInput);
+
+ if (!GameState.getBeenToWSC()) {
+ requestExtraSequence(kTSA37WSCToAI5, 0, kFilterNoInput);
+ requestExtraSequence(kTSA37PegasusAI5, 0, kFilterNoInput);
+ requestExtraSequence(kTSA37AI5ToWSC, 0, kFilterNoInput);
+ GameState.setBeenToWSC(true);
+ }
+
+ requestExtraSequence(kTSA37WSCToDepart, 0, kFilterNoInput);
+ requestExtraSequence(kTSA37PegasusDepart, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ default:
+ Neighborhood::clickInHotspot(input, clickedSpot);
+ break;
+ }
+}
+
+void FullTSA::showMainJumpMenu() {
+ ExtraID jumpMenuView = kTSA37JumpMenu000;
+
+ if (GameState.getNoradFinished())
+ jumpMenuView += 4;
+ if (GameState.getMarsFinished())
+ jumpMenuView += 2;
+ if (GameState.getWSCFinished())
+ jumpMenuView += 1;
+
+ showExtraView(jumpMenuView);
+ setCurrentActivation(kActivationMainJumpMenu);
+}
+
+void FullTSA::playTBPMonitor() {
+ InputDevice.waitInput(kFilterAllButtons);
+
+ if ((GameState.getT0BMonitorMode() & kPlayingTBPMask) == 0) {
+ ExtraID extra;
+
+ switch (GameState.getT0BMonitorMode() & kRawModeMask) {
+ case kMonitorTheory:
+ GameState.setTSASeenTheory(true);
+ extra = kTSA0BTBPTheory;
+ GameState.setScoringSawTheory(true);
+ break;
+ case kMonitorBackground:
+ GameState.setTSASeenBackground(true);
+ extra = kTSA0BTBPBackground;
+ GameState.setScoringSawBackground(true);
+ break;
+ case kMonitorProcedure:
+ GameState.setTSASeenProcedure(true);
+ extra = kTSA0BTBPProcedure;
+ GameState.setScoringSawProcedure(true);
+ break;
+ default:
+ error("Invalid monitor mode");
+ }
+
+ GameState.setT0BMonitorMode(GameState.getT0BMonitorMode() | kPlayingTBPMask);
+
+ ExtraTable::Entry entry;
+ getExtraEntry(extra, entry);
+ _lastExtra = extra;
+
+ GameState.setT0BMonitorStart(entry.movieStart + kFullTSAFrameDuration * 5);
+ startMovieSequence(GameState.getT0BMonitorStart(), entry.movieEnd, kExtraCompletedFlag, false, kFilterAllInput);
+ } else if (_navMovie.isRunning()) {
+ _navMovie.stop();
+ } else {
+ _navMovie.start();
+ }
+}
+
+void FullTSA::initializeTBPMonitor(const int newMode, const ExtraID highlightExtra) {
+ GameState.setT0BMonitorMode(newMode);
+
+ if (newMode != kMonitorNeutral) {
+ showExtraView(highlightExtra);
+ _vm->delayShell(1, 2);
+ setCurrentActivation(kActivateTSA0BTBPVideo);
+ _sprite1.addPICTResourceFrame(kTBPRewindPICTID, false, 0, 0);
+ _sprite1.moveElementTo(kTBPRewindLeft, kTBPRewindTop);
+ _sprite1.setCurrentFrameIndex(0);
+ _sprite2.addPICTResourceFrame(kTBPCloseBoxPICTID, false, 0, 0);
+ _sprite2.moveElementTo(kTBPCloseLeft, kTBPCloseTop);
+ _sprite2.setCurrentFrameIndex(0);
+ playTBPMonitor();
+ } else {
+ if (GameState.getTSAState() == kTSAPlayerForcedReview && GameState.getTSASeenTheory() &&
+ GameState.getTSASeenBackground() && GameState.getTSASeenProcedure()) {
+ setOffRipAlarm();
+ } else {
+ setCurrentActivation(kActivateTSA0BZoomedIn);
+ updateViewFrame();
+ }
+
+ releaseSprites();
+ }
+
+ _interruptionFilter = kFilterAllInput;
+}
+
+void FullTSA::startUpComparisonMonitor() {
+ releaseSprites();
+
+ _sprite1.addPICTResourceFrame(kComparisonHiliteNoradPICTID, false,
+ kComparisonHiliteNoradLeft - kComparisonHiliteSpriteLeft,
+ kComparisonHiliteNoradTop - kComparisonHiliteSpriteTop);
+ _sprite1.addPICTResourceFrame(kComparisonHiliteMarsPICTID, false,
+ kComparisonHiliteMarsLeft - kComparisonHiliteSpriteLeft,
+ kComparisonHiliteMarsTop - kComparisonHiliteSpriteTop);
+ _sprite1.addPICTResourceFrame(kComparisonHiliteCaldoriaPICTID, false,
+ kComparisonHiliteCaldoriaLeft - kComparisonHiliteSpriteLeft,
+ kComparisonHiliteCaldoriaTop - kComparisonHiliteSpriteTop);
+ _sprite1.addPICTResourceFrame(kComparisonHiliteWSCPICTID, false,
+ kComparisonHiliteWSCLeft - kComparisonHiliteSpriteLeft,
+ kComparisonHiliteWSCTop - kComparisonHiliteSpriteTop);
+
+ _sprite1.setCurrentFrameIndex(0);
+ _sprite1.moveElementTo(kComparisonHiliteSpriteLeft, kComparisonHiliteSpriteTop);
+
+ _sprite2.addPICTResourceFrame(kComparisonChancesNoradPICTID, false,
+ kComparisonChancesNoradLeft - kComparisonChancesSpriteLeft,
+ kComparisonChancesNoradTop - kComparisonChancesSpriteTop);
+ _sprite2.addPICTResourceFrame(kComparisonChancesMarsPICTID, false,
+ kComparisonChancesMarsLeft - kComparisonChancesSpriteLeft,
+ kComparisonChancesMarsTop - kComparisonChancesSpriteTop);
+ _sprite2.addPICTResourceFrame(kComparisonChancesCaldoriaPICTID, false,
+ kComparisonChancesCaldoriaLeft - kComparisonChancesSpriteLeft,
+ kComparisonChancesCaldoriaTop - kComparisonChancesSpriteTop);
+ _sprite2.addPICTResourceFrame(kComparisonChancesWSCPICTID, false,
+ kComparisonChancesWSCLeft - kComparisonChancesSpriteLeft,
+ kComparisonChancesWSCTop - kComparisonChancesSpriteTop);
+
+ _sprite2.setCurrentFrameIndex(0);
+ _sprite2.moveElementTo(kComparisonChancesSpriteLeft, kComparisonChancesSpriteTop);
+ updateViewFrame();
+}
+
+void FullTSA::shutDownComparisonMonitor() {
+ releaseSprites();
+}
+
+void FullTSA::initializeComparisonMonitor(const int newMode, const ExtraID comparisonView) {
+ GameState.setT0BMonitorMode(newMode);
+ _privateFlags.setFlag(kTSAPrivatePlayingLeftComparisonFlag, false);
+ _privateFlags.setFlag(kTSAPrivatePlayingRightComparisonFlag, false);
+
+ if (newMode != kMonitorNeutral) {
+ shutDownComparisonMonitor();
+ setCurrentActivation(kActivateTSA0BComparisonVideo);
+ _sprite1.addPICTResourceFrame(kComparisonLeftRewindPICTID, false, 0, 0);
+ _sprite1.moveElementTo(kComparisonLeftRewindLeft, kComparisonLeftRewindTop);
+ _sprite1.setCurrentFrameIndex(0);
+ _sprite2.addPICTResourceFrame(kComparisonRightRewindPICTID, false, 0, 0);
+ _sprite2.moveElementTo(kComparisonRightRewindLeft, kComparisonRightRewindTop);
+ _sprite2.setCurrentFrameIndex(0);
+ _sprite3.addPICTResourceFrame(kComparisonCloseBoxPICTID, false, 0, 0);
+ _sprite3.moveElementTo(kComparisonCloseLeft, kComparisonCloseTop);
+ _sprite3.setCurrentFrameIndex(0);
+ showExtraView(comparisonView);
+ } else {
+ if (GameState.getTSAState() == kTSAPlayerInstalledHistoricalLog &&
+ GameState.getTSASeenNoradNormal() &&
+ GameState.getTSASeenNoradAltered() &&
+ GameState.getTSASeenMarsNormal() &&
+ GameState.getTSASeenMarsAltered() &&
+ GameState.getTSASeenCaldoriaNormal() &&
+ GameState.getTSASeenCaldoriaAltered() &&
+ GameState.getTSASeenWSCNormal() &&
+ GameState.getTSASeenWSCAltered()) {
+ GameState.setTSAState(kTSABossSawHistoricalLog);
+ requestExtraSequence(kTSA0BEastZoomOut, kExtraCompletedFlag, kFilterNoInput);
+ requestExtraSequence(kTSA0BEastTurnLeft, kExtraCompletedFlag, kFilterNoInput);
+ requestExtraSequence(kTSA0BNorthZoomIn, kExtraCompletedFlag, kFilterNoInput);
+ } else {
+ setCurrentActivation(kActivateTSA0BZoomedIn);
+ releaseSprites();
+ startUpComparisonMonitor();
+ }
+ }
+
+ _interruptionFilter = kFilterAllInput;
+}
+
+void FullTSA::playLeftComparison() {
+ InputDevice.waitInput(kFilterAllButtons);
+
+ if ((GameState.getT0BMonitorMode() & kPlayingLeftComparisonMask) == 0) {
+ ExtraID extra;
+
+ switch (GameState.getT0BMonitorMode() & kRawModeMask) {
+ case kMonitorNoradComparison:
+ GameState.setTSASeenNoradAltered(true);
+ extra = kTSA0BNoradAltered;
+ GameState.setScoringSawNoradAltered(true);
+ break;
+ case kMonitorMarsComparison:
+ GameState.setTSASeenMarsAltered(true);
+ extra = kTSA0BMarsAltered;
+ GameState.setScoringSawMarsAltered(true);
+ break;
+ case kMonitorCaldoriaComparison:
+ GameState.setTSASeenCaldoriaAltered(true);
+ extra = kTSA0BCaldoriaAltered;
+ GameState.setScoringSawCaldoriaAltered(true);
+ break;
+ case kMonitorWSCComparison:
+ GameState.setTSASeenWSCAltered(true);
+ extra = kTSA0BWSCAltered;
+ GameState.setScoringSawWSCAltered(true);
+ break;
+ default:
+ error("Invalid monitor mode");
+ }
+
+ GameState.setT0BMonitorMode(GameState.getT0BMonitorMode() | kPlayingLeftComparisonMask);
+
+ ExtraTable::Entry entry;
+ getExtraEntry(extra, entry);
+ _lastExtra = extra;
+
+ // skip first five frames of movie
+ // (this is a dissolve that doesn't belong...)
+ GameState.setT0BMonitorStart(entry.movieStart + kFullTSAFrameDuration * 5);
+ _privateFlags.setFlag(kTSAPrivatePlayingLeftComparisonFlag);
+
+ // Allow clicking...
+ startMovieSequence(GameState.getT0BMonitorStart(), entry.movieEnd,
+ kExtraCompletedFlag, false, JMPPPInput::getClickInputFilter());
+ } else if (_navMovie.isRunning()) {
+ _navMovie.stop();
+ } else {
+ _navMovie.start();
+ }
+}
+
+void FullTSA::playRightComparison() {
+ InputDevice.waitInput(kFilterAllButtons);
+
+ if ((GameState.getT0BMonitorMode() & kPlayingRightComparisonMask) == 0) {
+ ExtraID extra;
+
+ switch (GameState.getT0BMonitorMode() & kRawModeMask) {
+ case kMonitorNoradComparison:
+ GameState.setTSASeenNoradNormal(true);
+ extra = kTSA0BNoradUnaltered;
+ GameState.setScoringSawNoradNormal(true);
+ break;
+ case kMonitorMarsComparison:
+ GameState.setTSASeenMarsNormal(true);
+ extra = kTSA0BMarsUnaltered;
+ GameState.setScoringSawMarsNormal(true);
+ break;
+ case kMonitorCaldoriaComparison:
+ GameState.setTSASeenCaldoriaNormal(true);
+ extra = kTSA0BCaldoriaUnaltered;
+ GameState.setScoringSawCaldoriaNormal(true);
+ break;
+ case kMonitorWSCComparison:
+ GameState.setTSASeenWSCNormal(true);
+ extra = kTSA0BWSCUnaltered;
+ GameState.setScoringSawWSCNormal(true);
+ break;
+ default:
+ error("Invalid monitor mode");
+ }
+
+ GameState.setT0BMonitorMode(GameState.getT0BMonitorMode() | kPlayingRightComparisonMask);
+
+ ExtraTable::Entry entry;
+ getExtraEntry(extra, entry);
+ _lastExtra = extra;
+
+ // skip first five frames of movie
+ // (this is a dissolve that doesn't belong...)
+ GameState.setT0BMonitorStart(entry.movieStart + kFullTSAFrameDuration * 5);
+ _privateFlags.setFlag(kTSAPrivatePlayingRightComparisonFlag);
+
+ // Allow clicking...
+ startMovieSequence(GameState.getT0BMonitorStart(), entry.movieEnd,
+ kExtraCompletedFlag, false, JMPPPInput::getClickInputFilter());
+ } else if (_navMovie.isRunning()) {
+ _navMovie.stop();
+ } else {
+ _navMovie.start();
+ }
+}
+
+// When this function is called, the player is zoomed up on the center monitor, and the
+// TSA state is kTSABossSawHistoricalLog.
+void FullTSA::startRobotGame() {
+ requestExtraSequence(kTSA0BNorthCantChangeHistory, 0, kFilterNoInput);
+ requestExtraSequence(kTSA0BAIInterruption, 0, kFilterNoInput);
+ requestExtraSequence(kTSA0BShowGuardRobots, 0, kFilterNoInput);
+ requestExtraSequence(kTSA0BRobotsToCommandCenter, kExtraCompletedFlag, kFilterNoInput);
+}
+
+void FullTSA::startUpRobotMonitor() {
+ releaseSprites();
+
+ _sprite1.addPICTResourceFrame(kRedirectionCCRolloverPICTID, true,
+ kRedirectionCCRolloverLeft - kRedirectionSprite1Left,
+ kRedirectionCCRolloverTop - kRedirectionSprite1Top);
+ _sprite1.addPICTResourceFrame(kRedirectionRRRolloverPICTID, true,
+ kRedirectionRRRolloverLeft - kRedirectionSprite1Left,
+ kRedirectionRRRolloverTop - kRedirectionSprite1Top);
+ _sprite1.addPICTResourceFrame(kRedirectionFDRolloverPICTID, false,
+ kRedirectionFDRolloverLeft - kRedirectionSprite1Left,
+ kRedirectionFDRolloverTop - kRedirectionSprite1Top);
+ _sprite1.addPICTResourceFrame(kRedirectionCCDoorPICTID, true,
+ kRedirectionCCDoorLeft - kRedirectionSprite1Left,
+ kRedirectionCCDoorTop - kRedirectionSprite1Top);
+ _sprite1.addPICTResourceFrame(kRedirectionRRDoorPICTID, true,
+ kRedirectionRRDoorLeft - kRedirectionSprite1Left,
+ kRedirectionRRDoorTop - kRedirectionSprite1Top);
+ _sprite1.addPICTResourceFrame(kRedirectionFDDoorPICTID, false,
+ kRedirectionFDDoorLeft - kRedirectionSprite1Left,
+ kRedirectionFDDoorTop - kRedirectionSprite1Top);
+ _sprite1.addPICTResourceFrame(kRedirectionClosePICTID, false,
+ kRedirectionCloseLeft - kRedirectionSprite1Left,
+ kRedirectionCloseTop - kRedirectionSprite1Top);
+ _sprite1.moveElementTo(kRedirectionSprite1Left, kRedirectionSprite1Top);
+
+ _sprite2.addPICTResourceFrame(kRedirectionSecuredPICTID, false,
+ kRedirectionSecuredLeft - kRedirectionSprite2Left,
+ kRedirectionSecuredTop - kRedirectionSprite2Top);
+ _sprite2.addPICTResourceFrame(kRedirectionNewTargetPICTID, false,
+ kRedirectionNewTargetLeft - kRedirectionSprite2Left,
+ kRedirectionNewTargetTop - kRedirectionSprite2Top);
+ _sprite2.moveElementTo(kRedirectionSprite2Left, kRedirectionSprite2Top);
+
+ switch (GameState.getTSAState()) {
+ case kRobotsAtCommandCenter:
+ showExtraView(kTSA0BNorthRobotsAtCCView);
+ break;
+ case kRobotsAtFrontDoor:
+ showExtraView(kTSA0BNorthRobotsAtFDView);
+ break;
+ case kRobotsAtReadyRoom:
+ showExtraView(kTSA0BNorthRobotsAtRRView);
+ break;
+ }
+}
+
+void FullTSA::shutDownRobotMonitor() {
+ releaseSprites();
+}
+
+// Assume this is called only when zoomed in at T0B west
+void FullTSA::setOffRipAlarm() {
+ GameState.setTSAState(kTSAPlayerDetectedRip);
+ _ripTimer.initImage();
+ _ripTimer.moveElementTo(kRipTimerLeft, kRipTimerTop);
+ _ripTimer.setSegment(0, kRipTimeLimit, kRipTimeScale);
+ _ripTimer.start();
+ loadAmbientLoops();
+ startExtraSequenceSync(kTSA0BRipAlarmScreen, kFilterNoInput);
+ _vm->delayShell(2, 1); // Two seconds..
+ requestExtraSequence(kTSA0BWestZoomOut, kExtraCompletedFlag, kFilterNoInput);
+ requestExtraSequence(kTSA0BWestTurnRight, 0, kFilterNoInput);
+ requestExtraSequence(kTSA0BNorthZoomIn, kExtraCompletedFlag, kFilterNoInput);
+ requestExtraSequence(kTSA0BNorthFinallyHappened, 0, kFilterNoInput);
+ requestExtraSequence(kTSA0BShowRip1, kExtraCompletedFlag, kFilterNoInput);
+}
+
+void FullTSA::checkContinuePoint(const RoomID room, const DirectionConstant direction) {
+ switch (MakeRoomView(room, direction)) {
+ case MakeRoomView(kTSA04, kNorth):
+ case MakeRoomView(kTSA14, kEast):
+ case MakeRoomView(kTSA15, kWest):
+ case MakeRoomView(kTSA16, kNorth):
+ case MakeRoomView(kTSA16, kSouth):
+ case MakeRoomView(kTSA21Cyan, kSouth):
+ case MakeRoomView(kTSA21Red, kSouth):
+ case MakeRoomView(kTSA26, kNorth):
+ makeContinuePoint();
+ break;
+ }
+}
+
+void FullTSA::arriveAt(const RoomID room, const DirectionConstant direction) {
+ checkRobotLocations(room, direction);
+ Neighborhood::arriveAt(room, direction);
+
+ switch (MakeRoomView(room, direction)) {
+ case MakeRoomView(kTSADeathRoom, kNorth):
+ case MakeRoomView(kTSADeathRoom, kSouth):
+ case MakeRoomView(kTSADeathRoom, kEast):
+ case MakeRoomView(kTSADeathRoom, kWest):
+ die(kDeathShotByTSARobots);
+ break;
+ case MakeRoomView(kTSA00, kNorth):
+ if (GameState.getLastNeighborhood() != kFullTSAID) {
+ makeContinuePoint();
+ openDoor();
+ } else {
+ setCurrentActivation(kActivateTSAReadyForCard);
+ loopExtraSequence(kTSATransporterArrowLoop, 0);
+ }
+ break;
+ case MakeRoomView(kTSA03, kNorth):
+ case MakeRoomView(kTSA05, kNorth):
+ case MakeRoomView(kTSA0A, kNorth):
+ case MakeRoomView(kTSA06, kNorth):
+ case MakeRoomView(kTSA07, kNorth):
+ if (_utilityFuse.isFuseLit())
+ _utilityFuse.stopFuse();
+ GameState.setScoringEnterTSA(true);
+ break;
+ case MakeRoomView(kTSA04, kNorth):
+ if (_utilityFuse.isFuseLit())
+ _utilityFuse.stopFuse();
+ if (!GameState.getTSASeenRobotGreeting())
+ startExtraSequence(kTSA04NorthRobotGreeting, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case MakeRoomView(kTSA03, kSouth):
+ GameState.setTSAFrontDoorUnlockedInside(GameState.getTSAState() == kRobotsAtFrontDoor || GameState.allTimeZonesFinished());
+ break;
+ case MakeRoomView(kTSA0A, kEast):
+ case MakeRoomView(kTSA0A, kWest):
+ if (GameState.getTSAState() == kTSAPlayerNotArrived)
+ setCurrentActivation(kActivateTSARobotsAwake);
+ break;
+ case MakeRoomView(kTSA0B, kNorth):
+ if (GameState.getTSA0BZoomedIn()) {
+ setCurrentActivation(kActivateTSA0BZoomedIn);
+
+ switch (GameState.getTSAState()) {
+ case kTSAPlayerNeedsHistoricalLog:
+ _ripTimer.show();
+ break;
+ case kRobotsAtCommandCenter:
+ case kRobotsAtFrontDoor:
+ case kRobotsAtReadyRoom:
+ startUpRobotMonitor();
+ break;
+ }
+ } else {
+ setCurrentActivation(kActivateTSA0BZoomedOut);
+
+ switch (GameState.getTSAState()) {
+ case kTSAPlayerNotArrived:
+ requestExtraSequence(kTSA0BNorthZoomIn, kExtraCompletedFlag, kFilterNoInput);
+ requestExtraSequence(kTSA0BNorthYoureBusted, 0, kFilterNoInput);
+ requestExtraSequence(kTSA0BNorthZoomOut, kExtraCompletedFlag, kFilterNoInput);
+ requestExtraSequence(kTSA0BNorthTurnLeft, 0, kFilterNoInput);
+ requestExtraSequence(kTSA0BWestZoomIn, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kTSAPlayerGotHistoricalLog:
+ startExtraSequence(kTSA0BNorthHistLogOpen, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ }
+ }
+ break;
+ case MakeRoomView(kTSA0B, kSouth):
+ GameState.setTSA0BZoomedIn(false);
+ setCurrentActivation(kActivateTSA0BZoomedOut);
+ break;
+ case MakeRoomView(kTSA0B, kWest):
+ if (GameState.getTSA0BZoomedIn()) {
+ setCurrentActivation(kActivateTSA0BZoomedIn);
+ initializeTBPMonitor(kMonitorNeutral, 0);
+ } else {
+ setCurrentActivation(kActivateTSA0BZoomedOut);
+ }
+ break;
+ case MakeRoomView(kTSA0B, kEast):
+ if (GameState.getTSA0BZoomedIn()) {
+ setCurrentActivation(kActivateTSA0BZoomedIn);
+
+ switch (GameState.getTSAState()) {
+ case kTSAPlayerInstalledHistoricalLog:
+ case kTSABossSawHistoricalLog:
+ case kRobotsAtCommandCenter:
+ case kRobotsAtFrontDoor:
+ case kRobotsAtReadyRoom:
+ initializeComparisonMonitor(kMonitorNeutral, 0);
+ break;
+ }
+ } else {
+ setCurrentActivation(kActivateTSA0BZoomedOut);
+ }
+ break;
+ case MakeRoomView(kTSA21Red, kSouth):
+ if (GameState.getTSAState() == kRobotsAtFrontDoor)
+ GameState.setScoringWentToReadyRoom2(true);
+ break;
+ case MakeRoomView(kTSA22Red, kEast):
+ if (!_vm->playerHasItemID(kJourneymanKey))
+ setCurrentActivation(kActivationDoesntHaveKey);
+ break;
+ case MakeRoomView(kTSA23Red, kWest):
+ if (!_vm->playerHasItemID(kPegasusBiochip))
+ setCurrentActivation(kActivationDoesntHaveChips);
+ break;
+ case MakeRoomView(kTSA25Red, kNorth):
+ arriveAtTSA25Red();
+ break;
+ case MakeRoomView(kTSA34, kSouth):
+ if (GameState.getLastRoom() == kTSA37)
+ closeDoorOffScreen(kTSA37, kNorth);
+ break;
+ case MakeRoomView(kTSA37, kNorth):
+ arriveAtTSA37();
+ break;
+ }
+}
+
+void FullTSA::checkRobotLocations(const RoomID room, const DirectionConstant dir) {
+ switch (room) {
+ case kTSA03:
+ case kTSA04:
+ case kTSA05:
+ case kTSA06:
+ case kTSA0A:
+ case kTSA07:
+ case kTSA08:
+ case kTSA09:
+ case kTSA10:
+ case kTSA11:
+ case kTSA12:
+ case kTSA13:
+ case kTSA14:
+ case kTSA15:
+ switch (GameState.getTSAState()) {
+ case kRobotsAtFrontDoor:
+ setCurrentAlternate(kAltTSARobotsAtFrontDoor);
+ break;
+ case kRobotsAtReadyRoom:
+ setCurrentAlternate(kAltTSARobotsAtReadyRoom);
+ break;
+ }
+ break;
+ case kTSA16:
+ if (dir == kNorth) {
+ switch (GameState.getTSAState()) {
+ case kRobotsAtCommandCenter:
+ if (!_privateFlags.getFlag(kTSAPrivateSeenRobotWarningFlag)) {
+ g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/TSA/XT11WB", false, kWarningInterruption);
+ _privateFlags.setFlag(kTSAPrivateSeenRobotWarningFlag, true);
+ }
+ break;
+ case kRobotsAtFrontDoor:
+ setCurrentAlternate(kAltTSARobotsAtFrontDoor);
+ break;
+ case kRobotsAtReadyRoom:
+ setCurrentAlternate(kAltTSARobotsAtReadyRoom);
+ break;
+ }
+ }
+ break;
+ }
+}
+
+void FullTSA::arriveAtTSA25Red() {
+ if (!_vm->playerHasItemID(kJourneymanKey))
+ startExtraSequence(kTSA25NorthDeniedNoKey, kExtraCompletedFlag, kFilterNoInput);
+ else if (!_vm->playerHasItemID(kPegasusBiochip))
+ startExtraSequence(kTSA25NorthDeniedNoChip, kExtraCompletedFlag, kFilterNoInput);
+ else if (GameState.getTSABiosuitOn())
+ startExtraSequence(kTSA25NorthAlreadyHaveSuit, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraSequence(kTSA25NorthPutOnSuit, kExtraCompletedFlag, kFilterNoInput);
+}
+
+void FullTSA::arriveAtTSA37() {
+ _ripTimer.stop();
+ _ripTimer.releaseImage();
+
+ switch (GameState.getTSAState()) {
+ case kTSAPlayerNeedsHistoricalLog:
+ startExtraLongSequence(kTSA37HorseToAI1, kTSA37AI2ToPrehistoric, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kPlayerOnWayToPrehistoric:
+ setCurrentActivation(kActivationJumpToPrehistoric);
+ showExtraView(kTSA37AI2ToPrehistoric);
+ break;
+ case kTSAPlayerGotHistoricalLog:
+ initializePegasusButtons(false);
+ break;
+ case kPlayerWentToPrehistoric:
+ case kPlayerOnWayToNorad:
+ case kPlayerOnWayToMars:
+ case kPlayerOnWayToWSC:
+ startExtraSequence(kTSA37TimeJumpToPegasus, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kRobotsAtFrontDoor:
+ startExtraLongSequence(kTSA37HorseToColonel2, kTSA37AI4ToMainMenu, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kPlayerLockedInPegasus:
+ showMainJumpMenu();
+ break;
+ case kPlayerFinishedWithTSA:
+ initializePegasusButtons(true);
+ break;
+ }
+}
+
+void FullTSA::turnTo(const DirectionConstant newDirection) {
+ Neighborhood::turnTo(newDirection);
+
+ switch (MakeRoomView(GameState.getCurrentRoom(), newDirection)) {
+ case MakeRoomView(kTSA03, kSouth):
+ if (GameState.getTSAState() == kRobotsAtFrontDoor || GameState.allTimeZonesFinished())
+ GameState.setTSAFrontDoorUnlockedInside(true);
+ else
+ GameState.setTSAFrontDoorUnlockedInside(false);
+ break;
+ case MakeRoomView(kTSA0A, kEast):
+ case MakeRoomView(kTSA0A, kWest):
+ setCurrentActivation(kActivateTSARobotsAwake);
+ break;
+ case MakeRoomView(kTSA0B, kEast):
+ if (GameState.getTSA0BZoomedIn())
+ setCurrentActivation(kActivateTSA0BZoomedIn);
+ else
+ setCurrentActivation(kActivateTSA0BZoomedOut);
+
+ GameState.setT0BMonitorMode(GameState.getT0BMonitorMode() & ~kPlayingAnyMask);
+
+ if (_privateFlags.getFlag(kTSAPrivateLogReaderOpenFlag))
+ _privateFlags.setFlag(kTSAPrivateLogReaderOpenFlag, false);
+
+ switch (GameState.getTSAState()) {
+ case kTSAPlayerInstalledHistoricalLog:
+ case kTSABossSawHistoricalLog:
+ case kRobotsAtCommandCenter:
+ case kRobotsAtFrontDoor:
+ case kRobotsAtReadyRoom:
+ if (GameState.getTSA0BZoomedIn())
+ startUpComparisonMonitor();
+ break;
+ }
+ break;
+ case MakeRoomView(kTSA0B, kNorth):
+ if (GameState.getTSA0BZoomedIn())
+ setCurrentActivation(kActivateTSA0BZoomedIn);
+ else
+ setCurrentActivation(kActivateTSA0BZoomedOut);
+
+ GameState.setT0BMonitorMode(GameState.getT0BMonitorMode() & ~kPlayingAnyMask);
+
+ switch (GameState.getTSAState()) {
+ case kTSAPlayerNeedsHistoricalLog:
+ if (GameState.getTSA0BZoomedIn())
+ _ripTimer.show();
+ break;
+ case kTSAPlayerGotHistoricalLog:
+ if (!GameState.getTSA0BZoomedIn())
+ startExtraSequence(kTSA0BNorthHistLogOpen, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kTSAPlayerInstalledHistoricalLog:
+ if (GameState.getTSA0BZoomedIn()) {
+ if ((GameState.getTSASeenNoradNormal() || GameState.getTSASeenNoradAltered()) &&
+ (GameState.getTSASeenMarsNormal() || GameState.getTSASeenMarsAltered()) &&
+ (GameState.getTSASeenCaldoriaNormal() || GameState.getTSASeenCaldoriaAltered()) &&
+ (GameState.getTSASeenWSCNormal() || GameState.getTSASeenWSCAltered())) {
+ GameState.setTSAState(kTSABossSawHistoricalLog);
+ startRobotGame();
+ }
+ }
+ break;
+ case kRobotsAtCommandCenter:
+ case kRobotsAtFrontDoor:
+ case kRobotsAtReadyRoom:
+ if (GameState.getTSA0BZoomedIn())
+ startExtraSequence(kTSA0BShowGuardRobots, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ }
+ break;
+ case MakeRoomView(kTSA0B, kWest):
+ if (GameState.getTSA0BZoomedIn())
+ setCurrentActivation(kActivateTSA0BZoomedIn);
+ else
+ setCurrentActivation(kActivateTSA0BZoomedOut);
+
+ GameState.setT0BMonitorMode(GameState.getT0BMonitorMode() & ~kPlayingAnyMask);
+
+ if (_privateFlags.getFlag(kTSAPrivateLogReaderOpenFlag))
+ _privateFlags.setFlag(kTSAPrivateLogReaderOpenFlag, false);
+
+ if (GameState.getTSA0BZoomedIn())
+ initializeTBPMonitor(kMonitorNeutral, 0);
+ break;
+ case MakeRoomView(kTSA0B, kSouth):
+ GameState.setTSA0BZoomedIn(false);
+ setCurrentActivation(kActivateTSA0BZoomedOut);
+ break;
+ case MakeRoomView(kTSA16, kNorth):
+ switch (GameState.getTSAState()) {
+ case kRobotsAtCommandCenter:
+ if (!_privateFlags.getFlag(kTSAPrivateSeenRobotWarningFlag)) {
+ g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/TSA/XT11WB", false, kWarningInterruption);
+ _privateFlags.setFlag(kTSAPrivateSeenRobotWarningFlag, true);
+ }
+ break;
+ case kRobotsAtFrontDoor:
+ setCurrentAlternate(kAltTSARobotsAtFrontDoor);
+ break;
+ case kRobotsAtReadyRoom:
+ setCurrentAlternate(kAltTSARobotsAtReadyRoom);
+ break;
+ }
+ break;
+ case MakeRoomView(kTSA22Red, kEast):
+ if (!_vm->playerHasItemID(kJourneymanKey))
+ setCurrentActivation(kActivationDoesntHaveKey);
+ break;
+ case MakeRoomView(kTSA22Red, kNorth):
+ case MakeRoomView(kTSA22Red, kSouth):
+ if (_privateFlags.getFlag(kTSAPrivateKeyVaultOpenFlag)) {
+ playSpotSoundSync(kTSAVaultCloseIn, kTSAVaultCloseOut);
+ _privateFlags.setFlag(kTSAPrivateKeyVaultOpenFlag, false);
+ }
+
+ setCurrentActivation(kActivateHotSpotAlways);
+ break;
+ case MakeRoomView(kTSA23Red, kWest):
+ if (!_vm->playerHasItemID(kPegasusBiochip))
+ setCurrentActivation(kActivationDoesntHaveChips);
+ break;
+ case MakeRoomView(kTSA23Red, kNorth):
+ case MakeRoomView(kTSA23Red, kSouth):
+ if (_privateFlags.getFlag(kTSAPrivateChipVaultOpenFlag)) {
+ playSpotSoundSync(kTSAVaultCloseIn, kTSAVaultCloseOut);
+ _privateFlags.setFlag(kTSAPrivateChipVaultOpenFlag, false);
+ }
+
+ setCurrentActivation(kActivateHotSpotAlways);
+ break;
+ }
+
+ // Make sure the TBP monitor is forced neutral.
+ GameState.setT0BMonitorMode(kMonitorNeutral);
+}
+
+void FullTSA::closeDoorOffScreen(const RoomID room, const DirectionConstant) {
+ switch (room) {
+ case kTSA00:
+ case kTSA01:
+ if (GameState.getCurrentRoom() == kTSA01 || GameState.getCurrentRoom() == kTSA02)
+ playSpotSoundSync(kTSAGTDoorCloseIn, kTSAGTDoorCloseOut);
+ break;
+ case kTSA02:
+ case kTSA03:
+ playSpotSoundSync(kTSAEntryDoorCloseIn, kTSAEntryDoorCloseOut);
+ break;
+ case kTSA14:
+ case kTSA15:
+ case kTSA16:
+ case kTSA21Cyan:
+ case kTSA21Red:
+ playSpotSoundSync(kTSAInsideDoorCloseIn, kTSAInsideDoorCloseOut);
+ break;
+ case kTSA34:
+ case kTSA37:
+ playSpotSoundSync(kTSAPegasusDoorCloseIn, kTSAPegasusDoorCloseOut);
+ break;
+ }
+}
+
+void FullTSA::receiveNotification(Notification *notification, const NotificationFlags flags) {
+ ExtraID lastExtra = _lastExtra;
+
+ if ((flags & kExtraCompletedFlag) != 0) {
+ switch (lastExtra) {
+ case kTSA0BEastTurnLeft:
+ // Need to check this here because turnTo will call _navMovie.stop,
+ // so it has to happen before Neighborhood::receiveNotification,
+ // which may end up starting another sequence...
+ turnTo(kNorth);
+ break;
+ }
+ }
+
+ Neighborhood::receiveNotification(notification, flags);
+
+ InventoryItem *item;
+
+ if ((flags & kExtraCompletedFlag) != 0) {
+ // Only allow input if we're not in the middle of series of queue requests.
+ if (actionQueueEmpty())
+ _interruptionFilter = kFilterAllInput;
+
+ switch (lastExtra) {
+ case kTSAGTCardSwipe:
+ item = (InventoryItem *)_vm->getAllItems().findItemByID(kKeyCard);
+ _vm->addItemToInventory(item);
+ setCurrentActivation(kActivateTSAReadyToTransport);
+ break;
+ case kTSAGTGoToCaldoria:
+ _vm->jumpToNewEnvironment(kCaldoriaID, kCaldoria44, kEast);
+
+ if (GameState.allTimeZonesFinished())
+ GameState.setScoringWentAfterSinclair(true);
+ break;
+ case kTSAGTGoToTokyo:
+ case kTSAGTGoToBeach:
+ if (GameState.allTimeZonesFinished())
+ die(kDeathSinclairShotDelegate);
+ else
+ die(kDeathUncreatedInTSA);
+ break;
+ case kTSA02NorthZoomOut:
+ openDoor();
+ break;
+
+ // Hall of suspects.
+ case kTSA04NorthRobotGreeting:
+ GameState.setTSASeenRobotGreeting(true);
+ restoreStriding(kTSA03, kNorth, kNoAlternateID);
+ break;
+ case kTSA03JimenezZoomIn:
+ GameState.setScoringSawBust1(true);
+ break;
+ case kTSA03CrenshawZoomIn:
+ GameState.setScoringSawBust2(true);
+ break;
+ case kTSA04MatsumotoZoomIn:
+ GameState.setScoringSawBust3(true);
+ break;
+ case kTSA04CastilleZoomIn:
+ GameState.setScoringSawBust4(true);
+ break;
+ case kTSA05SinclairZoomIn:
+ GameState.setScoringSawBust5(true);
+ break;
+ case kTSA05WhiteZoomIn:
+ GameState.setScoringSawBust6(true);
+ break;
+
+ // Command center
+ // Historical comparison...
+ case kTSA0BEastZoomIn:
+ GameState.setTSA0BZoomedIn(true);
+ setCurrentActivation(kActivateTSA0BZoomedIn);
+ GameState.setT0BMonitorMode(GameState.getT0BMonitorMode() & ~kPlayingAnyMask);
+
+ switch (GameState.getTSAState()) {
+ case kTSAPlayerInstalledHistoricalLog:
+ case kTSABossSawHistoricalLog:
+ case kRobotsAtCommandCenter:
+ case kRobotsAtFrontDoor:
+ case kRobotsAtReadyRoom:
+ startUpComparisonMonitor();
+ break;
+ }
+ break;
+ case kTSA0BEastZoomOut:
+ GameState.setTSA0BZoomedIn(false);
+ setCurrentActivation(kActivateTSA0BZoomedOut);
+
+ switch (GameState.getTSAState()) {
+ case kTSABossSawHistoricalLog:
+ // Prevent current view from activating.
+ break;
+ default:
+ activateCurrentView(GameState.getCurrentRoom(), GameState.getCurrentDirection(),
+ kSpotOnTurnMask);
+ break;
+ }
+ break;
+ case kTSA0BComparisonStartup:
+ if ((flags & kActionRequestCompletedFlag) != 0) {
+ _privateFlags.setFlag(kTSAPrivateLogReaderOpenFlag, false);
+ GameState.setTSAState(kTSAPlayerInstalledHistoricalLog);
+ turnTo(kEast);
+ }
+
+ startUpComparisonMonitor();
+ break;
+ case kTSA0BNoradAltered:
+ case kTSA0BMarsAltered:
+ case kTSA0BCaldoriaAltered:
+ case kTSA0BWSCAltered:
+ case kTSA0BNoradUnaltered:
+ case kTSA0BMarsUnaltered:
+ case kTSA0BCaldoriaUnaltered:
+ case kTSA0BWSCUnaltered:
+ initializeComparisonMonitor(kMonitorNeutral, 0);
+ break;
+
+ // Center monitor.
+ case kTSA0BNorthZoomIn:
+ GameState.setTSA0BZoomedIn(true);
+ setCurrentActivation(kActivateTSA0BZoomedIn);
+ GameState.setT0BMonitorMode(GameState.getT0BMonitorMode() & ~kPlayingAnyMask);
+
+ switch (GameState.getTSAState()) {
+ case kTSAPlayerNeedsHistoricalLog:
+ startExtraSequence(kTSA0BShowRip1, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kTSABossSawHistoricalLog:
+ case kTSAPlayerInstalledHistoricalLog:
+ if ((GameState.getTSASeenNoradNormal() || GameState.getTSASeenNoradAltered()) &&
+ (GameState.getTSASeenMarsNormal() || GameState.getTSASeenMarsAltered()) &&
+ (GameState.getTSASeenCaldoriaNormal() || GameState.getTSASeenCaldoriaAltered()) &&
+ (GameState.getTSASeenWSCNormal() || GameState.getTSASeenWSCAltered())) {
+ GameState.setTSAState(kTSABossSawHistoricalLog);
+ startRobotGame();
+ }
+ break;
+ case kRobotsAtCommandCenter:
+ case kRobotsAtFrontDoor:
+ case kRobotsAtReadyRoom:
+ startExtraSequence(kTSA0BShowGuardRobots, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ }
+ break;
+ case kTSA0BNorthZoomOut:
+ GameState.setTSA0BZoomedIn(false);
+ setCurrentActivation(kActivateTSA0BZoomedOut);
+ break;
+ case kTSA0BShowRip1:
+ GameState.setTSAState(kTSAPlayerNeedsHistoricalLog);
+ GameState.setTSACommandCenterLocked(false);
+
+ if ((flags & kActionRequestCompletedFlag) != 0)
+ turnTo(kNorth);
+
+ _ripTimer.show();
+ break;
+ case kTSA0BNorthHistLogOpen:
+ setCurrentActivation(kActivationLogReaderOpen);
+ _privateFlags.setFlag(kTSAPrivateLogReaderOpenFlag, true);
+ break;
+ case kTSA0BRobotsToCommandCenter:
+ GameState.setTSAState(kRobotsAtCommandCenter);
+ // Fall through
+ case kTSA0BShowGuardRobots:
+ startUpRobotMonitor();
+ // Fall through
+ case kTSA0BRobotsFromCommandCenterToReadyRoom:
+ case kTSA0BRobotsFromReadyRoomToCommandCenter:
+ case kTSA0BRobotsFromCommandCenterToFrontDoor:
+ case kTSA0BRobotsFromFrontDoorToCommandCenter:
+ case kTSA0BRobotsFromFrontDoorToReadyRoom:
+ case kTSA0BRobotsFromReadyRoomToFrontDoor:
+ _sprite2.setCurrentFrameIndex(kRedirectionSecuredSprite);
+ _sprite2.show();
+ break;
+
+ // TBP monitor.
+ case kTSA0BWestZoomIn:
+ GameState.setTSA0BZoomedIn(true);
+ setCurrentActivation(kActivateTSA0BZoomedIn);
+
+ if (GameState.getTSAState() == kTSAPlayerNotArrived) {
+ turnTo(kWest);
+ GameState.setTSACommandCenterLocked(true);
+ GameState.setTSAState(kTSAPlayerForcedReview);
+ }
+
+ initializeTBPMonitor(kMonitorNeutral, 0);
+ break;
+ case kTSA0BWestZoomOut:
+ GameState.setTSA0BZoomedIn(false);
+ setCurrentActivation(kActivateTSA0BZoomedOut);
+ GameState.setT0BMonitorMode(kMonitorNeutral);
+
+ switch (GameState.getTSAState()) {
+ case kTSAPlayerDetectedRip:
+ // Keep the current view from activating.
+ break;
+ default:
+ activateCurrentView(GameState.getCurrentRoom(), GameState.getCurrentDirection(),
+ kSpotOnTurnMask);
+ break;
+ }
+ break;
+ case kTSA0BTBPTheory:
+ case kTSA0BTBPBackground:
+ case kTSA0BTBPProcedure:
+ initializeTBPMonitor(kMonitorNeutral, 0);
+ break;
+
+ // Ready room
+ case kTSA22RedEastZoomInSequence:
+ _privateFlags.setFlag(kTSAPrivateKeyVaultOpenFlag, true);
+ setCurrentActivation(kActivationKeyVaultOpen);
+ break;
+ case kTSA23RedWestVaultZoomInSequence:
+ _privateFlags.setFlag(kTSAPrivateChipVaultOpenFlag, true);
+ setCurrentActivation(kActivationChipVaultOpen);
+ break;
+ case kTSA25NorthPutOnSuit:
+ GameState.setTSABiosuitOn(true);
+ GameState.setScoringGotBiosuit(true);
+ // Fall through...
+ case kTSA25NorthAlreadyHaveSuit:
+ requestExtraSequence(kTSA25NorthDescending1, 0, kFilterNoInput);
+ requestExtraSequence(kTSA25NorthDescending2, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kTSA25NorthDescending2:
+ arriveAt(kTSA26, kNorth);
+ break;
+
+ // Pegasus.
+ case kTSA37HorseToAI1:
+ case kTSA37AI2ToPrehistoric:
+ setCurrentActivation(kActivationJumpToPrehistoric);
+ GameState.setTSAState(kPlayerOnWayToPrehistoric);
+ break;
+ case kTSA37PegasusDepart:
+ _vm->setLastEnergyValue(kFullEnergy);
+
+ switch (GameState.getTSAState()) {
+ case kPlayerOnWayToPrehistoric:
+ _vm->jumpToNewEnvironment(kPrehistoricID, kPrehistoric02, kSouth);
+ GameState.setPrehistoricSeenTimeStream(false);
+ GameState.setPrehistoricSeenFlyer1(false);
+ GameState.setPrehistoricSeenFlyer2(false);
+ GameState.setPrehistoricSeenBridgeZoom(false);
+ GameState.setPrehistoricBreakerThrown(false);
+ GameState.setScoringGoToPrehistoric(true);
+ GameState.setTSAState(kPlayerWentToPrehistoric);
+ break;
+ case kPlayerOnWayToNorad:
+ _vm->jumpToNewEnvironment(kNoradAlphaID, kNorad01, kSouth);
+ GameState.setNoradSeenTimeStream(false);
+ GameState.setNoradGassed(true);
+ GameState.setNoradFillingStationOn(false);
+ GameState.setNoradN22MessagePlayed(false);
+ GameState.setNoradPlayedGlobeGame(false);
+ GameState.setNoradBeatRobotWithClaw(false);
+ GameState.setNoradBeatRobotWithDoor(false);
+ GameState.setNoradRetScanGood(false);
+ GameState.setNoradWaitingForLaser(false);
+ GameState.setNoradSubRoomPressure(9);
+ GameState.setNoradSubPrepState(kSubNotPrepped);
+ break;
+ case kPlayerOnWayToMars:
+ _vm->jumpToNewEnvironment(kMarsID, kMars0A, kNorth);
+ GameState.setMarsSeenTimeStream(false);
+ GameState.setMarsHeardUpperPodMessage(false);
+ GameState.setMarsRobotThrownPlayer(false);
+ GameState.setMarsHeardCheckInMessage(false);
+ GameState.setMarsPodAtUpperPlatform(false);
+ GameState.setMarsSeenThermalScan(false);
+ GameState.setMarsArrivedBelow(false);
+ GameState.setMarsSeenRobotAtReactor(false);
+ GameState.setMarsAvoidedReactorRobot(false);
+ GameState.setMarsLockFrozen(false);
+ GameState.setMarsLockBroken(false);
+ GameState.setMarsSecurityDown(false);
+ GameState.setMarsAirlockOpen(false);
+ GameState.setMarsReadyForShuttleTransport(false);
+ GameState.setMarsFinishedCanyonChase(false);
+ GameState.setMarsThreadedMaze(false);
+ break;
+ case kPlayerOnWayToWSC:
+ _vm->jumpToNewEnvironment(kWSCID, kWSC01, kWest);
+ GameState.setWSCSeenTimeStream(false);
+ GameState.setWSCPoisoned(false);
+ GameState.setWSCAnsweredAboutDart(false);
+ GameState.setWSCRemovedDart(false);
+ GameState.setWSCAnalyzerOn(false);
+ GameState.setWSCDartInAnalyzer(false);
+ GameState.setWSCAnalyzedDart(false);
+ GameState.setWSCPickedUpAntidote(false);
+ GameState.setWSCSawMorph(false);
+ GameState.setWSCDesignedAntidote(false);
+ GameState.setWSCOfficeMessagesOpen(false);
+ GameState.setWSCSeenNerd(false);
+ GameState.setWSCHeardPage1(false);
+ GameState.setWSCHeardPage2(false);
+ GameState.setWSCHeardCheckIn(false);
+ GameState.setWSCDidPlasmaDodge(false);
+ GameState.setWSCSeenSinclairLecture(false);
+ GameState.setWSCBeenAtWSC93(false);
+ GameState.setWSCCatwalkDark(false);
+ GameState.setWSCRobotDead(false);
+ GameState.setWSCRobotGone(false);
+ break;
+ };
+ break;
+ case kTSA37TimeJumpToPegasus:
+ if (g_energyMonitor)
+ g_energyMonitor->stopEnergyDraining();
+
+ switch (GameState.getTSAState()) {
+ case kPlayerWentToPrehistoric:
+ arriveFromPrehistoric();
+ break;
+ case kPlayerOnWayToNorad:
+ arriveFromNorad();
+ break;
+ case kPlayerOnWayToMars:
+ arriveFromMars();
+ break;
+ case kPlayerOnWayToWSC:
+ arriveFromWSC();
+ break;
+ default:
+ break;
+ }
+ break;
+ case kTSA37DownloadToOpMemReview:
+ switch (GameState.getTSAState()) {
+ case kPlayerOnWayToNorad:
+ g_opticalChip->playOpMemMovie(kPoseidonSpotID);
+ break;
+ case kPlayerOnWayToMars:
+ g_opticalChip->playOpMemMovie(kAriesSpotID);
+ break;
+ case kPlayerOnWayToWSC:
+ g_opticalChip->playOpMemMovie(kMercurySpotID);
+ break;
+ }
+
+ if (GameState.allTimeZonesFinished()) {
+ requestExtraSequence(kTSA37OpMemReviewToAllClear, 0, kFilterNoInput);
+ requestExtraSequence(kTSA37AllClearToCongratulations, 0, kFilterNoInput);
+ requestExtraSequence(kTSA37Congratulations, 0, kFilterNoInput);
+ requestExtraSequence(kTSA37CongratulationsToExit, kExtraCompletedFlag, kFilterNoInput);
+ } else {
+ requestExtraSequence(kTSA37OpMemReviewToMainMenu, kExtraCompletedFlag, kFilterNoInput);
+ }
+ break;
+ case kTSA37RecallToDownload:
+ case kTSA37ReviewRequiredToExit:
+ GameState.setTSAState(kTSAPlayerGotHistoricalLog);
+ initializePegasusButtons(kPegasusUnresolved);
+ break;
+ case kTSA37ZoomToMainMenu:
+ case kTSA37HorseToColonel2:
+ case kTSA37DownloadToMainMenu:
+ case kTSA37OpMemReviewToMainMenu:
+ case kTSA37AI4ToMainMenu:
+ GameState.setTSAState(kPlayerLockedInPegasus);
+ showMainJumpMenu();
+ makeContinuePoint();
+ break;
+ case kTSA37JumpToNoradMenu:
+ setCurrentActivation(kActivationJumpToNorad);
+ break;
+ case kTSA37JumpToMarsMenu:
+ setCurrentActivation(kActivationJumpToMars);
+ break;
+ case kTSA37JumpToWSCMenu:
+ setCurrentActivation(kActivationJumpToWSC);
+ break;
+ case kTSA37CancelNorad:
+ case kTSA37CancelMars:
+ case kTSA37CancelWSC:
+ showMainJumpMenu();
+ break;
+ case kTSA37CongratulationsToExit:
+ GameState.setTSAState(kPlayerFinishedWithTSA);
+ initializePegasusButtons(true);
+ break;
+ }
+ }
+
+ g_AIArea->checkMiddleArea();
+}
+
+void FullTSA::arriveFromPrehistoric() {
+ if (_vm->playerHasItemID(kHistoricalLog)) {
+ GameState.setScoringFinishedPrehistoric();
+ requestExtraSequence(kTSA37RecallToDownload, 0, kFilterNoInput);
+ requestExtraSequence(kTSA37DownloadToColonel1, 0, kFilterNoInput);
+ requestExtraSequence(kTSA37Colonel1, 0, kFilterNoInput);
+ requestExtraSequence(kTSA37Colonel1ToReviewRequired, 0, kFilterNoInput);
+ requestExtraSequence(kTSA37ReviewRequiredToExit, kExtraCompletedFlag, kFilterNoInput);
+ } else {
+ // Make sure rip timer is going...
+ startExtraSequence(kTSA37DownloadToMainMenu, kExtraCompletedFlag, kFilterNoInput);
+ }
+}
+
+void FullTSA::arriveFromNorad() {
+ requestExtraSequence(kTSA37RecallToDownload, 0, kFilterNoInput);
+
+ if (GameState.getNoradFinished() && !GameState.getScoringFinishedNorad()) {
+ GameState.setScoringFinishedNorad();
+ requestExtraSequence(kTSA37DownloadToOpMemReview, kExtraCompletedFlag, kFilterNoInput);
+ } else {
+ requestExtraSequence(kTSA37DownloadToMainMenu, kExtraCompletedFlag, kFilterNoInput);
+ }
+}
+
+void FullTSA::arriveFromMars() {
+ requestExtraSequence(kTSA37RecallToDownload, 0, kFilterNoInput);
+
+ if (GameState.getMarsFinished() && !GameState.getScoringFinishedMars()) {
+ GameState.setScoringFinishedMars();
+ requestExtraSequence(kTSA37DownloadToOpMemReview, kExtraCompletedFlag, kFilterNoInput);
+ } else {
+ requestExtraSequence(kTSA37DownloadToMainMenu, kExtraCompletedFlag, kFilterNoInput);
+ }
+}
+
+void FullTSA::arriveFromWSC() {
+ requestExtraSequence(kTSA37RecallToDownload, 0, kFilterNoInput);
+
+ if (GameState.getWSCFinished() && !GameState.getScoringFinishedWSC()) {
+ GameState.setScoringFinishedWSC();
+ requestExtraSequence(kTSA37DownloadToOpMemReview, kExtraCompletedFlag, kFilterNoInput);
+ } else {
+ requestExtraSequence(kTSA37DownloadToMainMenu, kExtraCompletedFlag, kFilterNoInput);
+ }
+}
+
+void FullTSA::initializePegasusButtons(bool resolved) {
+ if (resolved) {
+ _sprite1.addPICTResourceFrame(kResolvedPICTID, false, 0, 0);
+ _sprite1.moveElementTo(kResolvedLeft, kResolvedTop);
+ } else {
+ _sprite1.addPICTResourceFrame(kUnresolvedPICTID, false, 0, 0);
+ _sprite1.moveElementTo(kUnresolvedLeft, kUnresolvedTop);
+ }
+
+ _sprite1.setCurrentFrameIndex(0);
+ _sprite1.show();
+
+ _sprite2.addPICTResourceFrame(kExitPICTID, false, kExitLeft - kExitHilitedLeft, kExitTop - kExitHilitedTop);
+ _sprite2.addPICTResourceFrame(kExitHilitedPICTID, false, 0, 0);
+ _sprite2.moveElementTo(kExitHilitedLeft, kExitHilitedTop);
+ setCurrentActivation(kActivationReadyToExit);
+ _sprite2.setCurrentFrameIndex(0);
+ _sprite2.show();
+}
+
+Hotspot *FullTSA::getItemScreenSpot(Item *item, DisplayElement *element) {
+ switch (item->getObjectID()) {
+ case kJourneymanKey:
+ return _vm->getAllHotspots().findHotspotByID(kTSA22EastKeySpotID);
+ break;
+ case kPegasusBiochip:
+ return _vm->getAllHotspots().findHotspotByID(kTSA23WestChipsSpotID);
+ break;
+ }
+
+ return Neighborhood::getItemScreenSpot(item, element);
+}
+
+void FullTSA::dropItemIntoRoom(Item *item, Hotspot *dropSpot) {
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+
+ switch (item->getObjectID()) {
+ case kKeyCard:
+ if (dropSpot->getObjectID() == kTSAGTCardDropSpotID)
+ startExtraSequence(kTSAGTCardSwipe, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kHistoricalLog:
+ if (dropSpot->getObjectID() == kTSA0BNorthHistLogSpotID) {
+ requestExtraSequence(kTSA0BNorthHistLogCloseWithLog, 0, kFilterNoInput);
+ requestExtraSequence(kTSA0BNorthTurnRight, 0, kFilterNoInput);
+ requestExtraSequence(kTSA0BEastZoomIn, kExtraCompletedFlag, kFilterNoInput);
+ requestExtraSequence(kTSA0BComparisonStartup, kExtraCompletedFlag, kFilterNoInput);
+ GameState.setScoringPutLogInReader(true);
+ }
+ break;
+ }
+}
+
+uint FullTSA::getHistoricalLogIndex() {
+ uint index;
+
+ if (GameState.getTSASeenNoradNormal() && GameState.getTSASeenNoradAltered())
+ index = 8;
+ else
+ index = 0;
+
+ if (GameState.getTSASeenMarsNormal() && GameState.getTSASeenMarsAltered())
+ index += 4;
+
+ if (GameState.getTSASeenCaldoriaNormal() && GameState.getTSASeenCaldoriaAltered())
+ index += 2;
+
+ if (GameState.getTSASeenWSCNormal() && GameState.getTSASeenWSCAltered())
+ index += 1;
+
+ return index;
+}
+
+void FullTSA::handleInput(const Input &input, const Hotspot *cursorSpot) {
+ switch (MakeRoomView(GameState.getCurrentRoom(), GameState.getCurrentDirection())) {
+ case MakeRoomView(kTSA0B, kEast):
+ if (GameState.getTSA0BZoomedIn() && !_navMovie.isRunning() && GameState.getT0BMonitorMode() == kMonitorNeutral) {
+ switch (GameState.getTSAState()) {
+ case kTSAPlayerInstalledHistoricalLog:
+ case kTSABossSawHistoricalLog:
+ case kRobotsAtCommandCenter:
+ case kRobotsAtFrontDoor:
+ case kRobotsAtReadyRoom:
+ if (cursorSpot) {
+ switch (cursorSpot->getObjectID()) {
+ case kTSA0BEastCompareNoradSpotID:
+ _sprite1.setCurrentFrameIndex(0);
+ _sprite2.setCurrentFrameIndex(0);
+ _sprite1.show();
+ _sprite2.show();
+ break;
+ case kTSA0BEastCompareMarsSpotID:
+ _sprite1.setCurrentFrameIndex(1);
+ _sprite2.setCurrentFrameIndex(1);
+ _sprite1.show();
+ _sprite2.show();
+ break;
+ case kTSA0BEastCompareCaldoriaSpotID:
+ _sprite1.setCurrentFrameIndex(2);
+ _sprite2.setCurrentFrameIndex(2);
+ _sprite1.show();
+ _sprite2.show();
+ break;
+ case kTSA0BEastCompareWSCSpotID:
+ _sprite1.setCurrentFrameIndex(3);
+ _sprite2.setCurrentFrameIndex(3);
+ _sprite1.show();
+ _sprite2.show();
+ break;
+ default:
+ _sprite1.hide();
+ _sprite2.hide();
+ break;
+ }
+ } else {
+ _sprite1.hide();
+ _sprite2.hide();
+ }
+ break;
+ }
+ }
+ break;
+ case MakeRoomView(kTSA0B, kNorth):
+ if (GameState.getTSA0BZoomedIn() && !_navMovie.isRunning()) {
+ switch (GameState.getTSAState()) {
+ case kRobotsAtCommandCenter:
+ case kRobotsAtFrontDoor:
+ case kRobotsAtReadyRoom:
+ if (cursorSpot) {
+ switch (cursorSpot->getObjectID()) {
+ case kTSA0BNorthRobotsToCommandCenterSpotID:
+ _sprite1.setCurrentFrameIndex(kRedirectionCCRolloverSprite);
+ _sprite1.show();
+ break;
+ case kTSA0BNorthRobotsToReadyRoomSpotID:
+ _sprite1.setCurrentFrameIndex(kRedirectionRRRolloverSprite);
+ _sprite1.show();
+ break;
+ case kTSA0BNorthRobotsToFrontDoorSpotID:
+ _sprite1.setCurrentFrameIndex(kRedirectionFDRolloverSprite);
+ _sprite1.show();
+ break;
+ default:
+ _sprite1.hide();
+ break;
+ }
+ } else {
+ _sprite1.hide();
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ Neighborhood::handleInput(input, cursorSpot);
+}
+
+void FullTSA::releaseSprites() {
+ _sprite1.hide();
+ _sprite2.hide();
+ _sprite3.hide();
+ _sprite1.discardFrames();
+ _sprite2.discardFrames();
+ _sprite3.discardFrames();
+}
+
+bool FullTSA::canSolve() {
+ return GameState.getCurrentRoomAndView() == MakeRoomView(kTSA0B, kNorth) &&
+ GameState.getTSA0BZoomedIn() &&
+ (GameState.getTSAState() == kRobotsAtCommandCenter ||
+ GameState.getTSAState() == kRobotsAtFrontDoor ||
+ GameState.getTSAState() == kRobotsAtReadyRoom);
+}
+
+void FullTSA::doSolve() {
+ // REROUTING ROBOTS
+
+ _sprite1.setCurrentFrameIndex(kRedirectionFDDoorSprite);
+ _sprite1.show();
+ _vm->delayShell(1, 2);
+ _sprite1.hide();
+
+ switch (GameState.getTSAState()) {
+ case kRobotsAtCommandCenter:
+ GameState.setTSAState(kRobotsAtFrontDoor);
+ _sprite2.setCurrentFrameIndex(kRedirectionNewTargetSprite);
+ startExtraSequence(kTSA0BRobotsFromCommandCenterToFrontDoor, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kRobotsAtFrontDoor:
+ // Nothing
+ break;
+ case kRobotsAtReadyRoom:
+ GameState.setTSAState(kRobotsAtFrontDoor);
+ _sprite2.setCurrentFrameIndex(kRedirectionNewTargetSprite);
+ startExtraSequence(kTSA0BRobotsFromReadyRoomToFrontDoor, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ }
+}
+
+void FullTSA::updateCursor(const Common::Point where, const Hotspot *cursorSpot) {
+ if (cursorSpot) {
+ switch (cursorSpot->getObjectID()) {
+ case kTSA0BEastMonitorSpotID:
+ case kTSA0BNorthMonitorSpotID:
+ case kTSA0BWestMonitorSpotID:
+ case kTSA22EastMonitorSpotID:
+ case kTSA23WestMonitorSpotID:
+ _vm->_cursor->setCurrentFrameIndex(1);
+ return;
+ case kTSA0BEastMonitorOutSpotID:
+ case kTSA0BNorthMonitorOutSpotID:
+ case kTSA0BWestMonitorOutSpotID:
+ _vm->_cursor->setCurrentFrameIndex(2);
+ return;
+ }
+ }
+
+ Neighborhood::updateCursor(where, cursorSpot);
+}
+
+Common::String FullTSA::getNavMovieName() {
+ return "Images/TSA/Full TSA.movie";
+}
+
+Common::String FullTSA::getSoundSpotsName() {
+ return "Sounds/TSA/TSA Spots";
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/tsa/fulltsa.h b/engines/pegasus/neighborhood/tsa/fulltsa.h
new file mode 100644
index 0000000000..a646d57e6c
--- /dev/null
+++ b/engines/pegasus/neighborhood/tsa/fulltsa.h
@@ -0,0 +1,159 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_TSA_FULLTSA_H
+#define PEGASUS_NEIGHBORHOOD_TSA_FULLTSA_H
+
+#include "pegasus/neighborhood/neighborhood.h"
+
+namespace Pegasus {
+
+class RipTimer : public IdlerAnimation {
+public:
+ RipTimer(const DisplayElementID id) : IdlerAnimation(id) {}
+ virtual ~RipTimer() {}
+
+ void initImage();
+ void releaseImage();
+
+ void draw(const Common::Rect &);
+
+protected:
+ void timeChanged(const TimeValue);
+
+ CoordType _middle;
+ Surface _timerImage;
+};
+
+// Room IDs.
+
+static const RoomID kTSA00 = 0;
+static const RoomID kTSA22Red = 28;
+static const RoomID kTSA37 = 42;
+
+class FullTSA : public Neighborhood {
+public:
+ FullTSA(InputHandler *, PegasusEngine *);
+ virtual ~FullTSA() {}
+
+ virtual void init();
+
+ void start();
+
+ virtual uint16 getDateResID() const;
+
+ void flushGameState();
+
+ void checkContinuePoint(const RoomID, const DirectionConstant);
+
+ bool canSolve();
+ void doSolve();
+
+ void updateCursor(const Common::Point, const Hotspot *);
+
+protected:
+ enum {
+ kTSAPrivateLogReaderOpenFlag,
+ kTSAPrivateKeyVaultOpenFlag,
+ kTSAPrivateChipVaultOpenFlag,
+ kTSAPrivatePlayingLeftComparisonFlag,
+ kTSAPrivatePlayingRightComparisonFlag,
+ kTSAPrivateSeenRobotWarningFlag,
+ kNumTSAPrivateFlags
+ };
+
+ Common::String getBriefingMovie();
+ Common::String getEnvScanMovie();
+ uint getNumHints();
+ Common::String getHintMovie(uint);
+ void loadAmbientLoops();
+ virtual void clickInHotspot(const Input &, const Hotspot *);
+
+ virtual int16 getStaticCompassAngle(const RoomID, const DirectionConstant);
+ void activateOneHotspot(HotspotInfoTable::Entry &, Hotspot *spot);
+ virtual void activateHotspots();
+ void getExitCompassMove(const ExitTable::Entry &, FaderMoveSpec &);
+ void dropItemIntoRoom(Item *, Hotspot *);
+ void downButton(const Input &);
+ void startDoorOpenMovie(const TimeValue, const TimeValue);
+ TimeValue getViewTime(const RoomID, const DirectionConstant);
+ void findSpotEntry(const RoomID, const DirectionConstant, SpotFlags, SpotTable::Entry &);
+ void turnTo(const DirectionConstant);
+ CanMoveForwardReason canMoveForward(ExitTable::Entry &);
+ CanOpenDoorReason canOpenDoor(DoorTable::Entry &);
+ void bumpIntoWall();
+ void initializeTBPMonitor(const int, const ExtraID);
+ void playTBPMonitor();
+ void getExtraCompassMove(const ExtraTable::Entry &, FaderMoveSpec &);
+ Hotspot *getItemScreenSpot(Item *, DisplayElement *);
+ void openDoor();
+ void turnRight();
+ void turnLeft();
+ void closeDoorOffScreen(const RoomID, const DirectionConstant);
+ void playExtraMovie(const ExtraTable::Entry &, const NotificationFlags, const InputBits interruptionInput);
+ void handleInput(const Input &, const Hotspot *);
+ void arriveAtTSA25Red();
+ void startUpComparisonMonitor();
+ void shutDownComparisonMonitor();
+ void initializeComparisonMonitor(const int, const ExtraID);
+ void playLeftComparison();
+ void playRightComparison();
+ void startRobotGame();
+ void setOffRipAlarm();
+ uint getHistoricalLogIndex();
+ void startUpRobotMonitor();
+ void shutDownRobotMonitor();
+ void pickedUpItem(Item *item);
+ void arriveFromPrehistoric();
+
+ void arriveFromNorad();
+ void arriveFromMars();
+ void arriveFromWSC();
+
+ InputBits getInputFilter();
+ void arriveAt(const RoomID, const DirectionConstant);
+ void initializePegasusButtons(bool);
+ void releaseSprites();
+ void showMainJumpMenu();
+ void arriveAtTSA37();
+ void receiveNotification(Notification *, const NotificationFlags);
+ void checkRobotLocations(const RoomID, const DirectionConstant);
+ void getExtraEntry(const uint32, ExtraTable::Entry &);
+
+ Sprite _sprite1, _sprite2, _sprite3;
+ FuseFunction _utilityFuse;
+ RipTimer _ripTimer;
+
+ FlagsArray<byte, kNumTSAPrivateFlags> _privateFlags;
+
+ Common::String getNavMovieName();
+ Common::String getSoundSpotsName();
+
+ void dieUncreatedInTSA();
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/tsa/tinytsa.cpp b/engines/pegasus/neighborhood/tsa/tinytsa.cpp
new file mode 100644
index 0000000000..4f109620c1
--- /dev/null
+++ b/engines/pegasus/neighborhood/tsa/tinytsa.cpp
@@ -0,0 +1,453 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/energymonitor.h"
+#include "pegasus/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/biochips/aichip.h"
+#include "pegasus/items/biochips/opticalchip.h"
+#include "pegasus/neighborhood/mars/constants.h"
+#include "pegasus/neighborhood/norad/constants.h"
+#include "pegasus/neighborhood/tsa/tinytsa.h"
+#include "pegasus/neighborhood/wsc/wsc.h"
+
+namespace Pegasus {
+
+static const int16 kCompassShift = 30;
+
+static const TimeScale kTinyTSAMovieScale = 600;
+static const TimeScale kTinyTSAFramesPerSecond = 15;
+static const TimeScale kTinyTSAFrameDuration = 40;
+
+// Alternate IDs.
+static const AlternateID kAltTinyTSANormal = 0;
+
+// Hot Spot Activation IDs.
+static const HotSpotActivationID kActivationTinyTSAJumpToNorad = 1;
+static const HotSpotActivationID kActivationTinyTSAJumpToMars = 2;
+static const HotSpotActivationID kActivationTinyTSAJumpToWSC = 3;
+static const HotSpotActivationID kActivationTinyTSAReadyForJumpMenu = 4;
+static const HotSpotActivationID kActivationTinyTSAMainJumpMenu = 5;
+
+// Hot Spot IDs.
+static const HotSpotID kTinyTSA37NorthJumpToNoradSpotID = 5000;
+static const HotSpotID kTinyTSA37NorthCancelNoradSpotID = 5001;
+static const HotSpotID kTinyTSA37NorthJumpToMarsSpotID = 5002;
+static const HotSpotID kTinyTSA37NorthCancelMarsSpotID = 5003;
+static const HotSpotID kTinyTSA37NorthJumpToWSCSpotID = 5004;
+static const HotSpotID kTinyTSA37NorthCancelWSCSpotID = 5005;
+static const HotSpotID kTinyTSA37NorthJumpMenuSpotID = 5006;
+static const HotSpotID kTinyTSA37NorthNoradMenuSpotID = 5007;
+static const HotSpotID kTinyTSA37NorthMarsMenuSpotID = 5008;
+static const HotSpotID kTinyTSA37NorthWSCMenuSpotID = 5009;
+
+// Extra sequence IDs.
+static const ExtraID kTinyTSA37PegasusDepart = 0;
+static const ExtraID kTinyTSA37TimeJumpToPegasus = 1;
+static const ExtraID kTinyTSA37RecallToDownload = 2;
+static const ExtraID kTinyTSA37ExitHilited = 3;
+static const ExtraID kTinyTSA37ExitToHorse = 4;
+static const ExtraID kTinyTSA37JumpMenu000 = 5;
+static const ExtraID kTinyTSA37JumpMenu001 = 6;
+static const ExtraID kTinyTSA37JumpMenu010 = 7;
+static const ExtraID kTinyTSA37JumpMenu011 = 8;
+static const ExtraID kTinyTSA37JumpMenu100 = 9;
+static const ExtraID kTinyTSA37JumpMenu101 = 10;
+static const ExtraID kTinyTSA37JumpMenu110 = 11;
+static const ExtraID kTinyTSA37JumpMenu111 = 12;
+static const ExtraID kTinyTSA37JumpToWSCMenu = 13;
+static const ExtraID kTinyTSA37CancelWSC = 14;
+static const ExtraID kTinyTSA37JumpToWSC = 15;
+static const ExtraID kTinyTSA37WSCToAI5 = 16;
+static const ExtraID kTinyTSA37PegasusAI5 = 17;
+static const ExtraID kTinyTSA37AI5ToWSC = 18;
+static const ExtraID kTinyTSA37WSCToDepart = 19;
+static const ExtraID kTinyTSA37JumpToMarsMenu = 20;
+static const ExtraID kTinyTSA37CancelMars = 21;
+static const ExtraID kTinyTSA37JumpToMars = 22;
+static const ExtraID kTinyTSA37MarsToAI6 = 23;
+static const ExtraID kTinyTSA37PegasusAI6 = 24;
+static const ExtraID kTinyTSA37AI6ToMars = 25;
+static const ExtraID kTinyTSA37MarsToDepart = 26;
+static const ExtraID kTinyTSA37JumpToNoradMenu = 27;
+static const ExtraID kTinyTSA37CancelNorad = 28;
+static const ExtraID kTinyTSA37JumpToNorad = 29;
+static const ExtraID kTinyTSA37NoradToAI7 = 30;
+static const ExtraID kTinyTSA37PegasusAI7 = 31;
+static const ExtraID kTinyTSA37AI7ToNorad = 32;
+static const ExtraID kTinyTSA37NoradToDepart = 33;
+static const ExtraID kTinyTSA37EnvironmentalScan = 34;
+static const ExtraID kTinyTSA37DownloadToMainMenu = 35;
+static const ExtraID kTinyTSA37DownloadToOpMemReview = 36;
+static const ExtraID kTinyTSA37OpMemReviewToMainMenu = 37;
+
+TinyTSA::TinyTSA(InputHandler *nextHandler, PegasusEngine *owner) : Neighborhood(nextHandler, owner, "Tiny TSA", kTinyTSAID) {
+}
+
+void TinyTSA::start() {
+ g_energyMonitor->stopEnergyDraining();
+ Neighborhood::start();
+}
+
+Common::String TinyTSA::getBriefingMovie() {
+ Common::String movieName = Neighborhood::getBriefingMovie();
+
+ if (movieName.empty()) {
+ switch (getCurrentActivation()) {
+ case kActivationTinyTSAJumpToNorad:
+ g_AIChip->showBriefingClicked();
+ startExtraSequenceSync(kTinyTSA37PegasusAI7, kHintInterruption);
+ startExtraSequenceSync(kTinyTSA37AI7ToNorad, kFilterNoInput);
+ g_AIChip->clearClicked();
+ movieName = "";
+ break;
+ case kActivationTinyTSAJumpToMars:
+ g_AIChip->showBriefingClicked();
+ startExtraSequenceSync(kTinyTSA37PegasusAI6, kHintInterruption);
+ startExtraSequenceSync(kTinyTSA37AI6ToMars, kFilterNoInput);
+ g_AIChip->clearClicked();
+ movieName = "";
+ break;
+ case kActivationTinyTSAJumpToWSC:
+ g_AIChip->showBriefingClicked();
+ startExtraSequenceSync(kTinyTSA37PegasusAI5, kHintInterruption);
+ startExtraSequenceSync(kTinyTSA37AI5ToWSC, kFilterNoInput);
+ g_AIChip->clearClicked();
+ movieName = "";
+ break;
+ default:
+ movieName = "Images/AI/TSA/XT04";
+ break;
+ }
+ }
+
+ return movieName;
+}
+
+Common::String TinyTSA::getEnvScanMovie() {
+ Common::String movieName = Neighborhood::getEnvScanMovie();
+
+ if (movieName.empty()) {
+ g_AIChip->showEnvScanClicked();
+ startExtraSequenceSync(kTinyTSA37EnvironmentalScan, kHintInterruption);
+
+ switch (getCurrentActivation()) {
+ case kActivationTinyTSAJumpToNorad:
+ startExtraSequenceSync(kTinyTSA37AI7ToNorad, kFilterNoInput);
+ showExtraView(kTinyTSA37JumpToNoradMenu);
+ break;
+ case kActivationTinyTSAJumpToMars:
+ startExtraSequenceSync(kTinyTSA37AI6ToMars, kFilterNoInput);
+ showExtraView(kTinyTSA37JumpToMarsMenu);
+ break;
+ case kActivationTinyTSAJumpToWSC:
+ startExtraSequenceSync(kTinyTSA37AI5ToWSC, kFilterNoInput);
+ showExtraView(kTinyTSA37JumpToWSCMenu);
+ break;
+ default:
+ showMainJumpMenu();
+ break;
+ }
+
+ g_AIChip->clearClicked();
+ }
+
+ return movieName;
+}
+
+void TinyTSA::loadAmbientLoops() {
+ loadLoopSound1("Sounds/TSA/T01NAE.NEW.22K.AIFF");
+}
+
+int16 TinyTSA::getStaticCompassAngle(const RoomID room, const DirectionConstant dir) {
+ return Neighborhood::getStaticCompassAngle(room, dir) - kCompassShift;
+}
+
+uint16 TinyTSA::getDateResID() const {
+ return kDate2318ID;
+}
+
+InputBits TinyTSA::getInputFilter() {
+ // Can't move forward...
+ return Neighborhood::getInputFilter() & ~(kFilterUpButton | kFilterUpAuto);
+}
+
+void TinyTSA::clickInHotspot(const Input &input, const Hotspot *clickedSpot) {
+ if (clickedSpot) {
+ switch (clickedSpot->getObjectID()) {
+ case kTinyTSA37NorthJumpMenuSpotID:
+ // This hotspot isn't accessable from Tiny TSA
+ warning("jump menu spot");
+ return;
+ case kTinyTSA37NorthJumpToNoradSpotID:
+ GameState.setTSAState(kPlayerOnWayToNorad);
+ requestExtraSequence(kTinyTSA37JumpToNorad, 0, kFilterNoInput);
+ if (!GameState.getBeenToNorad()) {
+ requestExtraSequence(kTinyTSA37NoradToAI7, 0, kFilterNoInput);
+ requestExtraSequence(kTinyTSA37PegasusAI7, 0, kFilterNoInput);
+ requestExtraSequence(kTinyTSA37AI7ToNorad, 0, kFilterNoInput);
+ GameState.setBeenToNorad(true);
+ }
+
+ requestExtraSequence(kTinyTSA37NoradToDepart, 0, kFilterNoInput);
+ requestExtraSequence(kTinyTSA37PegasusDepart, kExtraCompletedFlag, kFilterNoInput);
+ return;
+ case kTinyTSA37NorthJumpToMarsSpotID:
+ GameState.setTSAState(kPlayerOnWayToMars);
+ requestExtraSequence(kTinyTSA37JumpToMars, 0, kFilterNoInput);
+ if (!GameState.getBeenToMars()) {
+ requestExtraSequence(kTinyTSA37MarsToAI6, 0, kFilterNoInput);
+ requestExtraSequence(kTinyTSA37PegasusAI6, 0, kFilterNoInput);
+ requestExtraSequence(kTinyTSA37AI6ToMars, 0, kFilterNoInput);
+ GameState.setBeenToMars(true);
+ }
+
+ requestExtraSequence(kTinyTSA37MarsToDepart, 0, kFilterNoInput);
+ requestExtraSequence(kTinyTSA37PegasusDepart, kExtraCompletedFlag, kFilterNoInput);
+ return;
+ case kTinyTSA37NorthJumpToWSCSpotID:
+ GameState.setTSAState(kPlayerOnWayToWSC);
+ requestExtraSequence(kTinyTSA37JumpToWSC, 0, kFilterNoInput);
+ if (!GameState.getBeenToWSC()) {
+ requestExtraSequence(kTinyTSA37WSCToAI5, 0, kFilterNoInput);
+ requestExtraSequence(kTinyTSA37PegasusAI5, 0, kFilterNoInput);
+ requestExtraSequence(kTinyTSA37AI5ToWSC, 0, kFilterNoInput);
+ GameState.setBeenToWSC(true);
+ }
+
+ requestExtraSequence(kTinyTSA37WSCToDepart, 0, kFilterNoInput);
+ requestExtraSequence(kTinyTSA37PegasusDepart, kExtraCompletedFlag, kFilterNoInput);
+ return;
+ }
+ }
+
+ Neighborhood::clickInHotspot(input, clickedSpot);
+}
+
+void TinyTSA::showMainJumpMenu() {
+ ExtraID jumpMenuView = kTinyTSA37JumpMenu000;
+
+ if (GameState.getNoradFinished())
+ jumpMenuView += 4;
+ if (GameState.getMarsFinished())
+ jumpMenuView += 2;
+ if (GameState.getWSCFinished())
+ jumpMenuView += 1;
+
+ showExtraView(jumpMenuView);
+ setCurrentActivation(kActivationTinyTSAMainJumpMenu);
+}
+
+void TinyTSA::checkContinuePoint(const RoomID, const DirectionConstant) {
+ makeContinuePoint();
+}
+
+void TinyTSA::arriveAt(const RoomID room, const DirectionConstant direction) {
+ Neighborhood::arriveAt(room, direction);
+
+ switch (GameState.getTSAState()) {
+ case kPlayerOnWayToNorad:
+ case kPlayerOnWayToMars:
+ case kPlayerOnWayToWSC:
+ startExtraSequence(kTinyTSA37TimeJumpToPegasus, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kPlayerLockedInPegasus:
+ showMainJumpMenu();
+ break;
+ }
+}
+
+void TinyTSA::receiveNotification(Notification *notification, const NotificationFlags flags) {
+ ExtraID lastExtra = _lastExtra;
+
+ Neighborhood::receiveNotification(notification, flags);
+
+ if ((flags & kExtraCompletedFlag) != 0) {
+ // Only allow input if we're not in the middle of series of queue requests.
+ if (actionQueueEmpty())
+ _interruptionFilter = kFilterAllInput;
+
+ switch (lastExtra) {
+ case kTinyTSA37PegasusDepart:
+ _vm->setLastEnergyValue(kFullEnergy);
+
+ switch (GameState.getTSAState()) {
+ case kPlayerOnWayToNorad:
+ _vm->jumpToNewEnvironment(kNoradAlphaID, kNorad01, kSouth);
+ GameState.setNoradSeenTimeStream(false);
+ GameState.setNoradGassed(true);
+ GameState.setNoradFillingStationOn(false);
+ GameState.setNoradN22MessagePlayed(false);
+ GameState.setNoradPlayedGlobeGame(false);
+ GameState.setNoradBeatRobotWithClaw(false);
+ GameState.setNoradBeatRobotWithDoor(false);
+ GameState.setNoradRetScanGood(false);
+ GameState.setNoradWaitingForLaser(false);
+ GameState.setNoradSubRoomPressure(9);
+ GameState.setNoradSubPrepState(kSubNotPrepped);
+ break;
+ case kPlayerOnWayToMars:
+ _vm->jumpToNewEnvironment(kMarsID, kMars0A, kNorth);
+ GameState.setMarsSeenTimeStream(false);
+ GameState.setMarsHeardUpperPodMessage(false);
+ GameState.setMarsRobotThrownPlayer(false);
+ GameState.setMarsHeardCheckInMessage(false);
+ GameState.setMarsPodAtUpperPlatform(false);
+ GameState.setMarsSeenThermalScan(false);
+ GameState.setMarsArrivedBelow(false);
+ GameState.setMarsSeenRobotAtReactor(false);
+ GameState.setMarsAvoidedReactorRobot(false);
+ GameState.setMarsLockFrozen(false);
+ GameState.setMarsLockBroken(false);
+ GameState.setMarsSecurityDown(false);
+ GameState.setMarsAirlockOpen(false);
+ GameState.setMarsReadyForShuttleTransport(false);
+ GameState.setMarsFinishedCanyonChase(false);
+ GameState.setMarsThreadedMaze(false);
+ break;
+ case kPlayerOnWayToWSC:
+ _vm->jumpToNewEnvironment(kWSCID, kWSC01, kWest);
+ GameState.setWSCSeenTimeStream(false);
+ GameState.setWSCPoisoned(false);
+ GameState.setWSCAnsweredAboutDart(false);
+ GameState.setWSCDartInAnalyzer(false);
+ GameState.setWSCRemovedDart(false);
+ GameState.setWSCAnalyzerOn(false);
+ GameState.setWSCAnalyzedDart(false);
+ GameState.setWSCPickedUpAntidote(false);
+ GameState.setWSCSawMorph(false);
+ GameState.setWSCDesignedAntidote(false);
+ GameState.setWSCOfficeMessagesOpen(false);
+ GameState.setWSCSeenNerd(false);
+ GameState.setWSCHeardPage1(false);
+ GameState.setWSCHeardPage2(false);
+ GameState.setWSCHeardCheckIn(false);
+ GameState.setWSCDidPlasmaDodge(false);
+ GameState.setWSCSeenSinclairLecture(false);
+ GameState.setWSCBeenAtWSC93(false);
+ GameState.setWSCCatwalkDark(false);
+ GameState.setWSCRobotDead(false);
+ GameState.setWSCRobotGone(false);
+ break;
+ };
+ break;
+ case kTinyTSA37TimeJumpToPegasus:
+ if (g_energyMonitor)
+ g_energyMonitor->stopEnergyDraining();
+
+ switch (GameState.getTSAState()) {
+ case kPlayerOnWayToNorad:
+ arriveFromNorad();
+ break;
+ case kPlayerOnWayToMars:
+ arriveFromMars();
+ break;
+ case kPlayerOnWayToWSC:
+ arriveFromWSC();
+ break;
+ default:
+ break;
+ }
+ break;
+ case kTinyTSA37DownloadToOpMemReview:
+ switch (GameState.getTSAState()) {
+ case kPlayerOnWayToNorad:
+ g_opticalChip->playOpMemMovie(kPoseidonSpotID);
+ break;
+ case kPlayerOnWayToMars:
+ g_opticalChip->playOpMemMovie(kAriesSpotID);
+ break;
+ case kPlayerOnWayToWSC:
+ g_opticalChip->playOpMemMovie(kMercurySpotID);
+ break;
+ }
+
+ requestExtraSequence(kTinyTSA37OpMemReviewToMainMenu, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kTinyTSA37DownloadToMainMenu:
+ case kTinyTSA37OpMemReviewToMainMenu:
+ GameState.setTSAState(kPlayerLockedInPegasus);
+ showMainJumpMenu();
+ makeContinuePoint();
+ break;
+ case kTinyTSA37JumpToNoradMenu:
+ setCurrentActivation(kActivationTinyTSAJumpToNorad);
+ break;
+ case kTinyTSA37JumpToMarsMenu:
+ setCurrentActivation(kActivationTinyTSAJumpToMars);
+ break;
+ case kTinyTSA37JumpToWSCMenu:
+ setCurrentActivation(kActivationTinyTSAJumpToWSC);
+ break;
+ case kTinyTSA37CancelNorad:
+ case kTinyTSA37CancelMars:
+ case kTinyTSA37CancelWSC:
+ showMainJumpMenu();
+ break;
+ }
+ }
+
+ g_AIArea->checkMiddleArea();
+}
+
+void TinyTSA::arriveFromNorad() {
+ requestExtraSequence(kTinyTSA37RecallToDownload, 0, kFilterNoInput);
+
+ if (GameState.getNoradFinished() && !GameState.getScoringFinishedNorad()) {
+ GameState.setScoringFinishedNorad();
+ requestExtraSequence(kTinyTSA37DownloadToOpMemReview, kExtraCompletedFlag, kFilterNoInput);
+ } else {
+ requestExtraSequence(kTinyTSA37DownloadToMainMenu, kExtraCompletedFlag, kFilterNoInput);
+ }
+}
+
+void TinyTSA::arriveFromMars() {
+ requestExtraSequence(kTinyTSA37RecallToDownload, 0, kFilterNoInput);
+
+ if (GameState.getMarsFinished() && !GameState.getScoringFinishedMars()) {
+ GameState.setScoringFinishedMars();
+ requestExtraSequence(kTinyTSA37DownloadToOpMemReview, kExtraCompletedFlag, kFilterNoInput);
+ } else {
+ requestExtraSequence(kTinyTSA37DownloadToMainMenu, kExtraCompletedFlag, kFilterNoInput);
+ }
+}
+
+void TinyTSA::arriveFromWSC() {
+ requestExtraSequence(kTinyTSA37RecallToDownload, 0, kFilterNoInput);
+
+ if (GameState.getWSCFinished() && !GameState.getScoringFinishedWSC()) {
+ GameState.setScoringFinishedWSC();
+ requestExtraSequence(kTinyTSA37DownloadToOpMemReview, kExtraCompletedFlag, kFilterNoInput);
+ } else {
+ requestExtraSequence(kTinyTSA37DownloadToMainMenu, kExtraCompletedFlag, kFilterNoInput);
+ }
+}
+
+Common::String TinyTSA::getNavMovieName() {
+ return "Images/TSA/Tiny TSA.movie";
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/tsa/tinytsa.h b/engines/pegasus/neighborhood/tsa/tinytsa.h
new file mode 100644
index 0000000000..2dc234675d
--- /dev/null
+++ b/engines/pegasus/neighborhood/tsa/tinytsa.h
@@ -0,0 +1,71 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_TSA_TINYTSA_H
+#define PEGASUS_NEIGHBORHOOD_TSA_TINYTSA_H
+
+#include "pegasus/neighborhood/neighborhood.h"
+
+namespace Pegasus {
+
+// Room IDs.
+
+static const RoomID kTinyTSA37 = 0;
+
+class TinyTSA : public Neighborhood {
+public:
+ TinyTSA(InputHandler *, PegasusEngine *);
+ virtual ~TinyTSA() {}
+
+ virtual uint16 getDateResID() const;
+
+ void start();
+
+ void checkContinuePoint(const RoomID, const DirectionConstant);
+
+protected:
+ Common::String getBriefingMovie();
+ Common::String getEnvScanMovie();
+ void loadAmbientLoops();
+ virtual void clickInHotspot(const Input &, const Hotspot *);
+
+ virtual int16 getStaticCompassAngle(const RoomID, const DirectionConstant);
+
+ void arriveFromNorad();
+ void arriveFromMars();
+ void arriveFromWSC();
+
+ InputBits getInputFilter();
+ void arriveAt(const RoomID, const DirectionConstant);
+ void showMainJumpMenu();
+ void receiveNotification(Notification *, const NotificationFlags);
+
+ Common::String getNavMovieName();
+ Common::String getSoundSpotsName() { return ""; }
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/turn.cpp b/engines/pegasus/neighborhood/turn.cpp
new file mode 100644
index 0000000000..1157796f55
--- /dev/null
+++ b/engines/pegasus/neighborhood/turn.cpp
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/textconsole.h"
+
+#include "pegasus/neighborhood/turn.h"
+
+namespace Pegasus {
+
+void TurnTable::loadFromStream(Common::SeekableReadStream *stream) {
+ uint32 count = stream->readUint32BE();
+ _entries.resize(count);
+
+ for (uint32 i = 0; i < count; i++) {
+ _entries[i].room = stream->readUint16BE();
+ _entries[i].direction = stream->readByte();
+ _entries[i].turnDirection = stream->readByte();
+ _entries[i].altCode = stream->readByte();
+ stream->readByte(); // alignment
+ _entries[i].endDirection = stream->readByte();
+ stream->readByte(); // alignment
+ debug(0, "Turn[%d]: %d %d %d %d %d", i, _entries[i].room, _entries[i].direction,
+ _entries[i].turnDirection, _entries[i].altCode, _entries[i].endDirection);
+ }
+}
+
+void TurnTable::clear() {
+ _entries.clear();
+}
+
+TurnTable::Entry TurnTable::findEntry(RoomID room, DirectionConstant direction, TurnDirection turnDirection, AlternateID altCode) {
+ for (uint32 i = 0; i < _entries.size(); i++)
+ if (_entries[i].room == room && _entries[i].direction == direction && _entries[i].turnDirection == turnDirection && _entries[i].altCode == altCode)
+ return _entries[i];
+
+ return Entry();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/turn.h b/engines/pegasus/neighborhood/turn.h
new file mode 100644
index 0000000000..329b03eddb
--- /dev/null
+++ b/engines/pegasus/neighborhood/turn.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_TURN_H
+#define PEGASUS_NEIGHBORHOOD_TURN_H
+
+#include "common/array.h"
+#include "common/endian.h"
+
+#include "pegasus/constants.h"
+
+namespace Common {
+ class SeekableReadStream;
+}
+
+namespace Pegasus {
+
+class TurnTable {
+public:
+ TurnTable() {}
+ ~TurnTable() {}
+
+ static uint32 getResTag() { return MKTAG('T', 'u', 'r', 'n'); }
+
+ void loadFromStream(Common::SeekableReadStream *stream);
+ void clear();
+
+ struct Entry {
+ Entry() { endDirection = kNoDirection; }
+ bool isEmpty() { return endDirection == kNoDirection; }
+
+ RoomID room;
+ DirectionConstant direction;
+ TurnDirection turnDirection;
+ AlternateID altCode;
+ DirectionConstant endDirection;
+ };
+
+ Entry findEntry(RoomID room, DirectionConstant direction, TurnDirection turnDirection, AlternateID altCode);
+
+private:
+ Common::Array<Entry> _entries;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/view.cpp b/engines/pegasus/neighborhood/view.cpp
new file mode 100644
index 0000000000..4e46f5374e
--- /dev/null
+++ b/engines/pegasus/neighborhood/view.cpp
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/textconsole.h"
+
+#include "pegasus/neighborhood/view.h"
+
+namespace Pegasus {
+
+void ViewTable::loadFromStream(Common::SeekableReadStream *stream) {
+ uint32 count = stream->readUint32BE();
+ _entries.resize(count);
+
+ for (uint32 i = 0; i < count; i++) {
+ _entries[i].room = stream->readUint16BE();
+ _entries[i].direction = stream->readByte();
+ _entries[i].altCode = stream->readByte();
+ _entries[i].time = stream->readUint32BE();
+ debug(0, "View[%d]: %d %d %d %d", i, _entries[i].room, _entries[i].direction,
+ _entries[i].altCode, _entries[i].time);
+ }
+}
+
+void ViewTable::clear() {
+ _entries.clear();
+}
+
+ViewTable::Entry ViewTable::findEntry(RoomID room, DirectionConstant direction, AlternateID altCode) {
+ for (uint32 i = 0; i < _entries.size(); i++)
+ if (_entries[i].room == room && _entries[i].direction == direction && _entries[i].altCode == altCode)
+ return _entries[i];
+
+ return Entry();
+}
+
+} // End of namespace pegasus
diff --git a/engines/pegasus/neighborhood/view.h b/engines/pegasus/neighborhood/view.h
new file mode 100644
index 0000000000..3397508b61
--- /dev/null
+++ b/engines/pegasus/neighborhood/view.h
@@ -0,0 +1,68 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_VIEW_H
+#define PEGASUS_NEIGHBORHOOD_VIEW_H
+
+#include "common/array.h"
+#include "common/endian.h"
+
+#include "pegasus/constants.h"
+
+namespace Common {
+ class SeekableReadStream;
+}
+
+namespace Pegasus {
+
+class ViewTable {
+public:
+ ViewTable() {}
+ ~ViewTable() {}
+
+ static uint32 getResTag() { return MKTAG('V', 'i', 'e', 'w'); }
+
+ void loadFromStream(Common::SeekableReadStream *stream);
+ void clear();
+
+ struct Entry {
+ Entry() { time = 0xffffffff; }
+ bool isEmpty() { return time == 0xffffffff; }
+
+ RoomID room;
+ DirectionConstant direction;
+ AlternateID altCode;
+ TimeValue time;
+ };
+
+ Entry findEntry(RoomID room, DirectionConstant direction, AlternateID altCode);
+
+private:
+ Common::Array<Entry> _entries;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/wsc/moleculebin.cpp b/engines/pegasus/neighborhood/wsc/moleculebin.cpp
new file mode 100644
index 0000000000..210c0ad313
--- /dev/null
+++ b/engines/pegasus/neighborhood/wsc/moleculebin.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/graphics.h"
+#include "pegasus/neighborhood/wsc/moleculebin.h"
+#include "pegasus/neighborhood/wsc/wsc.h"
+
+namespace Pegasus {
+
+static const CoordType kMoleculeBinWidth = 138;
+static const CoordType kMoleculeBinHeight = 128;
+
+static const CoordType kMoleculeWidth = 66;
+static const CoordType kMoleculeHeight = 40;
+
+static const CoordType kMoleculeBinLeft = kNavAreaLeft + 286;
+static const CoordType kMoleculeBinTop = kNavAreaLeft + 96;
+
+// Layouts:
+
+MoleculeBin::MoleculeBin() : DisplayElement(kNoDisplayElement) {
+ _highlightColor = g_system->getScreenFormat().RGBToColor(0xff, 0xff, 102);
+ _selectedMolecule = -1;
+}
+
+void MoleculeBin::initMoleculeBin() {
+ if (!isDisplaying()) {
+ for (int i = 0; i < 6; i++)
+ _binLayout[i] = i;
+
+ resetBin();
+ _binImages.getImageFromPICTFile("Images/World Science Center/Molecules");
+ setDisplayOrder(kWSCMoleculeBinOrder);
+ setBounds(kMoleculeBinLeft, kMoleculeBinTop, kMoleculeBinLeft + kMoleculeBinWidth,
+ kMoleculeBinTop + kMoleculeBinHeight);
+ startDisplaying();
+ show();
+ }
+}
+
+void MoleculeBin::cleanUpMoleculeBin() {
+ if (isDisplaying()) {
+ stopDisplaying();
+ _binImages.deallocateSurface();
+ }
+}
+
+void MoleculeBin::setBinLayout(const uint32 *layout) {
+ for (int i = 0; i < 6; i++)
+ _binLayout[i] = layout[i];
+}
+
+void MoleculeBin::highlightMolecule(const uint32 whichMolecule) {
+ if (!_moleculeFlags.getFlag(whichMolecule)) {
+ _moleculeFlags.setFlag(whichMolecule, true);
+ triggerRedraw();
+ }
+}
+
+bool MoleculeBin::isMoleculeHighlighted(uint32 whichMolecule) {
+ return _moleculeFlags.getFlag(whichMolecule);
+}
+
+void MoleculeBin::selectMolecule(const int whichMolecule) {
+ if (_selectedMolecule != whichMolecule) {
+ _selectedMolecule = whichMolecule;
+ triggerRedraw();
+ }
+}
+
+void MoleculeBin::resetBin() {
+ _moleculeFlags.clearAllFlags();
+ _selectedMolecule = -1;
+ triggerRedraw();
+}
+
+void MoleculeBin::draw(const Common::Rect &) {
+ Common::Rect r1(0, 0, kMoleculeWidth, kMoleculeHeight);
+ Common::Rect r2 = r1;
+
+ for (int i = 0; i < 6; i++) {
+ r1.moveTo(i * (kMoleculeWidth * 2), 0);
+
+ if (_moleculeFlags.getFlag(_binLayout[i]))
+ r1.translate(kMoleculeWidth, 0);
+
+ r2.moveTo((_binLayout[i] & 1) * (kMoleculeWidth + 2) + _bounds.left + 2,
+ (_binLayout[i] >> 1) * (kMoleculeHeight + 2) + _bounds.top + 2);
+
+ _binImages.copyToCurrentPort(r1, r2);
+ }
+
+ if (_selectedMolecule >= 0) {
+ r2.moveTo((_selectedMolecule & 1) * (kMoleculeWidth + 2) + _bounds.left + 2,
+ (_selectedMolecule >> 1) * (kMoleculeHeight + 2) + _bounds.top + 2);
+
+ Graphics::Surface *screen = ((PegasusEngine *)g_engine)->_gfx->getWorkArea();
+
+ screen->frameRect(r2, _highlightColor);
+ r2.grow(1);
+ screen->frameRect(r2, _highlightColor);
+ }
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/wsc/moleculebin.h b/engines/pegasus/neighborhood/wsc/moleculebin.h
new file mode 100644
index 0000000000..3de4b5ed2a
--- /dev/null
+++ b/engines/pegasus/neighborhood/wsc/moleculebin.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_WSC_MOLECULEBIN_H
+#define PEGASUS_NEIGHBORHOOD_WSC_MOLECULEBIN_H
+
+#include "pegasus/elements.h"
+#include "pegasus/surface.h"
+#include "pegasus/util.h"
+
+namespace Pegasus {
+
+enum {
+ kMolecule1,
+ kMolecule2,
+ kMolecule3,
+ kMolecule4,
+ kMolecule5,
+ kMolecule6
+};
+
+class MoleculeBin : public DisplayElement {
+public:
+ MoleculeBin();
+ virtual ~MoleculeBin() {}
+
+ void initMoleculeBin();
+ void cleanUpMoleculeBin();
+
+ void setBinLayout(const uint32 *);
+
+ void highlightMolecule(const uint32 whichMolecule);
+ void selectMolecule(const int whichMolecule);
+ void resetBin();
+
+ bool isMoleculeHighlighted(uint32);
+
+protected:
+ void draw(const Common::Rect &);
+
+ Surface _binImages;
+ FlagsArray<byte, kMolecule6 + 1> _moleculeFlags;
+ int _selectedMolecule;
+ uint32 _binLayout[6];
+ uint32 _highlightColor;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/wsc/wsc.cpp b/engines/pegasus/neighborhood/wsc/wsc.cpp
new file mode 100644
index 0000000000..50b7774da4
--- /dev/null
+++ b/engines/pegasus/neighborhood/wsc/wsc.cpp
@@ -0,0 +1,2546 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/energymonitor.h"
+#include "pegasus/gamestate.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/biochips/opticalchip.h"
+#include "pegasus/items/biochips/shieldchip.h"
+#include "pegasus/neighborhood/wsc/wsc.h"
+
+namespace Pegasus {
+
+static const CanMoveForwardReason kCantMoveWatchingDiagnosis = kCantMoveLastReason + 1;
+
+static const CanTurnReason kCantTurnWatchingDiagnosis = kCantTurnLastReason + 1;
+static const CanTurnReason kCantTurnWatchingAnalysis = kCantTurnWatchingDiagnosis + 1;
+static const CanTurnReason kCantTurnInMoleculeGame = kCantTurnWatchingAnalysis + 1;
+
+static const TimeScale kMoleculesMovieScale = 600;
+static const TimeValue kMoleculeLoopTime = 4 * kMoleculesMovieScale;
+static const TimeValue kMoleculeFailTime = 2 * kMoleculesMovieScale;
+
+enum {
+ kMoleculeLoop0Time = 0,
+ kMoleculeFail0Time = kMoleculeLoop0Time + kMoleculeLoopTime,
+ kMoleculeLoop1Time = kMoleculeFail0Time + kMoleculeFailTime,
+ kMoleculeFail1Time = kMoleculeLoop1Time + kMoleculeLoopTime,
+ kMoleculeLoop2Time = kMoleculeFail1Time + kMoleculeFailTime,
+ kMoleculeFail2Time = kMoleculeLoop2Time + kMoleculeLoopTime,
+ kMoleculeLoop3Time = kMoleculeFail2Time + kMoleculeFailTime,
+ kMoleculeFail3Time = kMoleculeLoop3Time + kMoleculeLoopTime,
+ kMoleculeLoop4Time = kMoleculeFail3Time + kMoleculeFailTime,
+ kMoleculeFail4Time = kMoleculeLoop4Time + kMoleculeLoopTime,
+ kMoleculeLoop5Time = kMoleculeFail4Time + kMoleculeFailTime,
+ kMoleculeFail5Time = kMoleculeLoop5Time + kMoleculeLoopTime,
+ kMoleculeLoop6Time = kMoleculeFail5Time + kMoleculeFailTime
+};
+
+static const TimeValue s_moleculeLoopTimes[] = {
+ kMoleculeLoop0Time,
+ kMoleculeLoop1Time,
+ kMoleculeLoop2Time,
+ kMoleculeLoop3Time,
+ kMoleculeLoop4Time,
+ kMoleculeLoop5Time,
+ kMoleculeLoop6Time
+};
+
+static const TimeValue s_moleculeFailTimes[] = {
+ kMoleculeFail0Time,
+ kMoleculeFail1Time,
+ kMoleculeFail2Time,
+ kMoleculeFail3Time,
+ kMoleculeFail4Time,
+ kMoleculeFail5Time
+};
+
+static const int16 kAuditoriumAngleOffset = 5;
+
+static const int kPlasmaEnergyWithShield = kMaxJMPEnergy * 10 / 100;
+static const int kPlasmaEnergyNoShield = kMaxJMPEnergy * 20 / 100;
+
+static const int kTimerEventPlasmaHit = 0;
+static const int kTimerEventPlayerGawkingAtRobot = 1;
+static const int kTimerEventPlayerGawkingAtRobot2 = 2;
+
+static const TimeValue kWSCMolecule1In = 0;
+static const TimeValue kWSCMolecule1Out = 937;
+
+static const TimeValue kWSCMolecule2In = 937;
+static const TimeValue kWSCMolecule2Out = 1864;
+
+static const TimeValue kWSCMolecule3In = 1864;
+static const TimeValue kWSCMolecule3Out = 2790;
+
+static const TimeValue kWSCClick1In = 2790;
+static const TimeValue kWSCClick1Out = 2890;
+
+static const TimeValue kWSCClick2In = 2890;
+static const TimeValue kWSCClick2Out = 3059;
+
+static const TimeValue kWSCClick3In = 3059;
+static const TimeValue kWSCClick3Out = 3156;
+
+static const TimeValue kWSCFlashlightClickIn = 3156;
+static const TimeValue kWSCFlashlightClickOut = 3211;
+
+static const TimeValue kWSCBumpIntoWallIn = 3211;
+static const TimeValue kWSCBumpIntoWallOut = 3514;
+
+static const TimeValue kWSCCantTransportIn = 3514;
+static const TimeValue kWSCCantTransportOut = 7791;
+
+static const TimeValue kHernandezNotHomeIn = 7791;
+static const TimeValue kHernandezNotHomeOut = 10199;
+
+static const TimeValue kWashingtonNotHomeIn = 10199;
+static const TimeValue kWashingtonNotHomeOut = 12649;
+
+static const TimeValue kSullivanNotHomeIn = 12649;
+static const TimeValue kSullivanNotHomeOut = 15031;
+
+static const TimeValue kNakamuraNotHomeIn = 15031;
+static const TimeValue kNakamuraNotHomeOut = 17545;
+
+static const TimeValue kGrailisNotHomeIn = 17545;
+static const TimeValue kGrailisNotHomeOut = 19937;
+
+static const TimeValue kTheriaultNotHomeIn = 19937;
+static const TimeValue kTheriaultNotHomeOut = 22395;
+
+static const TimeValue kGlennerNotHomeIn = 22395;
+static const TimeValue kGlennerNotHomeOut = 24770;
+
+static const TimeValue kSinclairNotHomeIn = 24770;
+static const TimeValue kSinclairNotHomeOut = 27328;
+
+static const TimeValue kWSCLabClosedIn = 27328;
+static const TimeValue kWSCLabClosedOut = 28904;
+
+static const TimeValue kSlidingDoorCloseIn = 28904;
+static const TimeValue kSlidingDoorCloseOut = 29295;
+
+static const TimeValue kSlimyDoorCloseIn = 29295;
+static const TimeValue kSlimyDoorCloseOut = 29788;
+
+static const TimeValue kPaging1In = 29788;
+static const TimeValue kPaging1Out = 32501;
+
+static const TimeValue kPaging2In = 32501;
+static const TimeValue kPaging2Out = 34892;
+
+static const TimeValue kCheckInIn = 34892;
+static const TimeValue kCheckInOut = 37789;
+
+static const TimeValue kDrinkAntidoteIn = 37789;
+static const TimeValue kDrinkAntidoteOut = 39725;
+
+static const TimeScale kWSCMovieScale = 600;
+static const TimeScale kWSCFramesPerSecond = 15;
+static const TimeScale kWSCFrameDuration = 40;
+
+// Alternate IDs.
+static const AlternateID kAltWSCNormal = 0;
+static const AlternateID kAltWSCTookMachineGun = 1;
+static const AlternateID kAltWSCW0ZDoorOpen = 2;
+static const AlternateID kAltWSCPeopleAtW19North = 3;
+
+// Room IDs.
+static const RoomID kWSC02 = 1;
+static const RoomID kWSC03 = 4;
+static const RoomID kWSC04 = 5;
+static const RoomID kWSC06 = 6;
+static const RoomID kWSC07 = 7;
+static const RoomID kWSC08 = 8;
+static const RoomID kWSC09 = 9;
+static const RoomID kWSC10 = 10;
+static const RoomID kWSC11 = 11;
+static const RoomID kWSC13 = 12;
+static const RoomID kWSC14 = 13;
+static const RoomID kWSC15 = 14;
+static const RoomID kWSC16 = 15;
+static const RoomID kWSC17 = 16;
+static const RoomID kWSC18 = 17;
+static const RoomID kWSC19 = 18;
+static const RoomID kWSC20 = 19;
+static const RoomID kWSC21 = 20;
+static const RoomID kWSC22 = 21;
+static const RoomID kWSC23 = 22;
+static const RoomID kWSC24 = 23;
+static const RoomID kWSC25 = 24;
+static const RoomID kWSC26 = 25;
+static const RoomID kWSC27 = 26;
+static const RoomID kWSC28 = 27;
+static const RoomID kWSC29 = 28;
+static const RoomID kWSC31 = 29;
+static const RoomID kWSC32 = 30;
+static const RoomID kWSC33 = 31;
+static const RoomID kWSC34 = 32;
+static const RoomID kWSC35 = 33;
+static const RoomID kWSC36 = 34;
+static const RoomID kWSC37 = 35;
+static const RoomID kWSC38 = 36;
+static const RoomID kWSC39 = 37;
+static const RoomID kWSC40 = 38;
+static const RoomID kWSC41 = 39;
+static const RoomID kWSC42 = 40;
+static const RoomID kWSC43 = 41;
+static const RoomID kWSC44 = 42;
+static const RoomID kWSC45 = 43;
+static const RoomID kWSC46 = 44;
+static const RoomID kWSC47 = 45;
+static const RoomID kWSC48 = 46;
+static const RoomID kWSC49 = 47;
+static const RoomID kWSC50 = 48;
+static const RoomID kWSC52 = 49;
+static const RoomID kWSC53 = 50;
+static const RoomID kWSC54 = 51;
+static const RoomID kWSC55 = 52;
+static const RoomID kWSC56 = 53;
+static const RoomID kWSC57 = 54;
+static const RoomID kWSC58 = 55;
+static const RoomID kWSC60 = 56;
+static const RoomID kWSC60East = 57;
+static const RoomID kWSC60North = 58;
+static const RoomID kWSC61 = 59;
+static const RoomID kWSC61South = 60;
+static const RoomID kWSC61West = 61;
+static const RoomID kWSC63 = 63;
+static const RoomID kWSC64 = 64;
+static const RoomID kWSC65 = 65;
+static const RoomID kWSC65Screen = 66;
+static const RoomID kWSC66 = 67;
+static const RoomID kWSC67 = 68;
+static const RoomID kWSC68 = 69;
+static const RoomID kWSC69 = 70;
+static const RoomID kWSC70 = 71;
+static const RoomID kWSC71 = 72;
+static const RoomID kWSC72 = 73;
+static const RoomID kWSC73 = 74;
+static const RoomID kWSC74 = 75;
+static const RoomID kWSC75 = 76;
+static const RoomID kWSC0Z = 77;
+static const RoomID kWSC76 = 78;
+static const RoomID kWSC77 = 79;
+static const RoomID kWSC78 = 80;
+static const RoomID kWSC79 = 81;
+static const RoomID kWSC80 = 82;
+static const RoomID kWSC81 = 83;
+static const RoomID kWSC82 = 84;
+static const RoomID kWSC83 = 85;
+static const RoomID kWSC84 = 86;
+static const RoomID kWSC85 = 87;
+static const RoomID kWSC86 = 88;
+static const RoomID kWSC87 = 89;
+static const RoomID kWSC88 = 90;
+static const RoomID kWSC89 = 91;
+static const RoomID kWSC90 = 92;
+static const RoomID kWSC91 = 93;
+static const RoomID kWSC92 = 94;
+static const RoomID kWSC93 = 95;
+static const RoomID kWSC94 = 96;
+static const RoomID kWSC95 = 97;
+static const RoomID kWSC96 = 98;
+static const RoomID kWSC97 = 99;
+static const RoomID kWSC98 = 100;
+static const RoomID kWSCDeathRoom = 101;
+
+// Hot Spot Activation IDs.
+static const HotSpotActivationID kActivationZoomedInToAnalyzer = 1;
+static const HotSpotActivationID kActivationShotByRobot = 2;
+static const HotSpotActivationID kActivationWarnedAboutPoison = 3;
+static const HotSpotActivationID kActivationMorphScreenOff = 4;
+static const HotSpotActivationID kActivationReadyForMorph = 5;
+static const HotSpotActivationID kActivationMorphLooping = 6;
+static const HotSpotActivationID kActivationMorphInterrupted = 7;
+static const HotSpotActivationID kActivationW03NorthOff = 8;
+static const HotSpotActivationID kActivationW03NorthReadyForInstructions = 9;
+static const HotSpotActivationID kActivationW03NorthSawInstructions = 10;
+static const HotSpotActivationID kActivationW03NorthInGame = 11;
+static const HotSpotActivationID kActivationReadyForSynthesis = 12;
+static const HotSpotActivationID kActivationSynthesizerLooping = 13;
+static const HotSpotActivationID kActivationReadyForMap = 14;
+static const HotSpotActivationID kActivationSinclairOfficeLocked = 15;
+static const HotSpotActivationID kActivationW58SouthDoorLocked = 16;
+static const HotSpotActivationID kActivationW61SouthOff = 17;
+static const HotSpotActivationID kActivationW61SouthOn = 18;
+static const HotSpotActivationID kActivationW61MessagesOff = 19;
+static const HotSpotActivationID kActivationW61MessagesOn = 20;
+static const HotSpotActivationID kActivationWSCRobotHeadOpen = 21;
+static const HotSpotActivationID kActivationRobotTurning = 22;
+static const HotSpotActivationID kActivationRobotDead = 23;
+static const HotSpotActivationID kActivationRobotGone = 24;
+
+// Hot Spot IDs.
+static const HotSpotID kWSCDropDartSpotID = 5000;
+static const HotSpotID kWSCTurnOnAnalyzerSpotID = 5001;
+static const HotSpotID kWSCAnalyzerScreenSpotID = 5002;
+static const HotSpotID kWSCSpinRobotSpotID = 5003;
+static const HotSpotID kWSC01YesSpotID = 5004;
+static const HotSpotID kWSC01NoSpotID = 5005;
+static const HotSpotID kWSC01AcknowledgeWarningSpotID = 5006;
+static const HotSpotID kWSC02SouthMorphSpotID = 5007;
+static const HotSpotID kWSC02SouthMessagesSpotID = 5008;
+static const HotSpotID kWSC02SouthMorphOutSpotID = 5009;
+static const HotSpotID kWSC02ActivateMorphScreenSpotID = 5010;
+static const HotSpotID kWSC02SouthStartMorphSpotID = 5011;
+static const HotSpotID kWSC02SouthInterruptMorphSpotID = 5012;
+static const HotSpotID kWSC02SouthMorphFinishedSpotID = 5013;
+static const HotSpotID kWSC02SouthTakeArgonSpotID = 5014;
+static const HotSpotID kWSC02SouthMessagesOutSpotID = 5015;
+static const HotSpotID kWSC02SouthTakeNitrogenSpotID = 5016;
+static const HotSpotID kWSC02SouthPlayMessagesSpotID = 5017;
+static const HotSpotID kWSC03NorthActivateScreenSpotID = 5018;
+static const HotSpotID kWSC03NorthBuildMoleculeSpotID = 5019;
+static const HotSpotID kWSC03NorthProceedSpotID = 5020;
+static const HotSpotID kWSC03NorthMolecule1SpotID = 5021;
+static const HotSpotID kWSC03NorthMolecule2SpotID = 5022;
+static const HotSpotID kWSC03NorthMolecule3SpotID = 5023;
+static const HotSpotID kWSC03NorthMolecule4SpotID = 5024;
+static const HotSpotID kWSC03NorthMolecule5SpotID = 5025;
+static const HotSpotID kWSC03NorthMolecule6SpotID = 5026;
+static const HotSpotID kWSC03SouthActivateSynthesizerSpotID = 5027;
+static const HotSpotID kWSC03SouthPickUpAntidoteSpotID = 5028;
+static const HotSpotID kWSC07SouthMapSpotID = 5029;
+static const HotSpotID kW42EastUnlockDoorSpotID = 5030;
+static const HotSpotID kW56NorthMapSpotID = 5031;
+static const HotSpotID kW58SouthPryDoorSpotID = 5032;
+static const HotSpotID kWSC60EastSpotID = 5033;
+static const HotSpotID kWSC60NorthSpotID = 5034;
+static const HotSpotID kWSC60EastOutSpotID = 5035;
+static const HotSpotID kWSC60NorthOutSpotID = 5036;
+static const HotSpotID kWSC61EastSpotID = 5037;
+static const HotSpotID kWSC61SouthSpotID = 5038;
+static const HotSpotID kW61SouthMachineGunSpotID = 5039;
+static const HotSpotID kW61SouthDropMachineGunSpotID = 5040;
+static const HotSpotID kWSC61WestSpotID = 5041;
+static const HotSpotID kWSC61SouthOutSpotID = 5042;
+static const HotSpotID kW61SouthActivateSpotID = 5043;
+static const HotSpotID kW61SmartAlloysSpotID = 5044;
+static const HotSpotID kW61MorphingSpotID = 5045;
+static const HotSpotID kW61TimeBendingSpotID = 5046;
+static const HotSpotID kWSC61WestOutSpotID = 5047;
+static const HotSpotID kW61TurnOnMessagesSpotID = 5048;
+static const HotSpotID kW61WhiteMessageSpotID = 5049;
+static const HotSpotID kW61WalchekMessageSpotID = 5050;
+static const HotSpotID kWSC65SouthScreenSpotID = 5051;
+static const HotSpotID kWSC65SouthScreenOutSpotID = 5052;
+static const HotSpotID kW98RetinalChipSpotID = 5053;
+static const HotSpotID kW98MapChipSpotID = 5054;
+static const HotSpotID kW98OpticalChipSpotID = 5055;
+static const HotSpotID kW98DropArgonSpotID = 5056;
+static const HotSpotID kW98GrabCableSpotID = 5057;
+static const HotSpotID kW98OpenRobotSpotID = 5058;
+static const HotSpotID kW98StunGunSpotID = 5059;
+
+// Extra sequence IDs.
+static const ExtraID kWSCArrivalFromTSA = 0;
+static const ExtraID kWSCShotByRobot = 1;
+static const ExtraID kWSCDartScan1 = 2;
+static const ExtraID kWSCDartScan2 = 3;
+static const ExtraID kWSCDartScanNo = 4;
+static const ExtraID kWSCDartScan3 = 5;
+static const ExtraID kWSCAnalyzerPowerUp = 6;
+static const ExtraID kWSCAnalyzerPowerUpWithDart = 7;
+static const ExtraID kWSCDropDartIntoAnalyzer = 8;
+static const ExtraID kWSCAnalyzeDart = 9;
+static const ExtraID kWSCZoomOutFromAnalyzer = 10;
+static const ExtraID kWSCSpinRobot = 11;
+static const ExtraID kWSC02MorphZoomNoArgon = 12;
+static const ExtraID kWSC02MessagesZoomNoNitrogen = 13;
+static const ExtraID kWSC02ZoomOutNoArgon = 14;
+static const ExtraID kWSC02TurnOnMorphScreen = 15;
+static const ExtraID kWSC02DropToMorphExperiment = 16;
+static const ExtraID kWSC02MorphLoop = 17;
+static const ExtraID kWSC02MorphInterruption = 18;
+static const ExtraID kWSC02MorphFinished = 19;
+static const ExtraID kWSC02TurnOffMorphScreen = 20;
+static const ExtraID kWSC02SouthViewNoArgon = 21;
+static const ExtraID kMessagesMovedToOffice = 22;
+static const ExtraID kMessagesOff = 23;
+static const ExtraID kMessagesZoomOutNoNitrogen = 24;
+static const ExtraID kMessagesMovedToOfficeNoNitrogen = 25;
+static const ExtraID kMessagesOffNoNitrogen = 26;
+static const ExtraID kMessagesViewNoNitrogen = 27;
+static const ExtraID kMessagesViewMachineOnNoNitrogen = 28;
+static const ExtraID kW03NorthActivate = 29;
+static const ExtraID kW03NorthGetData = 30;
+static const ExtraID kW03NorthInstructions = 31;
+static const ExtraID kW03NorthPrepMolecule1 = 32;
+static const ExtraID kW03NorthPrepMolecule2 = 33;
+static const ExtraID kW03NorthPrepMolecule3 = 34;
+static const ExtraID kW03NorthFinishSynthesis = 35;
+static const ExtraID kW03SouthCreateAntidote = 36;
+static const ExtraID kW03SouthAntidoteLoop = 37;
+static const ExtraID kW03SouthDeactivate = 38;
+static const ExtraID kW03SouthViewNoAntidote = 39;
+static const ExtraID kWSC07SouthMap = 40;
+static const ExtraID kW17WestPeopleCrossing = 41;
+static const ExtraID kW17WestPeopleCrossingView = 42;
+static const ExtraID kW21SouthPeopleCrossing = 43;
+static const ExtraID kW24SouthPeopleCrossing = 44;
+static const ExtraID kW34EastPeopleCrossing = 45;
+static const ExtraID kW36WestPeopleCrossing = 46;
+static const ExtraID kW38NorthPeopleCrossing = 47;
+static const ExtraID kW46SouthPeopleCrossing = 48;
+static const ExtraID kW49NorthPeopleCrossing = 49;
+static const ExtraID kW49NorthPeopleCrossingView = 50;
+static const ExtraID kWSC56SouthMap = 51;
+static const ExtraID kNerdAtTheDoor1 = 52;
+static const ExtraID kNerdAtTheDoor2 = 53;
+static const ExtraID kW61SouthZoomInNoGun = 54;
+static const ExtraID kW61Brochure = 55;
+static const ExtraID kW61SouthScreenOnWithGun = 56;
+static const ExtraID kW61SouthScreenOffWithGun = 57;
+static const ExtraID kW61SouthSmartAlloysWithGun = 58;
+static const ExtraID kW61SouthMorphingWithGun = 59;
+static const ExtraID kW61SouthTimeBendingWithGun = 60;
+static const ExtraID kW61SouthZoomOutNoGun = 61;
+static const ExtraID kW61SouthScreenOnNoGun = 62;
+static const ExtraID kW61SouthScreenOffNoGun = 63;
+static const ExtraID kW61SouthSmartAlloysNoGun = 64;
+static const ExtraID kW61SouthMorphingNoGun = 65;
+static const ExtraID kW61SouthTimeBendingNoGun = 66;
+static const ExtraID kW61MessagesOn = 67;
+static const ExtraID kW61MessagesOff = 68;
+static const ExtraID kW61WhiteMessage = 69;
+static const ExtraID kW61WalchekMessage = 70;
+static const ExtraID kW61WalchekEasterEgg1 = 71;
+static const ExtraID kW62SouthPlasmaRobotAppears = 72;
+static const ExtraID kW62ZoomToRobot = 73;
+static const ExtraID kW62ZoomOutFromRobot = 74;
+static const ExtraID kW62PlasmaDodgeSurvive = 75;
+static const ExtraID kW62PlasmaDodgeDie = 76;
+static const ExtraID kW65SouthSinclairLecture = 77;
+static const ExtraID kW73WestPeopleCrossing = 78;
+static const ExtraID kW73WestPeopleCrossingView = 79;
+static const ExtraID kW0ZSpottedByWomen = 80;
+static const ExtraID kW95RobotShoots = 81;
+static const ExtraID kW98MorphsToRobot = 82;
+static const ExtraID kW98RobotShoots = 83;
+static const ExtraID kW98RobotShocked = 84;
+static const ExtraID kW98RobotGassed = 85;
+static const ExtraID kW98RobotHeadOpensDark = 86;
+static const ExtraID kW98RobotHead000Dark = 87;
+static const ExtraID kW98RobotHead001Dark = 88;
+static const ExtraID kW98RobotHead010Dark = 89;
+static const ExtraID kW98RobotHead011Dark = 90;
+static const ExtraID kW98RobotHead100Dark = 91;
+static const ExtraID kW98RobotHead101Dark = 92;
+static const ExtraID kW98RobotHead110Dark = 93;
+static const ExtraID kW98RobotHead111Dark = 94;
+static const ExtraID kW98RobotHeadClosesDark = 95;
+static const ExtraID kW98WestViewWithGunDark = 96;
+static const ExtraID kW98WestViewNoGunDark = 97;
+static const ExtraID kW98RobotHeadOpensLight = 98;
+static const ExtraID kW98RobotHead000Light = 99;
+static const ExtraID kW98RobotHead001Light = 100;
+static const ExtraID kW98RobotHead010Light = 101;
+static const ExtraID kW98RobotHead011Light = 102;
+static const ExtraID kW98RobotHead100Light = 103;
+static const ExtraID kW98RobotHead101Light = 104;
+static const ExtraID kW98RobotHead110Light = 105;
+static const ExtraID kW98RobotHead111Light = 106;
+static const ExtraID kW98RobotHeadClosesLight = 107;
+static const ExtraID kW98WestViewWithGunLight = 108;
+static const ExtraID kW98WestViewNoGunLight = 109;
+
+static const CoordType kMoleculesMovieLeft = kNavAreaLeft + 112;
+static const CoordType kMoleculesMovieTop = kNavAreaTop + 40;
+
+WSC::WSC(InputHandler *nextHandler, PegasusEngine *owner) : Neighborhood(nextHandler, owner, "WSC", kWSCID),
+ _moleculesMovie(kNoDisplayElement) {
+ setIsItemTaken(kArgonCanister);
+ setIsItemTaken(kSinclairKey);
+ setIsItemTaken(kNitrogenCanister);
+ setIsItemTaken(kPoisonDart);
+ setIsItemTaken(kAntidote);
+ setIsItemTaken(kMachineGun);
+ setIsItemTaken(kStunGun);
+
+ GameState.setTakenItemID(kArgonPickup, GameState.isTakenItemID(kArgonCanister) &&
+ GameState.isTakenItemID(kSinclairKey));
+}
+
+uint16 WSC::getDateResID() const {
+ return kDate2310ID;
+}
+
+void WSC::init() {
+ Neighborhood::init();
+
+ _cachedZoomSpot = 0;
+ _argonSprite = 0;
+
+ // HACK: Fix the drag item for picking up the Sinclair Key Card
+ HotspotInfoTable::Entry *entry = findHotspotEntry(kWSC02SouthTakeArgonSpotID);
+ entry->hotspotItem = kArgonPickup;
+}
+
+void WSC::flushGameState() {
+ g_energyMonitor->saveCurrentEnergyValue();
+}
+
+void WSC::start() {
+ if (g_energyMonitor) {
+ g_energyMonitor->stopEnergyDraining();
+ g_energyMonitor->restoreLastEnergyValue();
+ _vm->resetEnergyDeathReason();
+ g_energyMonitor->startEnergyDraining();
+ }
+
+ if (!GameState.getWSCDidPlasmaDodge())
+ forceStridingStop(kWSC58, kSouth, kAltWSCNormal);
+
+ Neighborhood::start();
+}
+
+class PryDoorMessage : public AIPlayMessageAction {
+public:
+ PryDoorMessage() : AIPlayMessageAction("Images/AI/WSC/XW59SD3", false) {}
+
+protected:
+ virtual void performAIAction(AIRule *);
+};
+
+void PryDoorMessage::performAIAction(AIRule *rule) {
+ if (((PegasusEngine *)g_engine)->playerHasItemID(kShieldBiochip)
+ && ((PegasusEngine *)g_engine)->getCurrentBiochip()->getObjectID() != kShieldBiochip)
+ AIPlayMessageAction::performAIAction(rule);
+}
+
+void WSC::setUpAIRules() {
+ Neighborhood::setUpAIRules();
+
+ if (g_AIArea) {
+ AIPlayMessageAction *messageAction = new AIPlayMessageAction("Images/AI/WSC/XW1WB1", false);
+ AILastExtraCondition *extraCondition = new AILastExtraCondition(kWSCDartScan1);
+ AIRule *rule = new AIRule(extraCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Globals/XGLOB5A", false);
+ AILocationCondition *locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kWSC06, kNorth));
+ rule = new AIRule(locCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Globals/XGLOB5A", false);
+ locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kWSC10, kWest));
+ rule = new AIRule(locCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Globals/XGLOB5A", false);
+ locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kWSC28, kWest));
+ rule = new AIRule(locCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Globals/XGLOB5A", false);
+ locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kWSC49, kWest));
+ rule = new AIRule(locCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Globals/XGLOB5A", false);
+ locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kWSC65, kSouth));
+ rule = new AIRule(locCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Globals/XGLOB5A", false);
+ locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kWSC73, kSouth));
+ rule = new AIRule(locCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Globals/XGLOB5A", false);
+ locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kWSC79, kWest));
+ rule = new AIRule(locCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/WSC/XW59SD1", false);
+ locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kWSC58, kSouth));
+ rule = new AIRule(locCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ PryDoorMessage *pryDoorMessage = new PryDoorMessage();
+ AIDoorOpenedCondition *doorCondition = new AIDoorOpenedCondition(MakeRoomView(kWSC58, kSouth));
+ rule = new AIRule(doorCondition, pryDoorMessage);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/WSC/XW61E", false);
+ AIHasItemCondition *itemCondition = new AIHasItemCondition(kMachineGun);
+ rule = new AIRule(itemCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+
+ messageAction = new AIPlayMessageAction("Images/AI/Globals/XGLOB1E", false);
+ locCondition = new AILocationCondition(1);
+ locCondition->addLocation(MakeRoomView(kWSC95, kWest));
+ rule = new AIRule(locCondition, messageAction);
+ g_AIArea->addAIRule(rule);
+ }
+}
+
+Common::String WSC::getBriefingMovie() {
+ return "Images/AI/WSC/XWO";
+}
+
+Common::String WSC::getEnvScanMovie() {
+ RoomID room = GameState.getCurrentRoom();
+
+ if (room >= kWSC01 && room <= kWSC04)
+ return "Images/AI/WSC/XWE1";
+ else if (room >= kWSC06 && room <= kWSC58)
+ return "Images/AI/WSC/XWE2";
+ else if (room >= kWSC60 && room <= kWSC61West)
+ return "Images/AI/WSC/XWE3";
+ else if (room >= kWSC64 && room <= kWSC98)
+ return "Images/AI/WSC/XWE4";
+
+ return "Images/AI/WSC/XWE5";
+}
+
+uint WSC::getNumHints() {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kWSC10, kWest):
+ case MakeRoomView(kWSC28, kWest):
+ case MakeRoomView(kWSC49, kWest):
+ case MakeRoomView(kWSC65, kSouth):
+ case MakeRoomView(kWSC75, kSouth):
+ case MakeRoomView(kWSC79, kWest):
+ return 2;
+ case MakeRoomView(kWSC02, kSouth):
+ if (_vm->getEnergyDeathReason() == kDeathDidntStopPoison &&
+ !_privateFlags.getFlag(kWSCPrivateInMoleculeGameFlag) &&
+ !GameState.getWSCDesignedAntidote())
+ return 3;
+ else if (!GameState.getScoringGotNitrogenCanister() ||
+ !GameState.getScoringGotSinclairKey())
+ return 1;
+ break;
+ case MakeRoomView(kWSC03, kNorth):
+ // WORKAROUND: The original game is missing the first two hint movies and
+ // just plays nothing in its stead. We'll just return that we have one
+ // hint available.
+ if (inSynthesizerGame())
+ return 1;
+
+ // fall through
+ case MakeRoomView(kWSC01, kNorth):
+ case MakeRoomView(kWSC01, kSouth):
+ case MakeRoomView(kWSC01, kEast):
+ case MakeRoomView(kWSC01, kWest):
+ case MakeRoomView(kWSC02, kNorth):
+ case MakeRoomView(kWSC02, kEast):
+ case MakeRoomView(kWSC02, kWest):
+ case MakeRoomView(kWSC02Morph, kNorth):
+ case MakeRoomView(kWSC02Morph, kEast):
+ case MakeRoomView(kWSC02Morph, kWest):
+ case MakeRoomView(kWSC02Messages, kNorth):
+ case MakeRoomView(kWSC02Messages, kEast):
+ case MakeRoomView(kWSC02Messages, kWest):
+ case MakeRoomView(kWSC03, kSouth):
+ case MakeRoomView(kWSC03, kEast):
+ case MakeRoomView(kWSC03, kWest):
+ case MakeRoomView(kWSC04, kNorth):
+ case MakeRoomView(kWSC04, kSouth):
+ case MakeRoomView(kWSC04, kEast):
+ case MakeRoomView(kWSC04, kWest):
+ if (_vm->getEnergyDeathReason() == kDeathDidntStopPoison &&
+ !_privateFlags.getFlag(kWSCPrivateInMoleculeGameFlag) &&
+ !GameState.getWSCDesignedAntidote())
+ return 3;
+ break;
+ case MakeRoomView(kWSC02Messages, kSouth):
+ if (_vm->getEnergyDeathReason() == kDeathDidntStopPoison &&
+ !_privateFlags.getFlag(kWSCPrivateInMoleculeGameFlag) &&
+ !GameState.getWSCDesignedAntidote())
+ return 3;
+ else if (!GameState.getScoringGotNitrogenCanister())
+ return 1;
+ break;
+ case MakeRoomView(kWSC02Morph, kSouth):
+ if (_vm->getEnergyDeathReason() == kDeathDidntStopPoison &&
+ !_privateFlags.getFlag(kWSCPrivateInMoleculeGameFlag) &&
+ !GameState.getWSCDesignedAntidote())
+ return 3;
+ else if (!GameState.getScoringGotSinclairKey())
+ return 1;
+ break;
+ case MakeRoomView(kWSC42, kEast):
+ if (!GameState.isCurrentDoorOpen())
+ return 1;
+ break;
+ case MakeRoomView(kWSC58, kSouth):
+ if (GameState.isCurrentDoorOpen()) {
+ if (GameState.getWSCDidPlasmaDodge())
+ return 0;
+ else
+ return 1;
+ } else if (_vm->playerHasItemID(kCrowbar))
+ return 2;
+
+ return 3;
+ case MakeRoomView(kWSC61, kEast):
+ if (!GameState.getScoringSawBrochure())
+ return 1;
+ break;
+ case MakeRoomView(kWSC61, kSouth):
+ if (!GameState.getScoringSawSinclairEntry1() ||
+ !GameState.getScoringSawSinclairEntry2() ||
+ !GameState.getScoringSawSinclairEntry3())
+ return 1;
+ break;
+ case MakeRoomView(kWSC98, kWest):
+ if (getCurrentActivation() == kActivationRobotTurning)
+ return 1;
+ break;
+ }
+
+ return 0;
+}
+
+Common::String WSC::getHintMovie(uint hintNum) {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kWSC10, kWest):
+ case MakeRoomView(kWSC28, kWest):
+ case MakeRoomView(kWSC49, kWest):
+ case MakeRoomView(kWSC65, kSouth):
+ case MakeRoomView(kWSC75, kSouth):
+ case MakeRoomView(kWSC79, kWest):
+ if (hintNum == 1)
+ return "Images/AI/Globals/XGLOB5B";
+
+ return "Images/AI/Globals/XGLOB5C";
+ case MakeRoomView(kWSC02, kSouth):
+ if (_vm->getEnergyDeathReason() == kDeathDidntStopPoison &&
+ !_privateFlags.getFlag(kWSCPrivateInMoleculeGameFlag) &&
+ !GameState.getWSCDesignedAntidote())
+ return Common::String::format("Images/AI/WSC/XWPH%d", hintNum);
+
+ return "Images/AI/Globals/XGLOB1C";
+ case MakeRoomView(kWSC61, kEast):
+ case MakeRoomView(kWSC61, kSouth):
+ return "Images/AI/Globals/XGLOB1C";
+ case MakeRoomView(kWSC42, kEast):
+ if (_vm->playerHasItemID(kSinclairKey))
+ return "Images/AI/Globals/XGLOB1A";
+
+ return "Images/AI/Globals/XGLOB2C";
+ case MakeRoomView(kWSC58, kSouth):
+ switch (hintNum) {
+ case 1:
+ if (GameState.isCurrentDoorOpen()) {
+ // Only get here if we haven't done the plasma dodge game...
+ if (_vm->playerHasItemID(kShieldBiochip))
+ return "Images/AI/Globals/XGLOB1A";
+ else
+ return "Images/AI/Globals/XGLOB3F";
+ } else if (_vm->playerHasItemID(kCrowbar)) {
+ return "Images/AI/Globals/XGLOB1A";
+ }
+
+ return "Images/AI/Globals/XGLOB1B";
+ case 2:
+ // Only get here if the door is still locked...
+ if (_vm->playerHasItemID(kCrowbar))
+ return "Images/AI/WSC/XW59SD2";
+
+ return "Images/AI/Globals/XGLOB2D";
+ case 3:
+ // Only get here if the door is still locked and we don't have the
+ // crowbar...
+ return "Images/AI/WSC/XW59SD2";
+ }
+ break;
+ case MakeRoomView(kWSC03, kNorth):
+ // WORKAROUND: The original game is missing the first two hint movies and
+ // just plays nothing in its stead. We just make it the first hint.
+ if (inSynthesizerGame())
+ return "Images/AI/WSC/XW03NH3";
+
+ // fall through
+ case MakeRoomView(kWSC01, kNorth):
+ case MakeRoomView(kWSC01, kSouth):
+ case MakeRoomView(kWSC01, kEast):
+ case MakeRoomView(kWSC01, kWest):
+ case MakeRoomView(kWSC02, kNorth):
+ case MakeRoomView(kWSC02, kEast):
+ case MakeRoomView(kWSC02, kWest):
+ case MakeRoomView(kWSC02Morph, kNorth):
+ case MakeRoomView(kWSC02Morph, kEast):
+ case MakeRoomView(kWSC02Morph, kWest):
+ case MakeRoomView(kWSC02Messages, kNorth):
+ case MakeRoomView(kWSC02Messages, kEast):
+ case MakeRoomView(kWSC02Messages, kWest):
+ case MakeRoomView(kWSC03, kSouth):
+ case MakeRoomView(kWSC03, kEast):
+ case MakeRoomView(kWSC03, kWest):
+ case MakeRoomView(kWSC04, kNorth):
+ case MakeRoomView(kWSC04, kSouth):
+ case MakeRoomView(kWSC04, kEast):
+ case MakeRoomView(kWSC04, kWest):
+ // analyzer hint
+ return Common::String::format("Images/AI/WSC/XWPH%d", hintNum);
+ case MakeRoomView(kWSC02Messages, kSouth):
+ case MakeRoomView(kWSC02Morph, kSouth):
+ if (_vm->getEnergyDeathReason() == kDeathDidntStopPoison &&
+ !_privateFlags.getFlag(kWSCPrivateInMoleculeGameFlag) &&
+ !GameState.getWSCDesignedAntidote())
+ // analyzer hint
+ return Common::String::format("Images/AI/WSC/XWPH%d", hintNum);
+
+ return "Images/AI/Globals/XGLOB1C";
+ case MakeRoomView(kWSC98, kWest):
+ return "Images/AI/WSC/XW98WH2";
+ }
+
+ return "";
+}
+
+void WSC::prepareForAIHint(const Common::String &movieName) {
+ if (movieName == "Images/AI/WSC/XW98WH2" && isEventTimerRunning())
+ pauseTimer();
+}
+
+void WSC::cleanUpAfterAIHint(const Common::String &movieName) {
+ if (movieName == "Images/AI/WSC/XW98WH2" && isEventTimerRunning())
+ resumeTimer();
+}
+
+bool WSC::okayToJump() {
+ if (GameState.getWSCPoisoned()) {
+ die(kDeathDidntStopPoison);
+ return false;
+ }
+
+ bool result = Neighborhood::okayToJump();
+ if (!result)
+ playSpotSoundSync(kWSCCantTransportIn, kWSCCantTransportOut);
+
+ return result;
+}
+
+TimeValue WSC::getViewTime(const RoomID room, const DirectionConstant direction) {
+ ExtraID viewExtra = 0xffffffff;
+ ExtraTable::Entry extra;
+
+ switch (MakeRoomView(room, direction)) {
+ case MakeRoomView(kWSC01, kWest):
+ if (!GameState.getWSCSeenTimeStream()) {
+ getExtraEntry(kWSCArrivalFromTSA, extra);
+ return extra.movieStart;
+ } else if (GameState.getWSCPoisoned() && !GameState.getWSCAnsweredAboutDart()) {
+ viewExtra = kWSCDartScan1;
+ }
+ break;
+ case MakeRoomView(kWSC02Morph, kSouth):
+ if (GameState.isTakenItemID(kArgonPickup) || GameState.isTakenItemID(kArgonCanister))
+ viewExtra = kWSC02SouthViewNoArgon;
+ break;
+ case MakeRoomView(kWSC02Messages, kSouth):
+ if (GameState.isTakenItemID(kNitrogenCanister)) {
+ if (_privateFlags.getFlag(kWSCPrivateLabMessagesOpenFlag))
+ viewExtra = kMessagesViewMachineOnNoNitrogen;
+ else
+ viewExtra = kMessagesViewNoNitrogen;
+ }
+ break;
+ case MakeRoomView(kWSC03, kSouth):
+ if (_privateFlags.getFlag(kWSCDraggingAntidoteFlag))
+ viewExtra = kW03SouthViewNoAntidote;
+ break;
+ case MakeRoomView(kWSC17, kWest):
+ if (_privateFlags.getFlag(kWSCPrivateNeedPeopleAt17WestFlag))
+ viewExtra = kW17WestPeopleCrossingView;
+ break;
+ case MakeRoomView(kWSC49, kNorth):
+ if (_privateFlags.getFlag(kWSCPrivateNeedPeopleAt49NorthFlag))
+ viewExtra = kW49NorthPeopleCrossingView;
+ break;
+ case MakeRoomView(kWSC73, kWest):
+ if (_privateFlags.getFlag(kWSCPrivateNeedPeopleAt73WestFlag))
+ viewExtra = kW73WestPeopleCrossingView;
+ break;
+ case MakeRoomView(kWSC98, kWest):
+ if (GameState.getWSCRobotDead()) {
+ if (GameState.getWSCRobotGone()) {
+ if (GameState.isTakenItemID(kStunGun)) {
+ if (GameState.getWSCCatwalkDark())
+ viewExtra = kW98WestViewNoGunDark;
+ else
+ viewExtra = kW98WestViewNoGunLight;
+ } else {
+ if (GameState.getWSCCatwalkDark())
+ viewExtra = kW98WestViewWithGunDark;
+ else
+ viewExtra = kW98WestViewWithGunLight;
+ }
+ } else if (_privateFlags.getFlag(kWSCPrivateRobotHeadOpenFlag)) {
+ if (GameState.getWSCCatwalkDark())
+ viewExtra = kW98RobotHead111Dark;
+ else
+ viewExtra = kW98RobotHead111Light;
+
+ if (_privateFlags.getFlag(kWSCPrivateGotRetScanChipFlag))
+ viewExtra -= 1;
+ if (_privateFlags.getFlag(kWSCPrivateGotMapChipFlag))
+ viewExtra -= 2;
+ if (_privateFlags.getFlag(kWSCPrivateGotOpticalChipFlag))
+ viewExtra -= 4;
+ } else if (GameState.getWSCRobotDead()) {
+ // Should only happen on loading a saved game, so it can take its time.
+ if (GameState.getWSCCatwalkDark())
+ viewExtra = kW98RobotShocked;
+ else
+ viewExtra = kW98RobotGassed;
+ }
+ }
+ break;
+ }
+
+ if (viewExtra != 0xffffffff) {
+ getExtraEntry(viewExtra, extra);
+ return extra.movieEnd - 1;
+ }
+
+ return Neighborhood::getViewTime(room, direction);
+}
+
+void WSC::findSpotEntry(const RoomID room, const DirectionConstant direction, SpotFlags flags, SpotTable::Entry &spotEntry) {
+ switch (MakeRoomView(room, direction)) {
+ case MakeRoomView(kWSC58, kSouth):
+ case MakeRoomView(kWSC79, kWest):
+ if ((flags & kSpotOnTurnMask) != 0) {
+ spotEntry.clear();
+ return;
+ }
+ break;
+ }
+
+ Neighborhood::findSpotEntry(room, direction, flags, spotEntry);
+}
+
+void WSC::getZoomEntry(const HotSpotID id, ZoomTable::Entry &zoomEntry) {
+ Neighborhood::getZoomEntry(id, zoomEntry);
+
+ ExtraTable::Entry extra;
+ ExtraID zoomExtra = 0xffffffff;
+
+ switch (id) {
+ case kWSC02SouthMessagesSpotID:
+ if (GameState.isTakenItemID(kNitrogenCanister))
+ zoomExtra = kWSC02MessagesZoomNoNitrogen;
+ break;
+ case kWSC02SouthMessagesOutSpotID:
+ if (GameState.isTakenItemID(kNitrogenCanister))
+ zoomExtra = kMessagesZoomOutNoNitrogen;
+ break;
+ case kWSC02SouthMorphSpotID:
+ if (GameState.isTakenItemID(kArgonCanister))
+ zoomExtra = kWSC02MorphZoomNoArgon;
+ break;
+ case kWSC02SouthMorphOutSpotID:
+ if (GameState.isTakenItemID(kArgonCanister))
+ zoomExtra = kWSC02ZoomOutNoArgon;
+ break;
+ case kWSC61SouthSpotID:
+ if (GameState.isTakenItemID(kMachineGun))
+ zoomExtra = kW61SouthZoomInNoGun;
+ break;
+ case kWSC61SouthOutSpotID:
+ if (GameState.isTakenItemID(kMachineGun))
+ zoomExtra = kW61SouthZoomOutNoGun;
+ break;
+ }
+
+ if (zoomExtra != 0xffffffff) {
+ getExtraEntry(zoomExtra, extra);
+ zoomEntry.movieStart = extra.movieStart;
+ zoomEntry.movieEnd = extra.movieEnd;
+ }
+}
+
+void WSC::getExtraEntry(const uint32 id, ExtraTable::Entry &extraEntry) {
+ switch (id) {
+ case kWSCZoomOutFromAnalyzer:
+ Neighborhood::getExtraEntry(kWSCZoomOutFromAnalyzer, extraEntry);
+ extraEntry.movieEnd = extraEntry.movieStart + 14 * kWSCFrameDuration;
+ break;
+ case kW61WalchekMessage:
+ if (GameState.getEasterEgg())
+ Neighborhood::getExtraEntry(kW61WalchekEasterEgg1, extraEntry);
+ else
+ Neighborhood::getExtraEntry(id, extraEntry);
+ break;
+ case kW61SouthScreenOnWithGun:
+ if (GameState.isTakenItemID(kMachineGun))
+ Neighborhood::getExtraEntry(id, extraEntry);
+ else
+ Neighborhood::getExtraEntry(kW61SouthScreenOnNoGun, extraEntry);
+ break;
+ case kW61SouthSmartAlloysWithGun:
+ if (GameState.isTakenItemID(kMachineGun))
+ Neighborhood::getExtraEntry(id, extraEntry);
+ else
+ Neighborhood::getExtraEntry(kW61SouthSmartAlloysNoGun, extraEntry);
+ break;
+ case kW61SouthMorphingWithGun:
+ if (GameState.isTakenItemID(kMachineGun))
+ Neighborhood::getExtraEntry(id, extraEntry);
+ else
+ Neighborhood::getExtraEntry(kW61SouthMorphingNoGun, extraEntry);
+ break;
+ case kW61SouthTimeBendingWithGun:
+ if (GameState.isTakenItemID(kMachineGun))
+ Neighborhood::getExtraEntry(id, extraEntry);
+ else
+ Neighborhood::getExtraEntry(kW61SouthTimeBendingNoGun, extraEntry);
+ break;
+ case kW98RobotHeadOpensLight:
+ if (GameState.getWSCCatwalkDark())
+ Neighborhood::getExtraEntry(kW98RobotHeadOpensDark, extraEntry);
+ else
+ Neighborhood::getExtraEntry(id, extraEntry);
+ break;
+ default:
+ Neighborhood::getExtraEntry(id, extraEntry);
+ break;
+ }
+}
+
+CanMoveForwardReason WSC::canMoveForward(ExitTable::Entry &entry) {
+ if (GameState.getCurrentRoomAndView() == MakeRoomView(kWSC01, kWest) &&
+ getCurrentActivation() != kActivateHotSpotAlways)
+ return kCantMoveWatchingDiagnosis;
+
+ return Neighborhood::canMoveForward(entry);
+}
+
+// Also add cases here for compound analyzer...
+CanTurnReason WSC::canTurn(TurnDirection turnDirection, DirectionConstant &nextDir) {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kWSC01, kWest):
+ if (getCurrentActivation() != kActivateHotSpotAlways)
+ return kCantTurnWatchingDiagnosis;
+ break;
+ case MakeRoomView(kWSC01, kEast):
+ if (getCurrentActivation() != kActivateHotSpotAlways)
+ return kCantTurnWatchingAnalysis;
+ break;
+ case MakeRoomView(kWSC03, kNorth):
+ if (_privateFlags.getFlag(kWSCPrivateInMoleculeGameFlag))
+ return kCantTurnInMoleculeGame;
+ break;
+ }
+
+ return Neighborhood::canTurn(turnDirection, nextDir);
+}
+
+CanOpenDoorReason WSC::canOpenDoor(DoorTable::Entry &entry) {
+ switch (GameState.getCurrentRoom()) {
+ case kWSC42:
+ if (!_privateFlags.getFlag(kWSCPrivateSinclairOfficeOpenFlag))
+ return kCantOpenLocked;
+ break;
+ case kWSC58:
+ if (!_privateFlags.getFlag(kWSCPrivate58SouthOpenFlag))
+ return kCantOpenLocked;
+ break;
+ }
+
+ return Neighborhood::canOpenDoor(entry);
+}
+
+void WSC::bumpIntoWall() {
+ requestSpotSound(kWSCBumpIntoWallIn, kWSCBumpIntoWallOut, kFilterAllInput, 0);
+ Neighborhood::bumpIntoWall();
+}
+
+void WSC::closeDoorOffScreen(const RoomID room, const DirectionConstant) {
+ Item *keyCard;
+
+ switch (room) {
+ case kWSC58:
+ case kWSC62:
+ case kWSC63:
+ case kWSC64:
+ case kWSC85:
+ case kWSC86:
+ case kWSC88:
+ case kWSC89:
+ playSpotSoundSync(kSlidingDoorCloseIn, kSlidingDoorCloseOut);
+ break;
+ case kWSC81:
+ case kWSC82:
+ case kWSC92:
+ case kWSC93:
+ keyCard = _vm->getAllItems().findItemByID(kKeyCard);
+ if (keyCard->getItemState() == kFlashlightOn && (GameState.getCurrentRoom() == kWSC81 ||
+ GameState.getCurrentRoom() == kWSC93)) {
+ keyCard->setItemState(kFlashlightOff);
+ playSpotSoundSync(kWSCFlashlightClickIn, kWSCFlashlightClickOut);
+ } else if (keyCard->getItemState() == kFlashlightOff && (GameState.getCurrentRoom() == kWSC82 ||
+ GameState.getCurrentRoom() == kWSC92)) {
+ keyCard->setItemState(kFlashlightOn);
+ playSpotSoundSync(kWSCFlashlightClickIn, kWSCFlashlightClickOut);
+ }
+
+ playSpotSoundSync(kSlimyDoorCloseIn, kSlimyDoorCloseOut);
+ break;
+ default:
+ playSpotSoundSync(kSlimyDoorCloseIn, kSlimyDoorCloseOut);
+ break;
+ }
+}
+
+void WSC::cantMoveThatWay(CanMoveForwardReason reason) {
+ if (reason != kCantMoveWatchingDiagnosis)
+ Neighborhood::cantMoveThatWay(reason);
+}
+
+void WSC::cantOpenDoor(CanOpenDoorReason reason) {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kWSC22, kWest):
+ playSpotSoundSync(kNakamuraNotHomeIn, kNakamuraNotHomeOut);
+ break;
+ case MakeRoomView(kWSC23, kEast):
+ playSpotSoundSync(kHernandezNotHomeIn, kHernandezNotHomeOut);
+ break;
+ case MakeRoomView(kWSC26, kWest):
+ playSpotSoundSync(kGrailisNotHomeIn, kGrailisNotHomeOut);
+ break;
+ case MakeRoomView(kWSC27, kEast):
+ playSpotSoundSync(kWashingtonNotHomeIn, kWashingtonNotHomeOut);
+ break;
+ case MakeRoomView(kWSC32, kWest):
+ playSpotSoundSync(kTheriaultNotHomeIn, kTheriaultNotHomeOut);
+ break;
+ case MakeRoomView(kWSC33, kEast):
+ playSpotSoundSync(kSullivanNotHomeIn, kSullivanNotHomeOut);
+ break;
+ case MakeRoomView(kWSC41, kWest):
+ playSpotSoundSync(kGlennerNotHomeIn, kGlennerNotHomeOut);
+ break;
+ case MakeRoomView(kWSC42, kEast):
+ playSpotSoundSync(kSinclairNotHomeIn, kSinclairNotHomeOut);
+ break;
+ case MakeRoomView(kWSC15, kWest):
+ case MakeRoomView(kWSC25, kWest):
+ case MakeRoomView(kWSC33, kWest):
+ case MakeRoomView(kWSC41, kEast):
+ case MakeRoomView(kWSC46, kWest):
+ playSpotSoundSync(kWSCLabClosedIn, kWSCLabClosedOut);
+ break;
+ default:
+ Neighborhood::cantOpenDoor(reason);
+ break;
+ }
+}
+
+void WSC::doorOpened() {
+ Neighborhood::doorOpened();
+
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kWSC42, kEast):
+ _vm->addItemToInventory((InventoryItem *)_vm->getAllItems().findItemByID(kSinclairKey));
+ break;
+ case MakeRoomView(kWSC58, kSouth):
+ GameState.setScoringUsedCrowBarInWSC();
+ _vm->addItemToInventory((InventoryItem *)_vm->getAllItems().findItemByID(kCrowbar));
+ break;
+ case MakeRoomView(kWSC06, kNorth):
+ case MakeRoomView(kWSC79, kWest):
+ die(kDeathArrestedInWSC);
+ break;
+ case MakeRoomView(kWSC60, kWest):
+ if (_vm->itemInInventory(kMachineGun))
+ startExtraSequence(kNerdAtTheDoor2, kExtraCompletedFlag, kFilterNoInput);
+ else if (!GameState.getWSCSeenNerd())
+ startExtraSequence(kNerdAtTheDoor1, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case MakeRoomView(kWSC95, kWest):
+ GameState.setScoringOpenedCatwalk();
+ scheduleEvent(kGawkAtRobotTime, 1, kTimerEventPlayerGawkingAtRobot);
+ break;
+ }
+}
+
+void WSC::turnLeft() {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kWSC17, kNorth):
+ if (!_privateFlags.getFlag(kWSCPrivateSeenPeopleAt17WestFlag) && _vm->getRandomNumber(2) == 0)
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt17WestFlag, true);
+ break;
+ case MakeRoomView(kWSC49, kEast):
+ if (!_privateFlags.getFlag(kWSCPrivateSeenPeopleAt49NorthFlag) && _vm->getRandomNumber(2) == 0)
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt49NorthFlag, true);
+ break;
+ case MakeRoomView(kWSC73, kNorth):
+ if (!_privateFlags.getFlag(kWSCPrivateSeenPeopleAt73WestFlag) && _vm->getRandomNumber(2) == 0)
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt73WestFlag, true);
+ break;
+ case MakeRoomView(kWSC73, kWest):
+ if (!GameState.getWSCBeenAtWSC93())
+ setCurrentAlternate(kAltWSCW0ZDoorOpen);
+ break;
+ case MakeRoomView(kWSC95, kWest):
+ cancelEvent();
+ break;
+ }
+
+ Neighborhood::turnLeft();
+}
+
+void WSC::turnRight() {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kWSC17, kSouth):
+ if (!_privateFlags.getFlag(kWSCPrivateSeenPeopleAt17WestFlag) && _vm->getRandomNumber(2) == 0)
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt17WestFlag, true);
+ break;
+ case MakeRoomView(kWSC49, kWest):
+ if (!_privateFlags.getFlag(kWSCPrivateSeenPeopleAt49NorthFlag) && _vm->getRandomNumber(2) == 0)
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt49NorthFlag, true);
+ break;
+ case MakeRoomView(kWSC73, kSouth):
+ if (!_privateFlags.getFlag(kWSCPrivateSeenPeopleAt73WestFlag) && _vm->getRandomNumber(2) == 0)
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt73WestFlag, true);
+ break;
+ case MakeRoomView(kWSC73, kEast):
+ if (!GameState.getWSCBeenAtWSC93())
+ setCurrentAlternate(kAltWSCW0ZDoorOpen);
+ break;
+ case MakeRoomView(kWSC95, kWest):
+ cancelEvent();
+ break;
+ }
+
+ Neighborhood::turnRight();
+}
+
+void WSC::moveForward() {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kWSC19, kNorth):
+ if (!_privateFlags.getFlag(kWSCPrivateSeenPeopleAt19NorthFlag))
+ setCurrentAlternate(kAltWSCPeopleAtW19North);
+ break;
+ case MakeRoomView(kWSC95, kWest):
+ cancelEvent();
+ break;
+ }
+
+ Neighborhood::moveForward();
+}
+
+void WSC::zoomTo(const Hotspot *hotspot) {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kWSC02Messages, kSouth):
+ if (_privateFlags.getFlag(kWSCPrivateLabMessagesOpenFlag)) {
+ _cachedZoomSpot = hotspot;
+ if (GameState.isTakenItemID(kNitrogenCanister))
+ startExtraSequence(kMessagesOffNoNitrogen, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraSequence(kMessagesOff, kExtraCompletedFlag, kFilterNoInput);
+ return;
+ }
+ break;
+ case MakeRoomView(kWSC61West, kWest):
+ if (GameState.getWSCOfficeMessagesOpen()) {
+ _cachedZoomSpot = hotspot;
+ startExtraSequence(kW61MessagesOff, kExtraCompletedFlag, kFilterNoInput);
+ return;
+ }
+ break;
+ case MakeRoomView(kWSC61South, kSouth):
+ if (_privateFlags.getFlag(kWSCPrivateOfficeLogOpenFlag)) {
+ _cachedZoomSpot = hotspot;
+ if (GameState.isTakenItemID(kMachineGun))
+ startExtraSequence(kW61SouthScreenOffNoGun, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraSequence(kW61SouthScreenOffWithGun, kExtraCompletedFlag, kFilterNoInput);
+ return;
+ }
+ break;
+ }
+
+ Neighborhood::zoomTo(hotspot);
+}
+
+void WSC::startExtraSequence(const ExtraID extraID, const NotificationFlags flags, const InputBits interruptionFilter) {
+ if (extraID == kW61Brochure)
+ loadLoopSound1("");
+
+ Neighborhood::startExtraSequence(extraID, flags, interruptionFilter);
+}
+
+int16 WSC::getStaticCompassAngle(const RoomID room, const DirectionConstant dir) {
+ int16 angle = Neighborhood::getStaticCompassAngle(room, dir);
+
+ switch (room) {
+ case kWSC02Messages:
+ angle -= 50;
+ break;
+ case kWSC02Morph:
+ angle += 5;
+ break;
+ case kWSC60East:
+ angle -= 10;
+ break;
+ case kWSC66:
+ angle -= kAuditoriumAngleOffset;
+ break;
+ case kWSC67:
+ angle += kAuditoriumAngleOffset;
+ break;
+ case kWSC68:
+ angle -= kAuditoriumAngleOffset * 2;
+ break;
+ case kWSC69:
+ angle += kAuditoriumAngleOffset * 2;
+ break;
+ case kWSC70:
+ angle -= kAuditoriumAngleOffset * 3;
+ break;
+ case kWSC71:
+ angle += kAuditoriumAngleOffset * 3;
+ break;
+ case kWSC72:
+ if (dir == kEast || dir == kWest)
+ angle -= kAuditoriumAngleOffset * 4;
+ break;
+ case kWSC73:
+ if (dir == kEast || dir == kWest)
+ angle += kAuditoriumAngleOffset * 4;
+ break;
+ }
+
+ return angle;
+}
+
+void WSC::getExitCompassMove(const ExitTable::Entry &exitEntry, FaderMoveSpec &compassMove) {
+ Neighborhood::getExitCompassMove(exitEntry, compassMove);
+
+ if (exitEntry.room == kWSC65 && exitEntry.direction == kSouth) {
+ compassMove.insertFaderKnot(exitEntry.movieStart + 100 * kWSCFrameDuration, 180);
+ compassMove.insertFaderKnot(exitEntry.movieStart + 108 * kWSCFrameDuration, 150);
+ compassMove.insertFaderKnot(exitEntry.movieEnd, 150);
+ }
+}
+
+void WSC::getExtraCompassMove(const ExtraTable::Entry &entry, FaderMoveSpec &compassMove) {
+ switch (entry.extra) {
+ case kW61Brochure:
+ compassMove.insertFaderKnot(entry.movieStart + 15 * kWSCFrameDuration, 85);
+ compassMove.insertFaderKnot(entry.movieEnd - 15 * kWSCFrameDuration, 85);
+ compassMove.insertFaderKnot(entry.movieEnd, 90);
+ break;
+ default:
+ Neighborhood::getExtraCompassMove(entry, compassMove);
+ break;
+ }
+}
+
+void WSC::loadAmbientLoops() {
+ RoomID room = GameState.getCurrentRoom();
+
+ if (room >= kWSC01 && room <= kWSC04) {
+ if (GameState.getWSCSeenTimeStream())
+ loadLoopSound1("Sounds/World Science Center/WLabLoop.22K.AIFF", 0x100 / 2);
+ } else if ((room >= kWSC06 && room <= kWSC58) || (room >= kWSC62 && room <= kWSC63))
+ loadLoopSound1("Sounds/World Science Center/Organic Walls.22K.AIFF", 0x100 / 2);
+ else if (room >= kWSC82 && room <= kWSC92)
+ loadLoopSound1("Sounds/World Science Center/Creature Feature.22K.AIFF");
+ else if ((room >= kWSC60 && room <= kWSC61West) || (room >= kWSC64 && room <= kWSC81) ||
+ (room >= kWSC93 && room <= kWSC97))
+ loadLoopSound1("Sounds/World Science Center/The Other Side.22K.AIFF", 0x100 / 12);
+ else if (room == kWSC98)
+ loadLoopSound1("Sounds/World Science Center/WCatLoop.22K.AIFF");
+}
+
+void WSC::checkContinuePoint(const RoomID room, const DirectionConstant direction) {
+ switch (MakeRoomView(room, direction)) {
+ case MakeRoomView(kWSC07, kNorth):
+ case MakeRoomView(kWSC11, kSouth):
+ case MakeRoomView(kWSC13, kSouth):
+ case MakeRoomView(kWSC13, kWest):
+ case MakeRoomView(kWSC16, kWest):
+ case MakeRoomView(kWSC17, kEast):
+ case MakeRoomView(kWSC19, kWest):
+ case MakeRoomView(kWSC28, kNorth):
+ case MakeRoomView(kWSC28, kSouth):
+ case MakeRoomView(kWSC28, kEast):
+ case MakeRoomView(kWSC28, kWest):
+ case MakeRoomView(kWSC29, kNorth):
+ case MakeRoomView(kWSC29, kSouth):
+ case MakeRoomView(kWSC29, kEast):
+ case MakeRoomView(kWSC29, kWest):
+ case MakeRoomView(kWSC40, kEast):
+ case MakeRoomView(kWSC42, kEast):
+ case MakeRoomView(kWSC49, kWest):
+ case MakeRoomView(kWSC49, kNorth):
+ case MakeRoomView(kWSC50, kNorth):
+ case MakeRoomView(kWSC55, kEast):
+ case MakeRoomView(kWSC65, kSouth):
+ case MakeRoomView(kWSC65, kEast):
+ case MakeRoomView(kWSC65, kWest):
+ case MakeRoomView(kWSC72, kEast):
+ case MakeRoomView(kWSC72, kSouth):
+ case MakeRoomView(kWSC73, kWest):
+ case MakeRoomView(kWSC73, kSouth):
+ case MakeRoomView(kWSC79, kWest):
+ case MakeRoomView(kWSC81, kEast):
+ case MakeRoomView(kWSC93, kNorth):
+ case MakeRoomView(kWSC95, kWest):
+ makeContinuePoint();
+ break;
+ case MakeRoomView(kWSC58, kSouth):
+ if (!GameState.getWSCDidPlasmaDodge())
+ makeContinuePoint();
+ break;
+ case MakeRoomView(kWSC60, kWest):
+ if (_vm->playerHasItemID(kMachineGun))
+ makeContinuePoint();
+ break;
+ }
+}
+
+void WSC::arriveAt(const RoomID room, const DirectionConstant dir) {
+ switch (MakeRoomView(room, dir)) {
+ case MakeRoomView(kWSC60, kNorth):
+ case MakeRoomView(kWSC60, kSouth):
+ case MakeRoomView(kWSC60, kEast):
+ case MakeRoomView(kWSC60, kWest):
+ case MakeRoomView(kWSC60East, kNorth):
+ case MakeRoomView(kWSC60East, kSouth):
+ case MakeRoomView(kWSC60East, kEast):
+ case MakeRoomView(kWSC60East, kWest):
+ case MakeRoomView(kWSC60North, kNorth):
+ case MakeRoomView(kWSC60North, kSouth):
+ case MakeRoomView(kWSC60North, kEast):
+ case MakeRoomView(kWSC60North, kWest):
+ case MakeRoomView(kWSC61, kNorth):
+ case MakeRoomView(kWSC61, kSouth):
+ case MakeRoomView(kWSC61, kEast):
+ case MakeRoomView(kWSC61, kWest):
+ case MakeRoomView(kWSC61South, kNorth):
+ case MakeRoomView(kWSC61South, kSouth):
+ case MakeRoomView(kWSC61South, kEast):
+ case MakeRoomView(kWSC61South, kWest):
+ case MakeRoomView(kWSC61West, kNorth):
+ case MakeRoomView(kWSC61West, kSouth):
+ case MakeRoomView(kWSC61West, kEast):
+ case MakeRoomView(kWSC61West, kWest):
+ if (GameState.isTakenItemID(kMachineGun))
+ setCurrentAlternate(kAltWSCTookMachineGun);
+ else
+ setCurrentAlternate(kAltWSCNormal);
+ break;
+ case MakeRoomView(kWSC73, kSouth):
+ case MakeRoomView(kWSC75, kNorth):
+ case MakeRoomView(kWSC75, kSouth):
+ case MakeRoomView(kWSC75, kEast):
+ case MakeRoomView(kWSC75, kWest):
+ if (!GameState.getWSCBeenAtWSC93())
+ setCurrentAlternate(kAltWSCW0ZDoorOpen);
+ break;
+ }
+
+ Neighborhood::arriveAt(room, dir);
+
+ switch (MakeRoomView(room, dir)) {
+ case MakeRoomView(kWSC01, kWest):
+ if (!GameState.getWSCSeenTimeStream()) {
+ requestExtraSequence(kWSCArrivalFromTSA, kExtraCompletedFlag, kFilterNoInput);
+ requestExtraSequence(kWSCShotByRobot, 0, kFilterNoInput);
+ requestExtraSequence(kWSCDartScan1, kExtraCompletedFlag, kFilterNoInput);
+ } else if (GameState.getWSCPoisoned() && !GameState.getWSCAnsweredAboutDart()) {
+ setCurrentActivation(kActivationShotByRobot);
+ }
+ break;
+ case MakeRoomView(kWSC01, kEast):
+ if (GameState.getWSCDartInAnalyzer())
+ requestExtraSequence(kWSCDropDartIntoAnalyzer, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case MakeRoomView(kWSC02Morph, kSouth):
+ setCurrentActivation(kActivationMorphScreenOff);
+ break;
+ case MakeRoomView(kWSC03, kNorth):
+ setCurrentActivation(kActivationW03NorthOff);
+ break;
+ case MakeRoomView(kWSC03, kSouth):
+ if (GameState.getWSCDesignedAntidote() && !GameState.getWSCPickedUpAntidote())
+ setCurrentActivation(kActivationReadyForSynthesis);
+ break;
+ case MakeRoomView(kWSC16, kNorth):
+ if (getCurrentAlternate() == kAltWSCPeopleAtW19North) {
+ setCurrentAlternate(kAltWSCNormal);
+ _privateFlags.setFlag(kWSCPrivateSeenPeopleAt19NorthFlag, true);
+ }
+ break;
+ case MakeRoomView(kWSC07, kSouth):
+ case MakeRoomView(kWSC56, kNorth):
+ setCurrentActivation(kActivationReadyForMap);
+ break;
+ case MakeRoomView(kWSC42, kWest):
+ setCurrentAlternate(kAltWSCNormal);
+ break;
+ case MakeRoomView(kWSC42, kEast):
+ _privateFlags.setFlag(kWSCPrivateSinclairOfficeOpenFlag, false);
+ setCurrentActivation(kActivationSinclairOfficeLocked);
+ break;
+ case MakeRoomView(kWSC58, kSouth):
+ setCurrentActivation(kActivationW58SouthDoorLocked);
+ _privateFlags.setFlag(kWSCPrivate58SouthOpenFlag, false);
+ break;
+ case MakeRoomView(kWSC60, kEast):
+ GameState.setScoringEnteredSinclairOffice();
+ break;
+ case MakeRoomView(kWSC61West, kWest):
+ setCurrentActivation(kActivationW61MessagesOff);
+ break;
+ case MakeRoomView(kWSC61South, kSouth):
+ setCurrentActivation(kActivationW61SouthOff);
+ break;
+ case MakeRoomView(kWSC62, kSouth):
+ if (!GameState.getWSCDidPlasmaDodge()) {
+ g_AIArea->lockAIOut();
+ loadLoopSound1("Sounds/World Science Center/Plasma Rock.22K.AIFF");
+ requestExtraSequence(kW62SouthPlasmaRobotAppears, 0, kFilterNoInput);
+ requestExtraSequence(kW62ZoomToRobot, 0, kFilterNoInput);
+ requestExtraSequence(kW62ZoomOutFromRobot, kExtraCompletedFlag, kFilterNoInput);
+ }
+ break;
+ case MakeRoomView(kWSC65Screen, kSouth):
+ if (!GameState.getWSCSeenSinclairLecture()) {
+ GameState.setWSCSeenSinclairLecture(true);
+ startExtraSequence(kW65SouthSinclairLecture, kExtraCompletedFlag, kFilterAllInput);
+ }
+ break;
+ case MakeRoomView(kWSC66, kWest):
+ case MakeRoomView(kWSC67, kEast):
+ if (!GameState.getWSCHeardPage2()) {
+ playSpotSoundSync(kPaging2In, kPaging2Out);
+ GameState.setWSCHeardPage2(true);
+ }
+ case MakeRoomView(kWSC10, kNorth):
+ case MakeRoomView(kWSC26, kSouth):
+ case MakeRoomView(kWSC72, kWest):
+ case MakeRoomView(kWSC83, kWest):
+ if (!GameState.getWSCHeardCheckIn()) {
+ playSpotSoundSync(kCheckInIn, kCheckInOut);
+ GameState.setWSCHeardCheckIn(true);
+ }
+ break;
+ case MakeRoomView(kWSC0Z, kSouth):
+ if (getCurrentAlternate() == kAltWSCW0ZDoorOpen)
+ turnLeft();
+ break;
+ case MakeRoomView(kWSC93, kEast):
+ GameState.setWSCBeenAtWSC93(true);
+ break;
+ case MakeRoomView(kWSC98, kWest):
+ if (!GameState.getWSCRobotDead()) {
+ scheduleEvent(kGawkAtRobotTime2, 1, kTimerEventPlayerGawkingAtRobot2);
+ setCurrentActivation(kActivationRobotTurning);
+ if (g_AIArea)
+ g_AIArea->checkMiddleArea();
+ } else if (!GameState.getWSCRobotGone()) {
+ setCurrentActivation(kActivationRobotDead);
+ } else {
+ if (GameState.getWSCCatwalkDark()) {
+ // Change the gun hot spot...
+ _vm->getAllHotspots().setHotspotRect(kW98StunGunSpotID, Common::Rect(181 + kNavAreaLeft,
+ 99 + kNavAreaTop,372 + kNavAreaLeft, 149 + kNavAreaTop));
+ }
+ setCurrentActivation(kActivationRobotGone);
+ }
+ break;
+ case MakeRoomView(kWSCDeathRoom, kNorth):
+ case MakeRoomView(kWSCDeathRoom, kSouth):
+ case MakeRoomView(kWSCDeathRoom, kEast):
+ case MakeRoomView(kWSCDeathRoom, kWest):
+ die(kDeathArrestedInWSC);
+ break;
+ }
+
+ checkPeopleCrossing();
+ setUpPoison();
+}
+
+void WSC::turnTo(const DirectionConstant direction) {
+ Neighborhood::turnTo(direction);
+
+ switch (MakeRoomView(GameState.getCurrentRoom(), direction)) {
+ case MakeRoomView(kWSC01, kNorth):
+ case MakeRoomView(kWSC01, kSouth):
+ GameState.setWSCAnalyzerOn(false);
+ break;
+ case MakeRoomView(kWSC03, kNorth):
+ setCurrentActivation(kActivationW03NorthOff);
+ break;
+ case MakeRoomView(kWSC03, kSouth):
+ if (GameState.getWSCDesignedAntidote() && !GameState.getWSCPickedUpAntidote())
+ setCurrentActivation(kActivationReadyForSynthesis);
+ break;
+ case MakeRoomView(kWSC07, kSouth):
+ case MakeRoomView(kWSC56, kNorth):
+ setCurrentActivation(kActivationReadyForMap);
+ break;
+ case MakeRoomView(kWSC18, kSouth):
+ case MakeRoomView(kWSC57, kEast):
+ case MakeRoomView(kWSC75, kEast):
+ case MakeRoomView(kWSC90, kSouth):
+ if (!GameState.getWSCHeardCheckIn()) {
+ playSpotSoundSync(kCheckInIn, kCheckInOut);
+ GameState.setWSCHeardCheckIn(true);
+ }
+ break;
+ case MakeRoomView(kWSC56, kSouth):
+ if (!GameState.getWSCHeardPage1()) {
+ playSpotSoundSync(kPaging1In, kPaging1Out);
+ GameState.setWSCHeardPage1(true);
+ }
+ // clone2727 says: This falls through?!??! WTF?
+ case MakeRoomView(kWSC42, kEast):
+ _privateFlags.setFlag(kWSCPrivateSinclairOfficeOpenFlag, false);
+ setCurrentActivation(kActivationSinclairOfficeLocked);
+ break;
+ case MakeRoomView(kWSC58, kSouth):
+ setCurrentActivation(kActivationW58SouthDoorLocked);
+ _privateFlags.setFlag(kWSCPrivate58SouthOpenFlag, false);
+ break;
+ case MakeRoomView(kWSC73, kWest):
+ setCurrentAlternate(kAltWSCNormal);
+ break;
+ case MakeRoomView(kWSC0Z, kEast):
+ if (getCurrentAlternate() == kAltWSCW0ZDoorOpen)
+ startExtraSequence(kW0ZSpottedByWomen, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ }
+
+ checkPeopleCrossing();
+}
+
+void WSC::receiveNotification(Notification *notification, const NotificationFlags flags) {
+ int32 currentEnergy;
+ Item *item;
+
+ if (flags & kExtraCompletedFlag) {
+ _interruptionFilter = kFilterAllInput;
+
+ switch (_lastExtra) {
+ case kWSCArrivalFromTSA:
+ GameState.setWSCSeenTimeStream(true);
+ loadAmbientLoops();
+ break;
+ case kWSCDartScan1:
+ setCurrentActivation(kActivationShotByRobot);
+ GameState.setWSCPoisoned(true);
+ setUpPoison();
+ makeContinuePoint();
+ break;
+ case kWSCDartScan2:
+ _vm->addItemToInventory((InventoryItem *)_vm->getAllItems().findItemByID(kPoisonDart));
+ GameState.setScoringRemovedDart();
+ GameState.setWSCRemovedDart(true);
+ setUpPoison();
+ g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/WSC/XW1WB2", false, kHintInterruption);
+ // Fall through...
+ case kWSCDartScanNo:
+ GameState.setWSCAnsweredAboutDart(true);
+ startExtraSequence(kWSCDartScan3, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kWSCDartScan3:
+ setCurrentActivation(kActivateHotSpotAlways);
+ break;
+ case kWSCAnalyzerPowerUp:
+ case kWSCAnalyzerPowerUpWithDart:
+ GameState.setWSCAnalyzerOn(true);
+ break;
+ case kWSCDropDartIntoAnalyzer:
+ setCurrentActivation(kActivationZoomedInToAnalyzer);
+ break;
+ case kWSCAnalyzeDart:
+ GameState.setWSCAnalyzedDart(true);
+ GameState.setScoringAnalyzedDart();
+ break;
+ case kWSCZoomOutFromAnalyzer:
+ setCurrentActivation(kActivateHotSpotAlways);
+ GameState.setWSCAnalyzerOn(false);
+ GameState.setWSCDartInAnalyzer(false);
+ updateViewFrame();
+ break;
+ case kMessagesMovedToOffice:
+ case kMessagesMovedToOfficeNoNitrogen:
+ _privateFlags.setFlag(kWSCPrivateLabMessagesOpenFlag, true);
+ GameState.setScoringPlayedWithMessages();
+ break;
+ case kMessagesOff:
+ case kMessagesOffNoNitrogen:
+ _privateFlags.setFlag(kWSCPrivateLabMessagesOpenFlag, false);
+ if (_cachedZoomSpot) {
+ zoomTo(_cachedZoomSpot);
+ _cachedZoomSpot = 0;
+ }
+ break;
+ case kWSC02TurnOnMorphScreen:
+ setCurrentActivation(kActivationReadyForMorph);
+ break;
+ case kWSC02DropToMorphExperiment:
+ loopExtraSequence(kWSC02MorphLoop, kExtraCompletedFlag);
+ setCurrentActivation(kActivationMorphLooping);
+ break;
+ case kWSC02MorphLoop:
+ if (_privateFlags.getFlag(kWSCPrivateInterruptedMorphFlag))
+ startExtraSequence(kWSC02MorphInterruption, kExtraCompletedFlag, kFilterNoInput);
+ else
+ scheduleNavCallBack(kExtraCompletedFlag);
+ break;
+ case kWSC02MorphInterruption:
+ setCurrentActivation(kActivationMorphInterrupted);
+ GameState.setScoringSawMorphExperiment();
+ break;
+ case kWSC02TurnOffMorphScreen:
+ setCurrentActivation(kActivationMorphScreenOff);
+ GameState.setWSCSawMorph(true);
+ break;
+ case kW03NorthActivate:
+ if (GameState.getWSCAnalyzedDart() && !GameState.getWSCDesignedAntidote())
+ startExtraSequence(kW03NorthGetData, kExtraCompletedFlag, kFilterNoInput);
+ else
+ setCurrentActivation(kActivateHotSpotAlways);
+ break;
+ case kW03NorthGetData:
+ setCurrentActivation(kActivationW03NorthReadyForInstructions);
+ break;
+ case kW03NorthInstructions:
+ setCurrentActivation(kActivationW03NorthSawInstructions);
+ break;
+ case kW03NorthPrepMolecule1:
+ setUpMoleculeGame();
+ break;
+ case kW03NorthPrepMolecule2:
+ case kW03NorthPrepMolecule3:
+ nextMoleculeGameLevel();
+ break;
+ case kW03NorthFinishSynthesis:
+ setCurrentActivation(kActivateHotSpotAlways);
+ _privateFlags.setFlag(kWSCPrivateInMoleculeGameFlag, false);
+ GameState.setWSCDesignedAntidote(true);
+ GameState.setScoringBuiltAntidote();
+ break;
+ case kW03SouthCreateAntidote:
+ setCurrentActivation(kActivationSynthesizerLooping);
+ loopExtraSequence(kW03SouthAntidoteLoop);
+ break;
+ case kW03SouthDeactivate:
+ setCurrentActivation(kActivateHotSpotAlways);
+ break;
+ case kWSC07SouthMap:
+ case kWSC56SouthMap:
+ setCurrentActivation(kActivateHotSpotAlways);
+ GameState.setScoringSawWSCDirectory();
+ break;
+ case kNerdAtTheDoor1:
+ GameState.setWSCSeenNerd(true);
+ break;
+ case kNerdAtTheDoor2:
+ die(kDeathArrestedInWSC);
+ break;
+ case kW61Brochure:
+ GameState.setScoringSawBrochure();
+ loadAmbientLoops();
+ break;
+ case kW61SouthSmartAlloysWithGun:
+ case kW61SouthSmartAlloysNoGun:
+ GameState.setScoringSawSinclairEntry1();
+ break;
+ case kW61SouthMorphingWithGun:
+ case kW61SouthMorphingNoGun:
+ GameState.setScoringSawSinclairEntry2();
+ break;
+ case kW61SouthTimeBendingWithGun:
+ case kW61SouthTimeBendingNoGun:
+ GameState.setScoringSawSinclairEntry3();
+ break;
+ case kW61MessagesOn:
+ GameState.setWSCOfficeMessagesOpen(true);
+ setCurrentActivation(kActivationW61MessagesOn);
+ break;
+ case kW61MessagesOff:
+ GameState.setWSCOfficeMessagesOpen(false);
+ setCurrentActivation(kActivationW61MessagesOff);
+ if (_cachedZoomSpot) {
+ zoomTo(_cachedZoomSpot);
+ _cachedZoomSpot = 0;
+ }
+ break;
+ case kW61SouthScreenOnWithGun:
+ case kW61SouthScreenOnNoGun:
+ _privateFlags.setFlag(kWSCPrivateOfficeLogOpenFlag, true);
+ setCurrentActivation(kActivationW61SouthOn);
+ break;
+ case kW61SouthScreenOffWithGun:
+ case kW61SouthScreenOffNoGun:
+ _privateFlags.setFlag(kWSCPrivateOfficeLogOpenFlag, false);
+ setCurrentActivation(kActivationW61SouthOff);
+ if (_cachedZoomSpot) {
+ zoomTo(_cachedZoomSpot);
+ _cachedZoomSpot = 0;
+ }
+ break;
+ case kW62ZoomOutFromRobot:
+ // Handle action queue before starting new movie sequences.
+ Neighborhood::receiveNotification(notification, flags);
+ _energyDrainRate = g_energyMonitor->getEnergyDrainRate();
+ g_energyMonitor->setEnergyDrainRate(0);
+ currentEnergy = g_energyMonitor->getCurrentEnergy();
+ _vm->setEnergyDeathReason(kDeathHitByPlasma);
+
+ if (GameState.getShieldOn())
+ currentEnergy -= kPlasmaEnergyWithShield;
+ else
+ currentEnergy -= kPlasmaEnergyNoShield;
+
+ if (currentEnergy <= 0)
+ startExtraSequence(kW62PlasmaDodgeDie, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraSequence(kW62PlasmaDodgeSurvive, kExtraCompletedFlag, kFilterNoInput);
+
+ scheduleEvent(kPlasmaImpactTime, kOneTickPerSecond, kTimerEventPlasmaHit);
+ break;
+ case kW62PlasmaDodgeDie:
+ g_energyMonitor->setEnergyValue(0);
+ break;
+ case kW62PlasmaDodgeSurvive:
+ if (GameState.getShieldOn()) {
+ g_shield->setItemState(kShieldNormal);
+ g_energyMonitor->drainEnergy(kPlasmaEnergyWithShield);
+ } else {
+ g_energyMonitor->drainEnergy(kPlasmaEnergyNoShield);
+ }
+
+ g_energyMonitor->setEnergyDrainRate(_energyDrainRate);
+ g_AIArea->unlockAI();
+ GameState.setScoringFinishedPlasmaDodge();
+ GameState.setWSCDidPlasmaDodge(true);
+ restoreStriding(kWSC58, kSouth, kAltWSCNormal);
+ loadAmbientLoops();
+ break;
+ case kW0ZSpottedByWomen:
+ die(kDeathArrestedInWSC);
+ break;
+ case kW17WestPeopleCrossing:
+ _privateFlags.setFlag(kWSCPrivateSeenPeopleAt17WestFlag, true);
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt17WestFlag, false);
+ break;
+ case kW21SouthPeopleCrossing:
+ _privateFlags.setFlag(kWSCPrivateSeenPeopleAt21SouthFlag, true);
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt21SouthFlag, true);
+ break;
+ case kW24SouthPeopleCrossing:
+ _privateFlags.setFlag(kWSCPrivateSeenPeopleAt24SouthFlag, true);
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt24SouthFlag, true);
+ break;
+ case kW34EastPeopleCrossing:
+ _privateFlags.setFlag(kWSCPrivateSeenPeopleAt34EastFlag, true);
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt34EastFlag, true);
+ break;
+ case kW36WestPeopleCrossing:
+ _privateFlags.setFlag(kWSCPrivateSeenPeopleAt36WestFlag, true);
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt36WestFlag, true);
+ break;
+ case kW38NorthPeopleCrossing:
+ _privateFlags.setFlag(kWSCPrivateSeenPeopleAt38NorthFlag, true);
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt38NorthFlag, true);
+ break;
+ case kW46SouthPeopleCrossing:
+ _privateFlags.setFlag(kWSCPrivateSeenPeopleAt46SouthFlag, true);
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt46SouthFlag, true);
+ break;
+ case kW49NorthPeopleCrossing:
+ _privateFlags.setFlag(kWSCPrivateSeenPeopleAt49NorthFlag, true);
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt49NorthFlag, false);
+ break;
+ case kW73WestPeopleCrossing:
+ _privateFlags.setFlag(kWSCPrivateSeenPeopleAt73WestFlag, true);
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt73WestFlag, false);
+ break;
+ case kW95RobotShoots:
+ case kW98RobotShoots:
+ die(kDeathShotOnCatwalk);
+ break;
+ case kW98MorphsToRobot:
+ if (_argonSprite) {
+ delete _argonSprite; _argonSprite = 0;
+ startExtraSequence(kW98RobotGassed, kExtraCompletedFlag, kFilterNoInput);
+ } else if (_privateFlags.getFlag(kWSCPrivateClickedCatwalkCableFlag)) {
+ startExtraSequence(kW98RobotShocked, kExtraCompletedFlag, kFilterNoInput);
+ } else {
+ startExtraSequence(kW98RobotShoots, kExtraCompletedFlag, kFilterNoInput);
+ }
+ break;
+ case kW98RobotShocked:
+ GameState.setWSCCatwalkDark(true);
+ // Change the gun hot spot...
+ _vm->getAllHotspots().setHotspotRect(kW98StunGunSpotID, Common::Rect(181 + kNavAreaLeft, 99 + kNavAreaTop,
+ 372 + kNavAreaLeft, 149 + kNavAreaTop));
+ setCurrentActivation(kActivationRobotDead);
+ GameState.setWSCRobotDead(true);
+ GameState.setScoringStoppedWSCRobot();
+
+ // Video is not present
+ //g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/WSC/XN59WD", false, kWarningInterruption);
+ break;
+ case kW98RobotGassed:
+ item = (Item *)_vm->getAllItems().findItemByID(kArgonCanister);
+ _vm->addItemToInventory((InventoryItem *)item);
+ setCurrentActivation(kActivationRobotDead);
+ GameState.setWSCRobotDead(true);
+ GameState.setScoringStoppedWSCRobot();
+
+ // Video is not present
+ //g_AIArea->playAIMovie(kRightAreaSignature, "Images/AI/WSC/XN59WD", false, kWarningInterruption);
+ break;
+ case kW98RobotHeadOpensLight:
+ case kW98RobotHeadOpensDark:
+ setCurrentActivation(kActivationWSCRobotHeadOpen);
+ _privateFlags.setFlag(kWSCPrivateRobotHeadOpenFlag, true);
+ break;
+ case kW98RobotHeadClosesDark:
+ case kW98RobotHeadClosesLight:
+ setCurrentActivation(kActivationRobotGone);
+ _privateFlags.setFlag(kWSCPrivateRobotHeadOpenFlag, false);
+ GameState.setWSCRobotGone(true);
+ break;
+ }
+ }
+
+ Neighborhood::receiveNotification(notification, flags);
+ g_AIArea->checkMiddleArea();
+}
+
+void WSC::timerExpired(const uint32 event) {
+ switch (event) {
+ case kTimerEventPlasmaHit:
+ if (GameState.getShieldOn())
+ g_shield->setItemState(kShieldPlasma);
+ break;
+ case kTimerEventPlayerGawkingAtRobot:
+ startExtraSequence(kW95RobotShoots, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kTimerEventPlayerGawkingAtRobot2:
+ startExtraSequence(kW98MorphsToRobot, kExtraCompletedFlag, kFilterAllInput);
+ break;
+ }
+}
+
+void WSC::setUpMoleculeGame() {
+ _privateFlags.setFlag(kWSCPrivateInMoleculeGameFlag, true);
+ setCurrentActivation(kActivationW03NorthInGame);
+ initOneMovie(&_moleculesMovie, "Images/World Science Center/Molecules.movie",
+ kWSCMoleculesMovieOrder, kMoleculesMovieLeft, kMoleculesMovieTop, true);
+ _moleculesMovie.redrawMovieWorld();
+ _moleculeBin.initMoleculeBin();
+ _moleculeGameLevel = 0;
+ nextMoleculeGameLevel();
+}
+
+void WSC::nextMoleculeGameLevel() {
+ _moleculeGameLevel++;
+
+ for (byte i = 0; i < 6; ++i)
+ _levelArray[i] = i;
+
+ _vm->shuffleArray((int32 *)_levelArray, 6);
+ _moleculeBin.setBinLayout(_levelArray);
+ startMoleculeGameLevel();
+}
+
+void WSC::startMoleculeGameLevel() {
+ _moleculeBin.resetBin();
+ _numCorrect = 0;
+ _moleculesMovie.stop();
+ _moleculesMovie.setFlags(0);
+ _moleculesMovie.setSegment(s_moleculeLoopTimes[0], s_moleculeLoopTimes[0] + kMoleculeLoopTime);
+ _moleculesMovie.setTime(s_moleculeLoopTimes[0]);
+ _moleculesMovie.setFlags(kLoopTimeBase);
+ _moleculesMovie.show();
+
+ switch (_moleculeGameLevel) {
+ case 1:
+ playSpotSoundSync(kWSCMolecule1In, kWSCMolecule1Out);
+ break;
+ case 2:
+ playSpotSoundSync(kWSCMolecule2In, kWSCMolecule2Out);
+ break;
+ case 3:
+ playSpotSoundSync(kWSCMolecule3In, kWSCMolecule3Out);
+ break;
+ }
+
+ _moleculesMovie.start();
+}
+
+void WSC::moleculeGameClick(const HotSpotID id) {
+ uint32 molecule = id - kWSC03NorthMolecule1SpotID;
+
+ _moleculeBin.highlightMolecule(molecule);
+ _moleculeBin.selectMolecule(molecule);
+
+ if (molecule == _levelArray[_numCorrect]) {
+ playSpotSoundSync(kWSCClick2In, kWSCClick2Out);
+ _numCorrect++;
+ _moleculesMovie.stop();
+ _moleculesMovie.setFlags(0);
+
+ TimeValue time = _moleculesMovie.getTime();
+ _moleculesMovie.setSegment(s_moleculeLoopTimes[_numCorrect], s_moleculeLoopTimes[_numCorrect] + kMoleculeLoopTime);
+ _moleculesMovie.setTime(s_moleculeLoopTimes[_numCorrect] + time - s_moleculeLoopTimes[_numCorrect - 1]);
+
+ if (_numCorrect == 6) {
+ _moleculesMovie.start();
+
+ while (_moleculesMovie.isRunning()) {
+ _vm->checkCallBacks();
+ _vm->refreshDisplay();
+ _vm->_system->delayMillis(10);
+ }
+
+ _moleculesMovie.stop();
+ _moleculesMovie.hide();
+
+ switch (_moleculeGameLevel) {
+ case 1:
+ startExtraSequence(kW03NorthPrepMolecule2, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case 2:
+ startExtraSequence(kW03NorthPrepMolecule3, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case 3:
+ _moleculesMovie.releaseMovie();
+ _moleculeBin.cleanUpMoleculeBin();
+ requestExtraSequence(kW03NorthFinishSynthesis, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ }
+ } else {
+ _moleculesMovie.setFlags(kLoopTimeBase);
+ _moleculesMovie.start();
+ }
+ } else {
+ // FAIL
+ playSpotSoundSync(kWSCClick3In, kWSCClick3Out);
+
+ _moleculesMovie.stop();
+ _moleculesMovie.setFlags(0);
+ _moleculesMovie.start();
+
+ while (_moleculesMovie.isRunning()) {
+ _vm->checkCallBacks();
+ _vm->refreshDisplay();
+ _vm->_system->delayMillis(10);
+ }
+
+ _moleculesMovie.stop();
+ _moleculesMovie.setFlags(0);
+ _moleculesMovie.setSegment(s_moleculeFailTimes[_numCorrect], s_moleculeFailTimes[_numCorrect] + kMoleculeFailTime);
+ _moleculesMovie.setTime(s_moleculeFailTimes[_numCorrect]);
+ _moleculesMovie.start();
+
+
+ while (_moleculesMovie.isRunning()) {
+ _vm->checkCallBacks();
+ _vm->refreshDisplay();
+ _vm->_system->delayMillis(10);
+ }
+
+ _moleculesMovie.stop();
+ startMoleculeGameLevel();
+ }
+}
+
+void WSC::activateOneHotspot(HotspotInfoTable::Entry &entry, Hotspot *hotspot) {
+ Neighborhood::activateOneHotspot(entry, hotspot);
+
+ Item *argonCanister;
+
+ switch (hotspot->getObjectID()) {
+ case kWSCTurnOnAnalyzerSpotID:
+ if (GameState.getWSCAnalyzerOn())
+ hotspot->setInactive();
+ break;
+ case kWSC02SouthTakeArgonSpotID:
+ if (!GameState.getWSCSawMorph() || GameState.isTakenItemID(kArgonCanister))
+ hotspot->setInactive();
+ break;
+ case kWSC02ActivateMorphScreenSpotID:
+ if (GameState.getWSCSawMorph())
+ hotspot->setInactive();
+ break;
+ case kWSC03NorthMolecule1SpotID:
+ case kWSC03NorthMolecule2SpotID:
+ case kWSC03NorthMolecule3SpotID:
+ case kWSC03NorthMolecule4SpotID:
+ case kWSC03NorthMolecule5SpotID:
+ case kWSC03NorthMolecule6SpotID:
+ if (_moleculeBin.isMoleculeHighlighted(hotspot->getObjectID() - kWSC03NorthMolecule1SpotID))
+ hotspot->setInactive();
+ break;
+ case kWSC03SouthPickUpAntidoteSpotID:
+ if (getCurrentActivation() == kActivationSynthesizerLooping)
+ hotspot->setActive();
+ break;
+ case kW98DropArgonSpotID:
+ argonCanister = _vm->getAllItems().findItemByID(kArgonCanister);
+ if (argonCanister->getItemState() != kArgonFull)
+ hotspot->setInactive();
+ break;
+ }
+}
+
+void WSC::activateHotspots() {
+ Neighborhood::activateHotspots();
+
+ if (GameState.getCurrentRoomAndView() == MakeRoomView(kWSC98, kWest) && _privateFlags.getFlag(kWSCPrivateRobotHeadOpenFlag)) {
+ if (_privateFlags.getFlag(kWSCPrivateGotRetScanChipFlag))
+ _vm->getAllHotspots().deactivateOneHotspot(kW98RetinalChipSpotID);
+ else
+ _vm->getAllHotspots().activateOneHotspot(kW98RetinalChipSpotID);
+
+ if (_privateFlags.getFlag(kWSCPrivateGotMapChipFlag))
+ _vm->getAllHotspots().deactivateOneHotspot(kW98MapChipSpotID);
+ else
+ _vm->getAllHotspots().activateOneHotspot(kW98MapChipSpotID);
+
+ if (_privateFlags.getFlag(kWSCPrivateGotOpticalChipFlag))
+ _vm->getAllHotspots().deactivateOneHotspot(kW98OpticalChipSpotID);
+ else
+ _vm->getAllHotspots().activateOneHotspot(kW98OpticalChipSpotID);
+ }
+}
+
+void WSC::clickInHotspot(const Input &input, const Hotspot *clickedSpot) {
+ if (JMPPPInput::isEasterEggModifierInput(input))
+ GameState.setEasterEgg(true);
+
+ if (clickedSpot) {
+ switch (clickedSpot->getObjectID()) {
+ case kWSCAnalyzerScreenSpotID:
+ requestExtraSequence(kWSCAnalyzeDart, kExtraCompletedFlag, kFilterNoInput);
+ requestExtraSequence(kWSCZoomOutFromAnalyzer, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kWSC02SouthPlayMessagesSpotID:
+ if (GameState.isTakenItemID(kNitrogenCanister)) {
+ if (_lastExtra == (uint32)kMessagesMovedToOfficeNoNitrogen)
+ startExtraSequence(kMessagesOffNoNitrogen, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraSequence(kMessagesMovedToOfficeNoNitrogen, kExtraCompletedFlag, kFilterNoInput);
+ } else {
+ if (_lastExtra == (uint32)kMessagesMovedToOffice)
+ startExtraSequence(kMessagesOff, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraSequence(kMessagesMovedToOffice, kExtraCompletedFlag, kFilterNoInput);
+ }
+ break;
+ case kWSC02SouthInterruptMorphSpotID:
+ _privateFlags.setFlag(kWSCPrivateInterruptedMorphFlag, true);
+ break;
+ case kWSC02SouthMorphFinishedSpotID:
+ requestExtraSequence(kWSC02MorphFinished, 0, kFilterNoInput);
+ requestExtraSequence(kWSC02TurnOffMorphScreen, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case kWSC03NorthMolecule1SpotID:
+ case kWSC03NorthMolecule2SpotID:
+ case kWSC03NorthMolecule3SpotID:
+ case kWSC03NorthMolecule4SpotID:
+ case kWSC03NorthMolecule5SpotID:
+ case kWSC03NorthMolecule6SpotID:
+ moleculeGameClick(clickedSpot->getObjectID());
+ break;
+ case kW98GrabCableSpotID:
+ if (isEventTimerRunning()) {
+ cancelEvent();
+ startExtraSequence(kW98MorphsToRobot, kExtraCompletedFlag, kFilterAllInput);
+ }
+
+ _privateFlags.setFlag(kWSCPrivateClickedCatwalkCableFlag, true);
+ break;
+ default:
+ Neighborhood::clickInHotspot(input, clickedSpot);
+ break;
+ }
+ } else {
+ Neighborhood::clickInHotspot(input, clickedSpot);
+ }
+
+ GameState.setEasterEgg(false);
+}
+
+void WSC::dropItemIntoRoom(Item *item, Hotspot *dropSpot) {
+ CoordType h, v;
+
+ switch (item->getObjectID()) {
+ case kPoisonDart:
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ GameState.setWSCDartInAnalyzer(true);
+ if (dropSpot && dropSpot->getObjectID() == kWSCDropDartSpotID) {
+ if (!GameState.getWSCAnalyzerOn())
+ requestExtraSequence(kWSCAnalyzerPowerUpWithDart, kExtraCompletedFlag, kFilterNoInput);
+
+ requestExtraSequence(kWSCDropDartIntoAnalyzer, kExtraCompletedFlag, kFilterNoInput);
+ }
+ break;
+ case kAntidote:
+ _privateFlags.setFlag(kWSCDraggingAntidoteFlag, false);
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ loopExtraSequence(kW03SouthAntidoteLoop);
+ break;
+ case kSinclairKey:
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ _privateFlags.setFlag(kWSCPrivateSinclairOfficeOpenFlag, true);
+ openDoor();
+ break;
+ case kCrowbar:
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ _privateFlags.setFlag(kWSCPrivate58SouthOpenFlag, true);
+ openDoor();
+ break;
+ case kMachineGun:
+ setCurrentAlternate(kAltWSCNormal);
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ break;
+ case kArgonCanister:
+ item->setItemState(kArgonEmpty);
+ _argonSprite = item->getDragSprite(0);
+ _argonSprite->setCurrentFrameIndex(1);
+ _argonSprite->setDisplayOrder(kDragSpriteOrder);
+ dropSpot->getCenter(h, v);
+ _argonSprite->centerElementAt(h, v);
+ _argonSprite->startDisplaying();
+ _argonSprite->show();
+
+ if (isEventTimerRunning()) {
+ cancelEvent();
+ startExtraSequence(kW98MorphsToRobot, kExtraCompletedFlag, kFilterAllInput);
+ }
+ break;
+ case kRetinalScanBiochip:
+ _privateFlags.setFlag(kWSCPrivateGotRetScanChipFlag, false);
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ break;
+ case kMapBiochip:
+ _privateFlags.setFlag(kWSCPrivateGotMapChipFlag, false);
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ break;
+ case kOpticalBiochip:
+ _privateFlags.setFlag(kWSCPrivateGotOpticalChipFlag, false);
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ break;
+ default:
+ Neighborhood::dropItemIntoRoom(item, dropSpot);
+ break;
+ }
+}
+
+void WSC::takeItemFromRoom(Item *item) {
+ switch (item->getObjectID()) {
+ case kAntidote:
+ _privateFlags.setFlag(kWSCDraggingAntidoteFlag, true);
+ Neighborhood::takeItemFromRoom(item);
+ break;
+ case kMachineGun:
+ setCurrentAlternate(kAltWSCTookMachineGun);
+ Neighborhood::takeItemFromRoom(item);
+ break;
+ case kRetinalScanBiochip:
+ _privateFlags.setFlag(kWSCPrivateGotRetScanChipFlag, true);
+ Neighborhood::takeItemFromRoom(item);
+ break;
+ case kMapBiochip:
+ _privateFlags.setFlag(kWSCPrivateGotMapChipFlag, true);
+ Neighborhood::takeItemFromRoom(item);
+ break;
+ case kOpticalBiochip:
+ _privateFlags.setFlag(kWSCPrivateGotOpticalChipFlag, true);
+ Neighborhood::takeItemFromRoom(item);
+ break;
+ default:
+ Neighborhood::takeItemFromRoom(item);
+ break;
+ }
+}
+
+Hotspot *WSC::getItemScreenSpot(Item *item, DisplayElement *element) {
+ HotSpotID destSpotID;
+
+ switch (item->getObjectID()) {
+ case kNitrogenCanister:
+ destSpotID = kWSC02SouthTakeNitrogenSpotID;
+ break;
+ case kArgonPickup:
+ destSpotID = kWSC02SouthTakeArgonSpotID;
+ break;
+ case kAntidote:
+ destSpotID = kWSC03SouthPickUpAntidoteSpotID;
+ break;
+ case kMachineGun:
+ destSpotID = kW61SouthMachineGunSpotID;
+ break;
+ case kRetinalScanBiochip:
+ destSpotID = kW98RetinalChipSpotID;
+ break;
+ case kMapBiochip:
+ destSpotID = kW98MapChipSpotID;
+ break;
+ case kOpticalBiochip:
+ destSpotID = kW98OpticalChipSpotID;
+ break;
+ default:
+ destSpotID = kNoHotSpotID;
+ break;
+ }
+
+ if (destSpotID == kNoHotSpotID)
+ return Neighborhood::getItemScreenSpot(item, element);
+
+ return _vm->getAllHotspots().findHotspotByID(destSpotID);
+}
+
+void WSC::pickedUpItem(Item *item) {
+ switch (item->getObjectID()) {
+ case kAntidote:
+ 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;
+ case kArgonPickup:
+ _vm->removeItemFromInventory((InventoryItem *)item);
+ item = (Item *)_vm->getAllItems().findItemByID(kArgonCanister);
+ _vm->addItemToInventory((InventoryItem *)item);
+ item = (Item *)_vm->getAllItems().findItemByID(kSinclairKey);
+ _vm->addItemToInventory((InventoryItem *)item);
+ _vm->getAllHotspots().setHotspotRect(kWSC02SouthMorphOutSpotID,
+ Common::Rect(kNavAreaLeft, kNavAreaTop, 512 + kNavAreaLeft, 256 + kNavAreaTop));
+ break;
+ case kArgonCanister:
+ GameState.setScoringGotArgonCanister();
+ break;
+ case kSinclairKey:
+ GameState.setScoringGotSinclairKey();
+ break;
+ case kNitrogenCanister:
+ GameState.setScoringGotNitrogenCanister();
+ break;
+ case kRetinalScanBiochip:
+ if (_privateFlags.getFlag(kWSCPrivateGotMapChipFlag) && _privateFlags.getFlag(kWSCPrivateGotOpticalChipFlag)) {
+ if (GameState.getWSCCatwalkDark())
+ startExtraSequence(kW98RobotHeadClosesDark, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraSequence(kW98RobotHeadClosesLight, kExtraCompletedFlag, kFilterNoInput);
+ }
+ break;
+ case kMapBiochip:
+ if (_privateFlags.getFlag(kWSCPrivateGotRetScanChipFlag) && _privateFlags.getFlag(kWSCPrivateGotOpticalChipFlag)) {
+ if (GameState.getWSCCatwalkDark())
+ startExtraSequence(kW98RobotHeadClosesDark, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraSequence(kW98RobotHeadClosesLight, kExtraCompletedFlag, kFilterNoInput);
+ }
+ break;
+ case kOpticalBiochip:
+ g_opticalChip->addMercury();
+ GameState.setScoringGotWSCOpMemChip();
+ if (_privateFlags.getFlag(kWSCPrivateGotRetScanChipFlag) && _privateFlags.getFlag(kWSCPrivateGotMapChipFlag)) {
+ if (GameState.getWSCCatwalkDark())
+ startExtraSequence(kW98RobotHeadClosesDark, kExtraCompletedFlag, kFilterNoInput);
+ else
+ startExtraSequence(kW98RobotHeadClosesLight, kExtraCompletedFlag, kFilterNoInput);
+ }
+ break;
+ case kStunGun:
+ GameState.setWSCFinished(true);
+
+ if (!GameState.getWSCCatwalkDark())
+ GameState.setScoringWSCGandhi();
+
+ recallToTSASuccess();
+ break;
+ }
+}
+
+void WSC::checkPeopleCrossing() {
+ switch (GameState.getCurrentRoomAndView()) {
+ case MakeRoomView(kWSC17, kWest):
+ if (_privateFlags.getFlag(kWSCPrivateNeedPeopleAt17WestFlag))
+ startExtraSequence(kW17WestPeopleCrossing, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case MakeRoomView(kWSC21, kSouth):
+ if (_privateFlags.getFlag(kWSCPrivateNeedPeopleAt21SouthFlag))
+ startExtraSequence(kW21SouthPeopleCrossing, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case MakeRoomView(kWSC24, kSouth):
+ if (_privateFlags.getFlag(kWSCPrivateNeedPeopleAt24SouthFlag))
+ startExtraSequence(kW24SouthPeopleCrossing, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case MakeRoomView(kWSC34, kEast):
+ if (_privateFlags.getFlag(kWSCPrivateNeedPeopleAt34EastFlag))
+ startExtraSequence(kW34EastPeopleCrossing, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case MakeRoomView(kWSC36, kWest):
+ if (_privateFlags.getFlag(kWSCPrivateNeedPeopleAt36WestFlag))
+ startExtraSequence(kW36WestPeopleCrossing, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case MakeRoomView(kWSC38, kNorth):
+ if (_privateFlags.getFlag(kWSCPrivateNeedPeopleAt38NorthFlag))
+ startExtraSequence(kW38NorthPeopleCrossing, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case MakeRoomView(kWSC46, kSouth):
+ if (_privateFlags.getFlag(kWSCPrivateNeedPeopleAt46SouthFlag))
+ startExtraSequence(kW46SouthPeopleCrossing, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case MakeRoomView(kWSC49, kNorth):
+ if (_privateFlags.getFlag(kWSCPrivateNeedPeopleAt49NorthFlag))
+ startExtraSequence(kW49NorthPeopleCrossing, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ case MakeRoomView(kWSC73, kWest):
+ if (_privateFlags.getFlag(kWSCPrivateNeedPeopleAt73WestFlag))
+ startExtraSequence(kW73WestPeopleCrossing, kExtraCompletedFlag, kFilterNoInput);
+ break;
+ default:
+ if (!_privateFlags.getFlag(kWSCPrivateSeenPeopleAt21SouthFlag) && _vm->getRandomNumber(2) == 0) {
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt21SouthFlag, true);
+ forceStridingStop(kWSC18, kSouth, kAltWSCNormal);
+ } else {
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt21SouthFlag, false);
+ restoreStriding(kWSC18, kSouth, kAltWSCNormal);
+ }
+
+ if (!_privateFlags.getFlag(kWSCPrivateSeenPeopleAt19NorthFlag) && _vm->getRandomNumber(2) == 0) {
+ forceStridingStop(kWSC22, kNorth, kAltWSCNormal);
+ } else {
+ restoreStriding(kWSC22, kNorth, kAltWSCNormal);
+ }
+
+ if (!_privateFlags.getFlag(kWSCPrivateSeenPeopleAt24SouthFlag) && _vm->getRandomNumber(2) == 0) {
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt24SouthFlag, true);
+ forceStridingStop(kWSC22, kSouth, kAltWSCNormal);
+ } else {
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt24SouthFlag, false);
+ restoreStriding(kWSC22, kSouth, kAltWSCNormal);
+ }
+
+ if (!_privateFlags.getFlag(kWSCPrivateSeenPeopleAt34EastFlag) && _vm->getRandomNumber(2) == 0) {
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt34EastFlag, true);
+ forceStridingStop(kWSC28, kEast, kAltWSCNormal);
+ } else {
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt34EastFlag, false);
+ restoreStriding(kWSC28, kEast, kAltWSCNormal);
+ }
+
+ if (!_privateFlags.getFlag(kWSCPrivateSeenPeopleAt36WestFlag) && _vm->getRandomNumber(2) == 0) {
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt36WestFlag, true);
+ forceStridingStop(kWSC40, kWest, kAltWSCNormal);
+ } else {
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt36WestFlag, false);
+ restoreStriding(kWSC40, kWest, kAltWSCNormal);
+ }
+
+ if (!_privateFlags.getFlag(kWSCPrivateSeenPeopleAt38NorthFlag) && _vm->getRandomNumber(2) == 0) {
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt38NorthFlag, true);
+ forceStridingStop(kWSC42, kNorth, kAltWSCNormal);
+ } else {
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt38NorthFlag, false);
+ restoreStriding(kWSC42, kNorth, kAltWSCNormal);
+ }
+
+ if (!_privateFlags.getFlag(kWSCPrivateSeenPeopleAt46SouthFlag) && _vm->getRandomNumber(2) == 0) {
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt46SouthFlag, true);
+ forceStridingStop(kWSC44, kSouth, kAltWSCNormal);
+ } else {
+ _privateFlags.setFlag(kWSCPrivateNeedPeopleAt46SouthFlag, false);
+ restoreStriding(kWSC44, kSouth, kAltWSCNormal);
+ }
+ break;
+ }
+}
+
+void WSC::setUpPoison() {
+ if (GameState.getWSCPoisoned()) {
+ if (GameState.getWSCRemovedDart()) {
+ if (g_energyMonitor->getEnergyDrainRate() != kWSCPoisonEnergyDrainNoDart) {
+ g_energyMonitor->setEnergyDrainRate(kWSCPoisonEnergyDrainNoDart);
+ _vm->setEnergyDeathReason(kDeathDidntStopPoison);
+ }
+ } else {
+ if (g_energyMonitor->getEnergyDrainRate() != kWSCPoisonEnergyDrainWithDart) {
+ g_energyMonitor->setEnergyDrainRate(kWSCPoisonEnergyDrainWithDart);
+ _vm->setEnergyDeathReason(kDeathDidntStopPoison);
+ }
+ }
+ } else if (g_energyMonitor->getEnergyDrainRate() != kEnergyDrainNormal) {
+ g_energyMonitor->setEnergyDrainRate(kEnergyDrainNormal);
+ _vm->resetEnergyDeathReason();
+ }
+}
+
+bool WSC::inSynthesizerGame() {
+ return _moleculesMovie.isMovieValid();
+}
+
+bool WSC::canSolve() {
+ return (inSynthesizerGame() || (GameState.getCurrentRoom() == kWSC98 && !GameState.getWSCRobotDead()));
+}
+
+void WSC::doSolve() {
+ if (inSynthesizerGame()) {
+ _moleculesMovie.releaseMovie();
+ _moleculeBin.cleanUpMoleculeBin();
+ requestExtraSequence(kW03NorthFinishSynthesis, kExtraCompletedFlag, kFilterNoInput);
+ } else if (GameState.getCurrentRoom() == kWSC98 && !GameState.getWSCRobotDead()) {
+ cancelEvent();
+ startExtraSequence(kW98RobotShocked, kExtraCompletedFlag, kFilterNoInput);
+ }
+}
+
+Common::String WSC::getNavMovieName() {
+ return "Images/World Science Center/WSC.movie";
+}
+
+Common::String WSC::getSoundSpotsName() {
+ return "Sounds/World Science Center/WSC Spots";
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/wsc/wsc.h b/engines/pegasus/neighborhood/wsc/wsc.h
new file mode 100644
index 0000000000..d9634b3539
--- /dev/null
+++ b/engines/pegasus/neighborhood/wsc/wsc.h
@@ -0,0 +1,166 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_WSC_WSC_H
+#define PEGASUS_NEIGHBORHOOD_WSC_WSC_H
+
+#include "pegasus/neighborhood/neighborhood.h"
+#include "pegasus/neighborhood/wsc/moleculebin.h"
+
+namespace Pegasus {
+
+static const DisplayOrder kWSCMoleculeBinOrder = kMonitorLayer;
+static const DisplayOrder kWSCMoleculesMovieOrder = kWSCMoleculeBinOrder + 1;
+
+static const RoomID kWSC01 = 0;
+static const RoomID kWSC02Morph = 2;
+static const RoomID kWSC02Messages = 3;
+static const RoomID kWSC62 = 62;
+
+class WSC : public Neighborhood {
+public:
+ WSC(InputHandler *, PegasusEngine *);
+ virtual ~WSC() {}
+
+ void flushGameState();
+
+ virtual uint16 getDateResID() const;
+
+ bool okayToJump();
+
+ void checkContinuePoint(const RoomID, const DirectionConstant);
+
+ bool inSynthesizerGame();
+
+ bool canSolve();
+ void doSolve();
+
+ virtual void prepareForAIHint(const Common::String &);
+ virtual void cleanUpAfterAIHint(const Common::String &);
+
+ void init();
+ void start();
+
+protected:
+ enum {
+ kWSCDraggingAntidoteFlag,
+
+ kWSCPrivateLabMessagesOpenFlag,
+ kWSCPrivateInterruptedMorphFlag,
+ kWSCPrivateInMoleculeGameFlag,
+ kWSCPrivateSinclairOfficeOpenFlag,
+ kWSCPrivateOfficeLogOpenFlag,
+ kWSCPrivate58SouthOpenFlag,
+ kWSCPrivateClickedCatwalkCableFlag,
+ kWSCPrivateRobotHeadOpenFlag,
+
+ kWSCPrivateSeenPeopleAt17WestFlag,
+ kWSCPrivateSeenPeopleAt19NorthFlag,
+ kWSCPrivateSeenPeopleAt21SouthFlag,
+ kWSCPrivateSeenPeopleAt24SouthFlag,
+ kWSCPrivateSeenPeopleAt34EastFlag,
+ kWSCPrivateSeenPeopleAt36WestFlag,
+ kWSCPrivateSeenPeopleAt38NorthFlag,
+ kWSCPrivateSeenPeopleAt46SouthFlag,
+ kWSCPrivateSeenPeopleAt49NorthFlag,
+ kWSCPrivateSeenPeopleAt73WestFlag,
+
+ kWSCPrivateNeedPeopleAt17WestFlag,
+ kWSCPrivateNeedPeopleAt21SouthFlag,
+ kWSCPrivateNeedPeopleAt24SouthFlag,
+ kWSCPrivateNeedPeopleAt34EastFlag,
+ kWSCPrivateNeedPeopleAt36WestFlag,
+ kWSCPrivateNeedPeopleAt38NorthFlag,
+ kWSCPrivateNeedPeopleAt46SouthFlag,
+ kWSCPrivateNeedPeopleAt49NorthFlag,
+ kWSCPrivateNeedPeopleAt73WestFlag,
+
+ kWSCPrivateGotRetScanChipFlag,
+ kWSCPrivateGotMapChipFlag,
+ kWSCPrivateGotOpticalChipFlag,
+
+ kNumWSCPrivateFlags
+ };
+
+ void arriveAt(const RoomID, const DirectionConstant);
+ void turnTo(const DirectionConstant);
+ void receiveNotification(Notification *, const NotificationFlags);
+ void dropItemIntoRoom(Item *, Hotspot *);
+ void clickInHotspot(const Input &, const Hotspot *);
+ TimeValue getViewTime(const RoomID, const DirectionConstant);
+ void getZoomEntry(const HotSpotID, ZoomTable::Entry &);
+ CanMoveForwardReason canMoveForward(ExitTable::Entry &entry);
+ void cantMoveThatWay(CanMoveForwardReason reason);
+ CanTurnReason canTurn(TurnDirection turn, DirectionConstant &nextDir);
+ void zoomTo(const Hotspot *hotspot);
+ void activateOneHotspot(HotspotInfoTable::Entry &, Hotspot *);
+ void setUpMoleculeGame();
+ void nextMoleculeGameLevel();
+ void startMoleculeGameLevel();
+ void moleculeGameClick(const HotSpotID);
+ void loadAmbientLoops();
+ CanOpenDoorReason canOpenDoor(DoorTable::Entry &);
+ void cantOpenDoor(CanOpenDoorReason);
+ void pickedUpItem(Item *);
+ void doorOpened();
+ void startExtraSequence(const ExtraID, const NotificationFlags, const InputBits);
+ void getExtraEntry(const uint32, ExtraTable::Entry &);
+ void takeItemFromRoom(Item *item);
+ void checkPeopleCrossing();
+ void turnLeft();
+ void turnRight();
+ void moveForward();
+ Hotspot *getItemScreenSpot(Item *, DisplayElement *);
+ int16 getStaticCompassAngle(const RoomID, const DirectionConstant);
+ void getExitCompassMove(const ExitTable::Entry &exitEntry, FaderMoveSpec &compassMove);
+ void getExtraCompassMove(const ExtraTable::Entry &entry, FaderMoveSpec &compassMove);
+ void bumpIntoWall();
+ void activateHotspots();
+ void setUpAIRules();
+ Common::String getBriefingMovie();
+ Common::String getEnvScanMovie();
+ uint getNumHints();
+ Common::String getHintMovie(uint);
+ void closeDoorOffScreen(const RoomID, const DirectionConstant);
+ void setUpPoison();
+ void findSpotEntry(const RoomID, const DirectionConstant, SpotFlags, SpotTable::Entry &);
+ void timerExpired(const uint32);
+
+ Common::String getSoundSpotsName();
+ Common::String getNavMovieName();
+
+ FlagsArray<byte, kNumWSCPrivateFlags> _privateFlags;
+ const Hotspot *_cachedZoomSpot;
+ MoleculeBin _moleculeBin;
+ int32 _moleculeGameLevel, _numCorrect;
+ Movie _moleculesMovie;
+ uint32 _levelArray[6];
+ Common::Rational _energyDrainRate;
+ Sprite *_argonSprite;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/neighborhood/zoom.cpp b/engines/pegasus/neighborhood/zoom.cpp
new file mode 100644
index 0000000000..478ec6e493
--- /dev/null
+++ b/engines/pegasus/neighborhood/zoom.cpp
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/textconsole.h"
+
+#include "pegasus/neighborhood/zoom.h"
+
+namespace Pegasus {
+
+void ZoomTable::loadFromStream(Common::SeekableReadStream *stream) {
+ uint32 count = stream->readUint32BE();
+ _entries.resize(count);
+
+ for (uint32 i = 0; i < count; i++) {
+ _entries[i].hotspot = stream->readUint16BE();
+ _entries[i].movieStart = stream->readUint32BE();
+ _entries[i].movieEnd = stream->readUint32BE();
+ _entries[i].room = stream->readUint16BE();
+ _entries[i].direction = stream->readByte();
+ debug(0, "Zoom[%d]: %d %d %d %d %d", i, _entries[i].hotspot, _entries[i].movieStart,
+ _entries[i].movieEnd, _entries[i].room, _entries[i].direction);
+ stream->readByte(); // alignment
+ }
+}
+
+void ZoomTable::clear() {
+ _entries.clear();
+}
+
+ZoomTable::Entry::Entry() {
+ clear();
+}
+
+void ZoomTable::Entry::clear() {
+ hotspot = kNoHotSpotID;
+ movieStart = 0xffffffff;
+ movieEnd = 0xffffffff;
+ room = kNoRoomID;
+ direction = kNoDirection;
+}
+
+ZoomTable::Entry ZoomTable::findEntry(HotSpotID hotspot) {
+ for (uint32 i = 0; i < _entries.size(); i++)
+ if (_entries[i].hotspot == hotspot)
+ return _entries[i];
+
+ return Entry();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/neighborhood/zoom.h b/engines/pegasus/neighborhood/zoom.h
new file mode 100644
index 0000000000..8bcf8974f8
--- /dev/null
+++ b/engines/pegasus/neighborhood/zoom.h
@@ -0,0 +1,70 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NEIGHBORHOOD_ZOOM_H
+#define PEGASUS_NEIGHBORHOOD_ZOOM_H
+
+#include "common/array.h"
+#include "common/endian.h"
+
+#include "pegasus/constants.h"
+
+namespace Common {
+ class SeekableReadStream;
+}
+
+namespace Pegasus {
+
+class ZoomTable {
+public:
+ ZoomTable() {}
+ ~ZoomTable() {}
+
+ static uint32 getResTag() { return MKTAG('Z', 'o', 'o', 'm'); }
+
+ void loadFromStream(Common::SeekableReadStream *stream);
+ void clear();
+
+ struct Entry {
+ Entry();
+ void clear();
+ bool isEmpty() { return movieStart == 0xffffffff; }
+
+ HotSpotID hotspot;
+ TimeValue movieStart;
+ TimeValue movieEnd;
+ RoomID room;
+ DirectionConstant direction;
+ };
+
+ Entry findEntry(HotSpotID hotspot);
+
+private:
+ Common::Array<Entry> _entries;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/notification.cpp b/engines/pegasus/notification.cpp
new file mode 100644
index 0000000000..2d57fcc5e7
--- /dev/null
+++ b/engines/pegasus/notification.cpp
@@ -0,0 +1,149 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/constants.h"
+#include "pegasus/notification.h"
+
+namespace Pegasus {
+
+typedef ReceiverList::iterator ReceiverIterator;
+
+Notification::Notification(const NotificationID id, NotificationManager *owner) : IDObject(id) {
+ _owner = owner;
+ _currentFlags = kNoNotificationFlags;
+ if (_owner)
+ _owner->addNotification(this);
+}
+
+Notification::~Notification() {
+ for (uint i = 0; i < _receivers.size(); i++)
+ _receivers[i].receiver->newNotification(NULL);
+
+ if (_owner)
+ _owner->removeNotification(this);
+}
+
+// Selectively set or clear notificiation bits.
+// Wherever mask is 0, leave existing bits untouched.
+// Wherever mask is 1, set bit equivalent to flags.
+void Notification::notifyMe(NotificationReceiver *receiver, NotificationFlags flags, NotificationFlags mask) {
+ for (uint i = 0; i < _receivers.size(); i++) {
+ if (_receivers[i].receiver == receiver) {
+ _receivers[i].mask = (_receivers[i].mask & ~mask) | (flags & mask);
+ receiver->newNotification(this);
+ return;
+ }
+ }
+
+ ReceiverEntry newEntry;
+ newEntry.receiver = receiver;
+ newEntry.mask = flags;
+ _receivers.push_back(newEntry);
+
+ receiver->newNotification(this);
+}
+
+void Notification::cancelNotification(NotificationReceiver *receiver) {
+ for (uint i = 0; i < _receivers.size(); i++) {
+ if (_receivers[i].receiver == receiver) {
+ _receivers.remove_at(i);
+ i--;
+ }
+ }
+}
+
+void Notification::setNotificationFlags(NotificationFlags flags, NotificationFlags mask) {
+ _currentFlags = (_currentFlags & ~mask) | flags;
+}
+
+void Notification::checkReceivers() {
+ NotificationFlags currentFlags = _currentFlags;
+ _currentFlags = kNoNotificationFlags;
+
+ for (uint i = 0; i < _receivers.size(); i++)
+ if (_receivers[i].mask & currentFlags)
+ _receivers[i].receiver->receiveNotification(this, currentFlags);
+}
+
+// Receiver entries are equal if their receivers are equal.
+
+int operator==(const ReceiverEntry &entry1, const ReceiverEntry &entry2) {
+ return entry1.receiver == entry2.receiver;
+}
+
+int operator!=(const ReceiverEntry &entry1, const ReceiverEntry &entry2) {
+ return entry1.receiver != entry2.receiver;
+}
+
+NotificationReceiver::NotificationReceiver() {
+ _notification = NULL;
+}
+
+NotificationReceiver::~NotificationReceiver() {
+ if (_notification)
+ _notification->cancelNotification(this);
+}
+
+void NotificationReceiver::receiveNotification(Notification *, const NotificationFlags) {
+}
+
+void NotificationReceiver::newNotification(Notification *notification) {
+ _notification = notification;
+}
+
+typedef NotificationList::iterator NotificationIterator;
+
+NotificationManager::NotificationManager() {
+}
+
+NotificationManager::~NotificationManager() {
+ detachNotifications();
+}
+
+void NotificationManager::addNotification(Notification *notification) {
+ _notifications.push_back(notification);
+}
+
+void NotificationManager::removeNotification(Notification *notification) {
+ for (NotificationIterator it = _notifications.begin(); it != _notifications.end();) {
+ if ((*it) == notification)
+ it = _notifications.erase(it);
+ else
+ it++;
+ }
+}
+
+void NotificationManager::detachNotifications() {
+ for (NotificationIterator it = _notifications.begin(); it != _notifications.end(); it++)
+ (*it)->_owner = 0;
+}
+
+void NotificationManager::checkNotifications() {
+ for (NotificationIterator it = _notifications.begin(); it != _notifications.end(); it++)
+ if ((*it)->_currentFlags != kNoNotificationFlags)
+ (*it)->checkReceivers();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/notification.h b/engines/pegasus/notification.h
new file mode 100644
index 0000000000..19b69829be
--- /dev/null
+++ b/engines/pegasus/notification.h
@@ -0,0 +1,123 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_NOTIFICATION_H
+#define PEGASUS_NOTIFICATION_H
+
+#include "common/array.h"
+#include "common/list.h"
+
+#include "pegasus/types.h"
+#include "pegasus/util.h"
+
+namespace Pegasus {
+
+class NotificationManager;
+class NotificationReceiver;
+
+struct ReceiverEntry {
+ NotificationReceiver *receiver;
+ NotificationFlags mask;
+};
+
+int operator==(const ReceiverEntry &entry1, const ReceiverEntry &entry2);
+int operator!=(const ReceiverEntry &entry1, const ReceiverEntry &entry2);
+
+typedef Common::Array<ReceiverEntry> ReceiverList;
+
+/*
+ A notification can have 32 flags associated with it, which can be user-defined.
+*/
+
+class Notification : public IDObject {
+friend class NotificationManager;
+
+public:
+ Notification(const NotificationID id, NotificationManager *owner);
+ virtual ~Notification();
+
+ // notifyMe will have this receiver notified when any of the specified notification
+ // flags are set.
+ // If there is already a notification set for this receiver, notifyMe does a bitwise
+ // OR with the receiver's current notification flags.
+
+ // Can selectively set or clear notification bits by using the flags and mask argument.
+
+ void notifyMe(NotificationReceiver*, NotificationFlags flags, NotificationFlags mask);
+ void cancelNotification(NotificationReceiver *receiver);
+
+ void setNotificationFlags(NotificationFlags flags, NotificationFlags mask);
+ NotificationFlags getNotificationFlags() { return _currentFlags; }
+
+ void clearNotificationFlags() { setNotificationFlags(0, ~(NotificationFlags)0); }
+
+protected:
+ void checkReceivers();
+
+ NotificationManager *_owner;
+ ReceiverList _receivers;
+ NotificationFlags _currentFlags;
+};
+
+class NotificationReceiver {
+friend class Notification;
+
+public:
+ NotificationReceiver();
+ virtual ~NotificationReceiver();
+
+protected:
+ // receiveNotification is called automatically whenever a notification that this
+ // receiver depends on has its flags set
+
+ virtual void receiveNotification(Notification *, const NotificationFlags);
+ virtual void newNotification(Notification *notification);
+
+private:
+ Notification *_notification;
+};
+
+typedef Common::List<Notification *> NotificationList;
+
+class NotificationManager : public NotificationReceiver {
+friend class Notification;
+
+public:
+ NotificationManager();
+ virtual ~NotificationManager();
+
+ void checkNotifications();
+
+protected:
+ void addNotification(Notification *notification);
+ void removeNotification(Notification *notification);
+ void detachNotifications();
+
+ NotificationList _notifications;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp
new file mode 100644
index 0000000000..420ca39331
--- /dev/null
+++ b/engines/pegasus/pegasus.cpp
@@ -0,0 +1,2347 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/config-manager.h"
+#include "common/error.h"
+#include "common/events.h"
+#include "common/fs.h"
+#include "common/file.h"
+#include "common/memstream.h"
+#include "common/savefile.h"
+#include "common/textconsole.h"
+#include "common/translation.h"
+#include "common/random.h"
+#include "base/plugins.h"
+#include "base/version.h"
+#include "gui/saveload.h"
+#include "video/qt_decoder.h"
+
+#include "pegasus/console.h"
+#include "pegasus/cursor.h"
+#include "pegasus/energymonitor.h"
+#include "pegasus/gamestate.h"
+#include "pegasus/interface.h"
+#include "pegasus/menu.h"
+#include "pegasus/movie.h"
+#include "pegasus/pegasus.h"
+#include "pegasus/timers.h"
+#include "pegasus/ai/ai_area.h"
+#include "pegasus/items/itemlist.h"
+#include "pegasus/items/biochips/aichip.h"
+#include "pegasus/items/biochips/biochipitem.h"
+#include "pegasus/items/biochips/mapchip.h"
+#include "pegasus/items/biochips/opticalchip.h"
+#include "pegasus/items/biochips/pegasuschip.h"
+#include "pegasus/items/biochips/retscanchip.h"
+#include "pegasus/items/biochips/shieldchip.h"
+#include "pegasus/items/inventory/airmask.h"
+#include "pegasus/items/inventory/gascanister.h"
+#include "pegasus/items/inventory/inventoryitem.h"
+#include "pegasus/items/inventory/keycard.h"
+#include "pegasus/neighborhood/neighborhood.h"
+#include "pegasus/neighborhood/caldoria/caldoria.h"
+#include "pegasus/neighborhood/mars/mars.h"
+#include "pegasus/neighborhood/norad/constants.h"
+#include "pegasus/neighborhood/norad/alpha/noradalpha.h"
+#include "pegasus/neighborhood/norad/delta/noraddelta.h"
+#include "pegasus/neighborhood/prehistoric/prehistoric.h"
+#include "pegasus/neighborhood/tsa/fulltsa.h"
+#include "pegasus/neighborhood/tsa/tinytsa.h"
+#include "pegasus/neighborhood/wsc/wsc.h"
+
+namespace Pegasus {
+
+PegasusEngine::PegasusEngine(OSystem *syst, const PegasusGameDescription *gamedesc) : Engine(syst), InputHandler(0), _gameDescription(gamedesc),
+ _shellNotification(kJMPDCShellNotificationID, this), _returnHotspot(kInfoReturnSpotID), _itemDragger(this), _bigInfoMovie(kNoDisplayElement),
+ _smallInfoMovie(kNoDisplayElement) {
+ _continuePoint = 0;
+ _saveAllowed = _loadAllowed = true;
+ _saveRequested = _loadRequested = false;
+ _gameMenu = 0;
+ _deathReason = kDeathStranded;
+ _neighborhood = 0;
+ _FXLevel = 0x80;
+ _ambientLevel = 0x80;
+ _gameMode = kNoMode;
+ _switchModesSync = false;
+ _draggingItem = 0;
+ _dragType = kDragNoDrag;
+ _idlerHead = 0;
+ _currentCD = 1;
+ _introTimer = 0;
+ _aiSaveStream = 0;
+}
+
+PegasusEngine::~PegasusEngine() {
+ delete _resFork;
+ delete _console;
+ delete _cursor;
+ delete _continuePoint;
+ delete _gameMenu;
+ delete _neighborhood;
+ delete _rnd;
+ delete _introTimer;
+ delete _aiSaveStream;
+
+ for (ItemIterator it = _allItems.begin(); it != _allItems.end(); it++)
+ delete *it;
+
+ InputDeviceManager::destroy();
+ GameStateManager::destroy();
+
+ // NOTE: This must be deleted last!
+ delete _gfx;
+}
+
+Common::Error PegasusEngine::run() {
+ _console = new PegasusConsole(this);
+ _gfx = new GraphicsManager(this);
+ _resFork = new Common::MacResManager();
+ _cursor = new Cursor();
+ _rnd = new Common::RandomSource("Pegasus");
+
+ if (!_resFork->open("JMP PP Resources") || !_resFork->hasResFork())
+ error("Could not load JMP PP Resources");
+
+ // Initialize items
+ createItems();
+
+ // Initialize cursors
+ _cursor->addCursorFrames(0x80); // Main
+ _cursor->addCursorFrames(900); // Mars Shuttle
+
+ // Initialize the item dragger bounds
+ _itemDragger.setHighlightBounds();
+
+ if (!isDemo() && !detectOpeningClosingDirectory()) {
+ Common::String message = "Missing intro directory. ";
+
+ // Give Mac OS X a more specific message because we can
+#ifdef MACOSX
+ message += "Make sure \"Opening/Closing\" is present.";
+#else
+ message += "Be sure to rename \"Opening/Closing\" to \"Opening_Closing\".";
+#endif
+
+ GUIErrorMessage(message);
+ warning("%s", message.c_str());
+ return Common::kNoGameDataFoundError;
+ }
+
+ // Set up input
+ InputHandler::setInputHandler(this);
+ allowInput(true);
+
+ // Set up inventories
+ _items.setWeightLimit(9);
+ _items.setOwnerID(kPlayerID);
+ _biochips.setWeightLimit(8);
+ _biochips.setOwnerID(kPlayerID);
+
+ _returnHotspot.setArea(Common::Rect(kNavAreaLeft, kNavAreaTop, 512 + kNavAreaLeft, 256 + kNavAreaTop));
+ _returnHotspot.setHotspotFlags(kInfoReturnSpotFlag);
+ _allHotspots.push_back(&_returnHotspot);
+
+ _screenDimmer.setBounds(Common::Rect(0, 0, 640, 480));
+ _screenDimmer.setDisplayOrder(kScreenDimmerOrder);
+
+ // Load from the launcher/cli if requested (and don't show the intro in those cases)
+ bool doIntro = true;
+ if (ConfMan.hasKey("save_slot")) {
+ uint32 gameToLoad = ConfMan.getInt("save_slot");
+ doIntro = (loadGameState(gameToLoad).getCode() != Common::kNoError);
+ }
+
+ _shellNotification.notifyMe(this, kJMPShellNotificationFlags, kJMPShellNotificationFlags);
+
+ if (doIntro)
+ // Start up the first notification
+ _shellNotification.setNotificationFlags(kGameStartingFlag, kGameStartingFlag);
+
+ if (!isDemo()) {
+ _introTimer = new FuseFunction();
+ _introTimer->setFunctor(new Common::Functor0Mem<void, PegasusEngine>(this, &PegasusEngine::introTimerExpired));
+ }
+
+ while (!shouldQuit()) {
+ processShell();
+ _system->delayMillis(10); // Ease off the CPU
+ }
+
+ return Common::kNoError;
+}
+
+bool PegasusEngine::canLoadGameStateCurrently() {
+ return _loadAllowed && !isDemo();
+}
+
+bool PegasusEngine::canSaveGameStateCurrently() {
+ return _saveAllowed && !isDemo() && g_neighborhood;
+}
+
+bool PegasusEngine::detectOpeningClosingDirectory() {
+ // We need to detect what our Opening/Closing directory is listed as
+ // On the original disc, it was 'Opening/Closing' but only HFS(+) supports the slash
+ // Mac OS X will display this as 'Opening:Closing' and we can use that directly
+ // On other systems, users will need to rename to "Opening_Closing"
+
+ Common::FSNode gameDataDir(ConfMan.get("path"));
+ gameDataDir = gameDataDir.getChild("Images");
+
+ if (!gameDataDir.exists())
+ return false;
+
+ Common::FSList fsList;
+ if (!gameDataDir.getChildren(fsList, Common::FSNode::kListDirectoriesOnly, true))
+ return false;
+
+ for (uint i = 0; i < fsList.size() && _introDirectory.empty(); i++) {
+ Common::String name = fsList[i].getName();
+
+ if (name.equalsIgnoreCase("Opening:Closing"))
+ _introDirectory = name;
+ else if (name.equalsIgnoreCase("Opening_Closing"))
+ _introDirectory = name;
+ }
+
+ if (_introDirectory.empty())
+ return false;
+
+ debug(0, "Detected intro location as '%s'", _introDirectory.c_str());
+ _introDirectory = Common::String("Images/") + _introDirectory;
+ return true;
+}
+
+void PegasusEngine::createItems() {
+ Common::SeekableReadStream *res = _resFork->getResource(MKTAG('N', 'I', 't', 'm'), 0x80);
+
+ uint16 entryCount = res->readUint16BE();
+
+ for (uint16 i = 0; i < entryCount; i++) {
+ ItemID itemID = res->readUint16BE();
+ NeighborhoodID neighborhoodID = res->readUint16BE();
+ RoomID roomID = res->readUint16BE();
+ DirectionConstant direction = res->readByte();
+ res->readByte(); // alignment
+
+ createItem(itemID, neighborhoodID, roomID, direction);
+ }
+
+ delete res;
+}
+
+void PegasusEngine::createItem(ItemID itemID, NeighborhoodID neighborhoodID, RoomID roomID, DirectionConstant direction) {
+ switch (itemID) {
+ case kInterfaceBiochip:
+ // Unused in game, but still in the data and we need to create
+ // it because it's saved/loaded from save files.
+ new BiochipItem(itemID, neighborhoodID, roomID, direction);
+ break;
+ case kAIBiochip:
+ new AIChip(itemID, neighborhoodID, roomID, direction);
+ break;
+ case kPegasusBiochip:
+ new PegasusChip(itemID, neighborhoodID, roomID, direction);
+ break;
+ case kOpticalBiochip:
+ new OpticalChip(itemID, neighborhoodID, roomID, direction);
+ break;
+ case kMapBiochip:
+ new MapChip(itemID, neighborhoodID, roomID, direction);
+ break;
+ case kRetinalScanBiochip:
+ new RetScanChip(itemID, neighborhoodID, roomID, direction);
+ break;
+ case kShieldBiochip:
+ new ShieldChip(itemID, neighborhoodID, roomID, direction);
+ break;
+ case kAirMask:
+ new AirMask(itemID, neighborhoodID, roomID, direction);
+ break;
+ case kKeyCard:
+ new KeyCard(itemID, neighborhoodID, roomID, direction);
+ break;
+ case kGasCanister:
+ new GasCanister(itemID, neighborhoodID, roomID, direction);
+ break;
+ default:
+ // Everything else is a normal inventory item
+ new InventoryItem(itemID, neighborhoodID, roomID, direction);
+ break;
+ }
+}
+
+void PegasusEngine::runIntro() {
+ stopIntroTimer();
+
+ bool skipped = false;
+
+ Video::VideoDecoder *video = new Video::QuickTimeDecoder();
+ if (video->loadFile(_introDirectory + "/BandaiLogo.movie")) {
+ video->start();
+
+ while (!shouldQuit() && !video->endOfVideo() && !skipped) {
+ if (video->needsUpdate()) {
+ const Graphics::Surface *frame = video->decodeNextFrame();
+
+ if (frame) {
+ _system->copyRectToScreen((byte *)frame->pixels, frame->pitch, 0, 0, frame->w, frame->h);
+ _system->updateScreen();
+ }
+ }
+
+ Input input;
+ InputDevice.getInput(input, kFilterAllInput);
+ if (input.anyInput())
+ skipped = true;
+
+ _system->delayMillis(10);
+ }
+ }
+
+ delete video;
+
+ if (shouldQuit() || skipped)
+ return;
+
+ video = new Video::QuickTimeDecoder();
+
+ if (!video->loadFile(_introDirectory + "/Big Movie.movie"))
+ error("Could not load intro movie");
+
+ video->seek(Audio::Timestamp(0, 10 * 600, 600));
+ video->start();
+
+ playMovieScaled(video, 0, 0);
+
+ delete video;
+}
+
+Common::Error PegasusEngine::showLoadDialog() {
+ GUI::SaveLoadChooser slc(_("Load game:"), _("Load"), false);
+
+ Common::String gameId = ConfMan.get("gameid");
+
+ const EnginePlugin *plugin = 0;
+ EngineMan.findGame(gameId, &plugin);
+
+ int slot = slc.runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName());
+
+ Common::Error result;
+
+ if (slot >= 0) {
+ if (loadGameState(slot).getCode() == Common::kNoError)
+ result = Common::kNoError;
+ else
+ result = Common::kUnknownError;
+ } else {
+ result = Common::kUserCanceled;
+ }
+
+ return result;
+}
+
+Common::Error PegasusEngine::showSaveDialog() {
+ GUI::SaveLoadChooser slc(_("Save game:"), _("Save"), true);
+
+ Common::String gameId = ConfMan.get("gameid");
+
+ const EnginePlugin *plugin = 0;
+ EngineMan.findGame(gameId, &plugin);
+
+ int slot = slc.runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName());
+
+ Common::Error result;
+
+ if (slot >= 0) {
+ if (saveGameState(slot, slc.getResultString()).getCode() == Common::kNoError)
+ result = Common::kNoError;
+ else
+ result = Common::kUnknownError;
+ } else {
+ result = Common::kUserCanceled;
+ }
+
+ return result;
+}
+
+GUI::Debugger *PegasusEngine::getDebugger() {
+ return _console;
+}
+
+void PegasusEngine::addIdler(Idler *idler) {
+ idler->_nextIdler = _idlerHead;
+ if (_idlerHead)
+ _idlerHead->_prevIdler = idler;
+ idler->_prevIdler = 0;
+ _idlerHead = idler;
+}
+
+void PegasusEngine::removeIdler(Idler *idler) {
+ if (idler->_prevIdler)
+ idler->_prevIdler->_nextIdler = idler->_nextIdler;
+ if (idler->_nextIdler)
+ idler->_nextIdler->_prevIdler = idler->_prevIdler;
+ if (idler == _idlerHead)
+ _idlerHead = idler->_nextIdler;
+ idler->_nextIdler = 0;
+ idler->_prevIdler = 0;
+}
+
+void PegasusEngine::giveIdleTime() {
+ for (Idler *idler = _idlerHead; idler != 0; idler = idler->_nextIdler)
+ idler->useIdleTime();
+}
+
+void PegasusEngine::addTimeBase(TimeBase *timeBase) {
+ _timeBases.push_back(timeBase);
+}
+
+void PegasusEngine::removeTimeBase(TimeBase *timeBase) {
+ _timeBases.remove(timeBase);
+}
+
+bool PegasusEngine::loadFromStream(Common::ReadStream *stream) {
+ // Dispose currently running stuff
+ useMenu(0);
+ useNeighborhood(0);
+ removeAllItemsFromInventory();
+ removeAllItemsFromBiochips();
+ _currentItemID = kNoItemID;
+ _currentBiochipID = kNoItemID;
+
+ if (!g_interface)
+ createInterface();
+
+ // Signature
+ uint32 creator = stream->readUint32BE();
+ if (creator != kPegasusPrimeCreator) {
+ warning("Bad save creator '%s'", tag2str(creator));
+ return false;
+ }
+
+ uint32 gameType = stream->readUint32BE();
+ int saveType;
+
+ switch (gameType) {
+ case kPegasusPrimeDisk1GameType:
+ case kPegasusPrimeDisk2GameType:
+ case kPegasusPrimeDisk3GameType:
+ case kPegasusPrimeDisk4GameType:
+ _currentCD = gameType - kPegasusPrimeDisk1GameType + 1;
+ saveType = kNormalSave;
+ break;
+ case kPegasusPrimeContinueType:
+ saveType = kContinueSave;
+ break;
+ default:
+ // There are five other possible game types on the Pippin
+ // version, but hopefully we don't see any of those here
+ warning("Unhandled pegasus game type '%s'", tag2str(gameType));
+ return false;
+ }
+
+ uint32 version = stream->readUint32BE();
+ if (version != kPegasusPrimeVersion) {
+ warning("Where did you get this save? It's a beta (v%04x)!", version & 0x7fff);
+ return false;
+ }
+
+ // Game State
+ GameState.readGameState(stream);
+
+ // Energy
+ setLastEnergyValue(stream->readUint32BE());
+
+ // Death reason
+ setEnergyDeathReason(stream->readByte());
+
+ // Items
+ _allItems.readFromStream(stream);
+
+ // Inventory
+ byte itemCount = stream->readByte();
+
+ if (itemCount > 0) {
+ for (byte i = 0; i < itemCount; i++) {
+ InventoryItem *inv = (InventoryItem *)_allItems.findItemByID((ItemID)stream->readUint16BE());
+ addItemToInventory(inv);
+ }
+
+ g_interface->setCurrentInventoryItemID((ItemID)stream->readUint16BE());
+ }
+
+ // Biochips
+ byte biochipCount = stream->readByte();
+
+ if (biochipCount > 0) {
+ for (byte i = 0; i < biochipCount; i++) {
+ BiochipItem *biochip = (BiochipItem *)_allItems.findItemByID((ItemID)stream->readUint16BE());
+ addItemToBiochips(biochip);
+ }
+
+ g_interface->setCurrentBiochipID((ItemID)stream->readUint16BE());
+ }
+
+
+ // TODO: Disc check
+
+ // Jump to environment
+ jumpToNewEnvironment(GameState.getCurrentNeighborhood(), GameState.getCurrentRoom(), GameState.getCurrentDirection());
+ _shellNotification.setNotificationFlags(0, kNeedNewJumpFlag);
+ performJump(GameState.getCurrentNeighborhood());
+
+ // AI rules
+ if (g_AIArea)
+ g_AIArea->readAIRules(stream);
+
+ startNeighborhood();
+
+ // Make a new continue point if this isn't already one
+ if (saveType == kNormalSave)
+ makeContinuePoint();
+
+ return true;
+}
+
+bool PegasusEngine::writeToStream(Common::WriteStream *stream, int saveType) {
+ // WORKAROUND: If we don't have the interface, we can't actually save.
+ // However, we should still have a continue point, so we will just dump that
+ // out. This is needed for saving a game while in the space chase.
+ if (!g_interface) {
+ // Saving a continue stream from a continue stream should
+ // never happen. In addition, we do need to have a continue
+ // stream for this to work.
+ if (saveType != kNormalSave || !_continuePoint)
+ return false;
+
+ writeContinueStream(stream);
+ return true;
+ }
+
+ if (g_neighborhood)
+ g_neighborhood->flushGameState();
+
+ // Signature
+ stream->writeUint32BE(kPegasusPrimeCreator);
+
+ if (saveType == kNormalSave)
+ stream->writeUint32BE(kPegasusPrimeDisk1GameType + _currentCD - 1);
+ else // Continue
+ stream->writeUint32BE(kPegasusPrimeContinueType);
+
+ stream->writeUint32BE(kPegasusPrimeVersion);
+
+ // Game State
+ GameState.writeGameState(stream);
+
+ // Energy
+ stream->writeUint32BE(getSavedEnergyValue());
+
+ // Death reason
+ stream->writeByte(getEnergyDeathReason());
+
+ // Items
+ _allItems.writeToStream(stream);
+
+ // Inventory
+ byte itemCount = _items.getNumItems();
+ stream->writeByte(itemCount);
+
+ if (itemCount > 0) {
+ for (uint32 i = 0; i < itemCount; i++)
+ stream->writeUint16BE(_items.getItemIDAt(i));
+
+ stream->writeUint16BE(g_interface->getCurrentInventoryItem()->getObjectID());
+ }
+
+ // Biochips
+ byte biochipCount = _biochips.getNumItems();
+ stream->writeByte(biochipCount);
+
+ if (biochipCount > 0) {
+ for (uint32 i = 0; i < biochipCount; i++)
+ stream->writeUint16BE(_biochips.getItemIDAt(i));
+
+ stream->writeUint16BE(g_interface->getCurrentBiochip()->getObjectID());
+ }
+
+ // AI rules
+ if (g_AIArea)
+ g_AIArea->writeAIRules(stream);
+
+ return true;
+}
+
+void PegasusEngine::makeContinuePoint() {
+ // WORKAROUND: Do not attempt to make a continue point if the interface is not set
+ // up. The original did *not* do this and attempting to restore the game using the pause
+ // menu during the canyon/space chase sequence would segfault the game and crash the
+ // system. Nice!
+ if (!g_interface)
+ return;
+
+ delete _continuePoint;
+
+ Common::MemoryWriteStreamDynamic newPoint(DisposeAfterUse::NO);
+ writeToStream(&newPoint, kContinueSave);
+ _continuePoint = new Common::MemoryReadStream(newPoint.getData(), newPoint.size(), DisposeAfterUse::YES);
+}
+
+void PegasusEngine::loadFromContinuePoint() {
+ // Failure to load a continue point is fatal
+
+ if (!_continuePoint)
+ error("Attempting to load from non-existant continue point");
+
+ _continuePoint->seek(0);
+
+ if (!loadFromStream(_continuePoint))
+ error("Failed loading continue point");
+}
+
+void PegasusEngine::writeContinueStream(Common::WriteStream *stream) {
+ // We're going to pretty much copy the stream, except for the save type
+ _continuePoint->seek(0);
+ stream->writeUint32BE(_continuePoint->readUint32BE());
+ _continuePoint->readUint32BE(); // skip the continue type
+ stream->writeUint32BE(kPegasusPrimeDisk1GameType + _currentCD - 1);
+
+ // Now just copy over the rest
+ uint32 size = _continuePoint->size() - _continuePoint->pos();
+ byte *data = new byte[size];
+ _continuePoint->read(data, size);
+ stream->write(data, size);
+ delete[] data;
+}
+
+Common::Error PegasusEngine::loadGameState(int slot) {
+ Common::StringArray filenames = _saveFileMan->listSavefiles("pegasus-*.sav");
+ Common::InSaveFile *loadFile = _saveFileMan->openForLoading(filenames[slot]);
+ if (!loadFile)
+ return Common::kUnknownError;
+
+ bool valid = loadFromStream(loadFile);
+ delete loadFile;
+
+ return valid ? Common::kNoError : Common::kUnknownError;
+}
+
+Common::Error PegasusEngine::saveGameState(int slot, const Common::String &desc) {
+ Common::String output = Common::String::format("pegasus-%s.sav", desc.c_str());
+ Common::OutSaveFile *saveFile = _saveFileMan->openForSaving(output, false);
+ if (!saveFile)
+ return Common::kUnknownError;
+
+ bool valid = writeToStream(saveFile, kNormalSave);
+ delete saveFile;
+
+ return valid ? Common::kNoError : Common::kUnknownError;
+}
+
+void PegasusEngine::receiveNotification(Notification *notification, const NotificationFlags flags) {
+ if (&_shellNotification == notification) {
+ switch (flags) {
+ case kGameStartingFlag: {
+ useMenu(new MainMenu());
+
+ if (!isDemo()) {
+ runIntro();
+ resetIntroTimer();
+ } else {
+ showTempScreen("Images/Demo/NGsplashScrn.pict");
+ }
+
+ if (shouldQuit())
+ return;
+
+ _gfx->invalRect(Common::Rect(0, 0, 640, 480));
+ _gfx->updateDisplay();
+ ((MainMenu *)_gameMenu)->startMainMenuLoop();
+ break;
+ }
+ case kPlayerDiedFlag:
+ doDeath();
+ break;
+ case kNeedNewJumpFlag:
+ performJump(GameState.getNextNeighborhood());
+ startNeighborhood();
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void PegasusEngine::checkCallBacks() {
+ for (Common::List<TimeBase *>::iterator it = _timeBases.begin(); it != _timeBases.end(); it++)
+ (*it)->checkCallBacks();
+}
+
+void PegasusEngine::resetIntroTimer() {
+ if (!isDemo() && _gameMenu && _gameMenu->getObjectID() == kMainMenuID) {
+ _introTimer->stopFuse();
+ _introTimer->primeFuse(kIntroTimeOut);
+ _introTimer->lightFuse();
+ }
+}
+
+void PegasusEngine::introTimerExpired() {
+ if (_gameMenu && _gameMenu->getObjectID() == kMainMenuID) {
+ ((MainMenu *)_gameMenu)->stopMainMenuLoop();
+
+ bool skipped = false;
+
+ Video::VideoDecoder *video = new Video::QuickTimeDecoder();
+ if (!video->loadFile(_introDirectory + "/LilMovie.movie"))
+ error("Failed to load little movie");
+
+ bool saveAllowed = swapSaveAllowed(false);
+ bool openAllowed = swapLoadAllowed(false);
+
+ video->start();
+ skipped = playMovieScaled(video, 0, 0);
+
+ delete video;
+
+ if (shouldQuit())
+ return;
+
+ if (!skipped) {
+ runIntro();
+
+ if (shouldQuit())
+ return;
+ }
+
+ resetIntroTimer();
+ _gfx->invalRect(Common::Rect(0, 0, 640, 480));
+
+ swapSaveAllowed(saveAllowed);
+ swapLoadAllowed(openAllowed);
+
+ _gfx->updateDisplay();
+ ((MainMenu *)_gameMenu)->startMainMenuLoop();
+ }
+}
+
+void PegasusEngine::stopIntroTimer() {
+ if (_introTimer)
+ _introTimer->stopFuse();
+}
+
+void PegasusEngine::delayShell(TimeValue time, TimeScale scale) {
+ if (time == 0 || scale == 0)
+ return;
+
+ uint32 startTime = g_system->getMillis();
+ uint32 timeInMillis = time * 1000 / scale;
+
+ while (g_system->getMillis() < startTime + timeInMillis) {
+ checkCallBacks();
+ _gfx->updateDisplay();
+ }
+}
+
+void PegasusEngine::useMenu(GameMenu *newMenu) {
+ if (_gameMenu) {
+ _gameMenu->restorePreviousHandler();
+ delete _gameMenu;
+ }
+
+ _gameMenu = newMenu;
+
+ if (_gameMenu)
+ _gameMenu->becomeCurrentHandler();
+}
+
+bool PegasusEngine::checkGameMenu() {
+ GameMenuCommand command = kMenuCmdNoCommand;
+
+ if (_gameMenu) {
+ command = _gameMenu->getLastCommand();
+ if (command != kMenuCmdNoCommand) {
+ _gameMenu->clearLastCommand();
+ doGameMenuCommand(command);
+ }
+ }
+
+ return command != kMenuCmdNoCommand;
+}
+
+void PegasusEngine::doGameMenuCommand(const GameMenuCommand command) {
+ Common::Error result;
+
+ switch (command) {
+ case kMenuCmdStartAdventure:
+ stopIntroTimer();
+ GameState.setWalkthroughMode(false);
+ startNewGame();
+ break;
+ case kMenuCmdCredits:
+ if (isDemo()) {
+ showTempScreen("Images/Demo/DemoCredits.pict");
+ _gfx->doFadeOutSync();
+ _gfx->updateDisplay();
+ _gfx->doFadeInSync();
+ } else {
+ stopIntroTimer();
+ _gfx->doFadeOutSync();
+ useMenu(new CreditsMenu());
+ _gfx->updateDisplay();
+ _gfx->doFadeInSync();
+ }
+ break;
+ case kMenuCmdQuit:
+ case kMenuCmdDeathQuitDemo:
+ if (isDemo())
+ showTempScreen("Images/Demo/NGquitScrn.pict");
+ _system->quit();
+ break;
+ case kMenuCmdOverview:
+ stopIntroTimer();
+ doInterfaceOverview();
+ resetIntroTimer();
+ break;
+ case kMenuCmdStartWalkthrough:
+ stopIntroTimer();
+ GameState.setWalkthroughMode(true);
+ startNewGame();
+ break;
+ case kMenuCmdRestore:
+ stopIntroTimer();
+ // fall through
+ case kMenuCmdDeathRestore:
+ result = showLoadDialog();
+ if (command == kMenuCmdRestore && result.getCode() != Common::kNoError)
+ resetIntroTimer();
+ break;
+ case kMenuCmdCreditsMainMenu:
+ _gfx->doFadeOutSync();
+ useMenu(new MainMenu());
+ _gfx->updateDisplay();
+ ((MainMenu *)_gameMenu)->startMainMenuLoop();
+ _gfx->doFadeInSync();
+ resetIntroTimer();
+ break;
+ case kMenuCmdDeathContinue:
+ if (((DeathMenu *)_gameMenu)->playerWon()) {
+ if (isDemo()) {
+ showTempScreen("Images/Demo/DemoCredits.pict");
+ _gfx->doFadeOutSync();
+ _gfx->updateDisplay();
+ _gfx->doFadeInSync();
+ } else {
+ _gfx->doFadeOutSync();
+ useMenu(0);
+ _gfx->clearScreen();
+ _gfx->updateDisplay();
+
+ Video::VideoDecoder *video = new Video::QuickTimeDecoder();
+ if (!video->loadFile(_introDirectory + "/Closing.movie"))
+ error("Could not load closing movie");
+
+ uint16 x = (640 - video->getWidth() * 2) / 2;
+ uint16 y = (480 - video->getHeight() * 2) / 2;
+
+ video->start();
+ playMovieScaled(video, x, y);
+
+ delete video;
+
+ if (shouldQuit())
+ return;
+
+ useMenu(new MainMenu());
+ _gfx->updateDisplay();
+ ((MainMenu *)_gameMenu)->startMainMenuLoop();
+ _gfx->doFadeInSync();
+ resetIntroTimer();
+ }
+ } else {
+ loadFromContinuePoint();
+ }
+ break;
+ case kMenuCmdDeathMainMenuDemo:
+ case kMenuCmdDeathMainMenu:
+ _gfx->doFadeOutSync();
+ useMenu(new MainMenu());
+ _gfx->updateDisplay();
+ ((MainMenu *)_gameMenu)->startMainMenuLoop();
+ _gfx->doFadeInSync();
+ resetIntroTimer();
+ break;
+ case kMenuCmdPauseSave:
+ if (showSaveDialog().getCode() != Common::kUserCanceled)
+ pauseMenu(false);
+ break;
+ case kMenuCmdPauseContinue:
+ pauseMenu(false);
+ break;
+ case kMenuCmdPauseRestore:
+ makeContinuePoint();
+ result = showLoadDialog();
+
+ if (result.getCode() == Common::kNoError) {
+ // Successfully loaded, unpause the game
+ pauseMenu(false);
+ } else if (result.getCode() != Common::kUserCanceled) {
+ // Try to get us back to a sane state
+ loadFromContinuePoint();
+ }
+ break;
+ case kMenuCmdPauseQuit:
+ _gfx->doFadeOutSync();
+ throwAwayEverything();
+ pauseMenu(false);
+ useMenu(new MainMenu());
+ _gfx->updateDisplay();
+ ((MainMenu *)_gameMenu)->startMainMenuLoop();
+ _gfx->doFadeInSync();
+ resetIntroTimer();
+ break;
+ case kMenuCmdNoCommand:
+ break;
+ default:
+ error("Unknown menu command %d", command);
+ }
+}
+
+void PegasusEngine::handleInput(const Input &input, const Hotspot *cursorSpot) {
+ if (!checkGameMenu())
+ shellGameInput(input, cursorSpot);
+
+ // Handle the console here
+ if (input.isConsoleRequested()) {
+ _console->attach();
+ _console->onFrame();
+ }
+
+ // Handle save requests here
+ if (_saveRequested && _saveAllowed) {
+ _saveRequested = false;
+
+ // Can only save during a game and not in the demo
+ if (g_neighborhood && !isDemo()) {
+ pauseEngine(true);
+ showSaveDialog();
+ pauseEngine(false);
+ }
+ }
+
+ // Handle load requests here
+ if (_loadRequested && _loadAllowed) {
+ _loadRequested = false;
+
+ // WORKAROUND: Do not entertain load requests when the pause menu is up
+ // The original did and the game entered a bad state after loading.
+ // It's theoretically possible to make it so it does work while the
+ // pause menu is up, but the pause state of the engine is just too weird.
+ // Just use the pause menu's restore button since it's there for that
+ // for you to load anyway.
+ if (!isDemo() && !(_gameMenu && _gameMenu->getObjectID() == kPauseMenuID)) {
+ pauseEngine(true);
+
+ if (g_neighborhood) {
+ makeContinuePoint();
+
+ Common::Error result = showLoadDialog();
+ if (result.getCode() != Common::kNoError && result.getCode() != Common::kUserCanceled)
+ loadFromContinuePoint();
+ } else {
+ if (_introTimer)
+ _introTimer->stopFuse();
+
+ Common::Error result = showLoadDialog();
+ if (result.getCode() != Common::kNoError) {
+ if (!_gameMenu) {
+ useMenu(new MainMenu());
+ ((MainMenu *)_gameMenu)->startMainMenuLoop();
+ }
+
+ resetIntroTimer();
+ }
+ }
+
+ pauseEngine(false);
+ }
+ }
+}
+
+void PegasusEngine::doInterfaceOverview() {
+ static const short kNumOverviewSpots = 11;
+ static const Common::Rect overviewSpots[kNumOverviewSpots] = {
+ Common::Rect(354, 318, 354 + 204, 318 + 12),
+ Common::Rect(211, 34, 211 + 114, 34 + 28),
+ Common::Rect(502, 344, 502 + 138, 344 + 120),
+ Common::Rect(132, 40, 132 + 79, 40 + 22),
+ Common::Rect(325, 40, 332 + 115, 40 + 22),
+ Common::Rect(70, 318, 70 + 284, 318 + 12),
+ Common::Rect(76, 334, 76 + 96, 334 + 96),
+ Common::Rect(64, 64, 64 + 512, 64 + 256),
+ Common::Rect(364, 334, 364 + 96, 334 + 96),
+ Common::Rect(172, 334, 172 + 192, 334 + 96),
+ Common::Rect(542, 36, 542 + 58, 36 + 20)
+ };
+
+ _gfx->doFadeOutSync();
+ useMenu(0);
+
+ Picture leftBackground(kNoDisplayElement);
+ leftBackground.initFromPICTFile("Images/Interface/OVLeft.mac");
+ leftBackground.setDisplayOrder(0);
+ leftBackground.moveElementTo(kBackground1Left, kBackground1Top);
+ leftBackground.startDisplaying();
+ leftBackground.show();
+
+ Picture topBackground(kNoDisplayElement);
+ topBackground.initFromPICTFile("Images/Interface/OVTop.mac");
+ topBackground.setDisplayOrder(0);
+ topBackground.moveElementTo(kBackground2Left, kBackground2Top);
+ topBackground.startDisplaying();
+ topBackground.show();
+
+ Picture rightBackground(kNoDisplayElement);
+ rightBackground.initFromPICTFile("Images/Interface/OVRight.mac");
+ rightBackground.setDisplayOrder(0);
+ rightBackground.moveElementTo(kBackground3Left, kBackground3Top);
+ rightBackground.startDisplaying();
+ rightBackground.show();
+
+ Picture bottomBackground(kNoDisplayElement);
+ bottomBackground.initFromPICTFile("Images/Interface/OVBottom.mac");
+ bottomBackground.setDisplayOrder(0);
+ bottomBackground.moveElementTo(kBackground4Left, kBackground4Top);
+ bottomBackground.startDisplaying();
+ bottomBackground.show();
+
+ Picture controllerHighlight(kNoDisplayElement);
+ controllerHighlight.initFromPICTFile("Images/Interface/OVcontrollerHilite.mac");
+ controllerHighlight.setDisplayOrder(0);
+ controllerHighlight.moveElementTo(kOverviewControllerLeft, kOverviewControllerTop);
+ controllerHighlight.startDisplaying();
+
+ Movie overviewText(kNoDisplayElement);
+ overviewText.initFromMovieFile("Images/Interface/Overview Mac.movie");
+ overviewText.setDisplayOrder(0);
+ overviewText.moveElementTo(kNavAreaLeft, kNavAreaTop);
+ overviewText.startDisplaying();
+ overviewText.show();
+ overviewText.redrawMovieWorld();
+
+ DropHighlight highlight(kNoDisplayElement);
+ highlight.setDisplayOrder(1);
+ highlight.startDisplaying();
+ highlight.setHighlightThickness(4);
+ highlight.setHighlightColor(g_system->getScreenFormat().RGBToColor(239, 239, 0));
+ highlight.setHighlightCornerDiameter(8);
+
+ Input input;
+ InputDevice.getInput(input, kFilterAllInput);
+
+ Common::Point cursorLoc;
+ input.getInputLocation(cursorLoc);
+
+ uint16 i;
+ for (i = 0; i < kNumOverviewSpots; ++i)
+ if (overviewSpots[i].contains(cursorLoc))
+ break;
+
+ TimeValue time;
+ if (i == kNumOverviewSpots)
+ time = 5;
+ else if (i > 4)
+ time = i + 1;
+ else
+ time = i;
+
+ if (time == 2) {
+ highlight.hide();
+ controllerHighlight.show();
+ } else if (i != kNumOverviewSpots) {
+ controllerHighlight.hide();
+ Common::Rect r = overviewSpots[i];
+ r.grow(5);
+ highlight.setBounds(r);
+ highlight.show();
+ } else {
+ highlight.hide();
+ controllerHighlight.hide();
+ }
+
+ overviewText.setTime(time * 3 + 2, 15);
+ overviewText.redrawMovieWorld();
+
+ _cursor->setCurrentFrameIndex(3);
+ _cursor->show();
+
+ _gfx->updateDisplay();
+ _gfx->doFadeInSync();
+
+ for (;;) {
+ InputDevice.getInput(input, kFilterAllInput);
+
+ if (input.anyInput() || shouldQuit() || _loadRequested || _saveRequested)
+ break;
+
+ input.getInputLocation(cursorLoc);
+ for (i = 0; i < kNumOverviewSpots; ++i)
+ if (overviewSpots[i].contains(cursorLoc))
+ break;
+
+ if (i == kNumOverviewSpots)
+ time = 5;
+ else if (i > 4)
+ time = i + 1;
+ else
+ time = i;
+
+ if (time == 2) {
+ highlight.hide();
+ controllerHighlight.show();
+ } else if (i != kNumOverviewSpots) {
+ controllerHighlight.hide();
+ Common::Rect r = overviewSpots[i];
+ r.grow(5);
+ highlight.setBounds(r);
+ highlight.show();
+ } else {
+ highlight.hide();
+ controllerHighlight.hide();
+ }
+
+ overviewText.setTime(time * 3 + 2, 15);
+ overviewText.redrawMovieWorld();
+
+ refreshDisplay();
+ _system->delayMillis(10);
+ }
+
+ if (shouldQuit())
+ return;
+
+ highlight.hide();
+ _cursor->hide();
+
+ _gfx->doFadeOutSync();
+ useMenu(new MainMenu());
+ _gfx->updateDisplay();
+ ((MainMenu *)_gameMenu)->startMainMenuLoop();
+ _gfx->doFadeInSync();
+
+ _saveRequested = false;
+ _loadRequested = false;
+}
+
+void PegasusEngine::showTempScreen(const Common::String &fileName) {
+ _gfx->doFadeOutSync();
+
+ Picture picture(0);
+ picture.initFromPICTFile(fileName);
+ picture.setDisplayOrder(kMaxAvailableOrder);
+ picture.startDisplaying();
+ picture.show();
+ _gfx->updateDisplay();
+
+ _gfx->doFadeInSync();
+
+ // Wait for the next event
+ bool done = false;
+ while (!shouldQuit() && !done) {
+ Common::Event event;
+ while (_eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_LBUTTONUP:
+ case Common::EVENT_RBUTTONUP:
+ case Common::EVENT_KEYDOWN:
+ done = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ _system->delayMillis(10);
+ }
+}
+
+void PegasusEngine::refreshDisplay() {
+ giveIdleTime();
+ _gfx->updateDisplay();
+}
+
+void PegasusEngine::resetEnergyDeathReason() {
+ switch (getCurrentNeighborhoodID()) {
+ case kMarsID:
+ _deathReason = kDeathArrestedInMars;
+ break;
+ case kNoradAlphaID:
+ case kNoradDeltaID:
+ _deathReason = kDeathArrestedInNorad;
+ break;
+ case kWSCID:
+ _deathReason = kDeathArrestedInWSC;
+ break;
+ default:
+ _deathReason = kDeathStranded;
+ break;
+ }
+}
+
+bool PegasusEngine::playerHasItem(const Item *item) {
+ return playerHasItemID(item->getObjectID());
+}
+
+bool PegasusEngine::playerHasItemID(const ItemID itemID) {
+ return itemInInventory(itemID) || itemInBiochips(itemID);
+}
+
+InventoryItem *PegasusEngine::getCurrentInventoryItem() {
+ if (g_interface)
+ return g_interface->getCurrentInventoryItem();
+
+ return 0;
+}
+
+bool PegasusEngine::itemInInventory(InventoryItem *item) {
+ return _items.itemInInventory(item);
+}
+
+bool PegasusEngine::itemInInventory(ItemID id) {
+ return _items.itemInInventory(id);
+}
+
+BiochipItem *PegasusEngine::getCurrentBiochip() {
+ if (g_interface)
+ return g_interface->getCurrentBiochip();
+
+ return 0;
+}
+
+bool PegasusEngine::itemInBiochips(BiochipItem *item) {
+ return _biochips.itemInInventory(item);
+}
+
+bool PegasusEngine::itemInBiochips(ItemID id) {
+ return _biochips.itemInInventory(id);
+}
+
+bool PegasusEngine::playerAlive() {
+ return (_shellNotification.getNotificationFlags() & kPlayerDiedFlag) == 0;
+}
+
+Common::String PegasusEngine::getBriefingMovie() {
+ if (_neighborhood)
+ return _neighborhood->getBriefingMovie();
+
+ return Common::String();
+}
+
+Common::String PegasusEngine::getEnvScanMovie() {
+ if (_neighborhood)
+ return _neighborhood->getEnvScanMovie();
+
+ return Common::String();
+}
+
+uint PegasusEngine::getNumHints() {
+ if (_neighborhood)
+ return _neighborhood->getNumHints();
+
+ return 0;
+}
+
+Common::String PegasusEngine::getHintMovie(uint hintNum) {
+ if (_neighborhood)
+ return _neighborhood->getHintMovie(hintNum);
+
+ return Common::String();
+}
+
+bool PegasusEngine::canSolve() {
+ if (_neighborhood)
+ return _neighborhood->canSolve();
+
+ return false;
+}
+
+void PegasusEngine::prepareForAIHint(const Common::String &movieName) {
+ if (g_neighborhood)
+ g_neighborhood->prepareForAIHint(movieName);
+}
+
+void PegasusEngine::cleanUpAfterAIHint(const Common::String &movieName) {
+ if (g_neighborhood)
+ g_neighborhood->cleanUpAfterAIHint(movieName);
+}
+
+void PegasusEngine::jumpToNewEnvironment(const NeighborhoodID neighborhoodID, const RoomID roomID, const DirectionConstant direction) {
+ GameState.setNextLocation(neighborhoodID, roomID, direction);
+ _shellNotification.setNotificationFlags(kNeedNewJumpFlag, kNeedNewJumpFlag);
+}
+
+void PegasusEngine::checkFlashlight() {
+ if (_neighborhood)
+ _neighborhood->checkFlashlight();
+}
+
+bool PegasusEngine::playMovieScaled(Video::VideoDecoder *video, uint16 x, uint16 y) {
+ bool skipped = false;
+
+ while (!shouldQuit() && !video->endOfVideo() && !skipped) {
+ if (video->needsUpdate()) {
+ const Graphics::Surface *frame = video->decodeNextFrame();
+
+ if (frame)
+ drawScaledFrame(frame, x, y);
+ }
+
+ Input input;
+ InputDevice.getInput(input, kFilterAllInput);
+ if (input.anyInput() || _saveRequested || _loadRequested)
+ skipped = true;
+
+ _system->delayMillis(10);
+ }
+
+ return skipped;
+}
+
+void PegasusEngine::die(const DeathReason reason) {
+ Input dummy;
+ if (isDragging())
+ _itemDragger.stopTracking(dummy);
+
+ _deathReason = reason;
+ _shellNotification.setNotificationFlags(kPlayerDiedFlag, kPlayerDiedFlag);
+}
+
+void PegasusEngine::doDeath() {
+ _gfx->doFadeOutSync();
+ throwAwayEverything();
+ useMenu(new DeathMenu(_deathReason));
+ _gfx->updateDisplay();
+ _gfx->doFadeInSync();
+}
+
+void PegasusEngine::throwAwayEverything() {
+ if (_items.getNumItems() != 0 && g_interface)
+ _currentItemID = g_interface->getCurrentInventoryItem()->getObjectID();
+ else
+ _currentItemID = kNoItemID;
+
+ if (_biochips.getNumItems() != 0 && g_interface)
+ _currentBiochipID = g_interface->getCurrentBiochip()->getObjectID();
+ else
+ _currentBiochipID = kNoItemID;
+
+ useMenu(0);
+ useNeighborhood(0);
+
+ delete g_interface;
+ g_interface = 0;
+}
+
+void PegasusEngine::processShell() {
+ checkCallBacks();
+ checkNotifications();
+ InputHandler::pollForInput();
+ refreshDisplay();
+}
+
+void PegasusEngine::createInterface() {
+ if (!g_interface)
+ new Interface();
+
+ g_interface->createInterface();
+}
+
+void PegasusEngine::setGameMode(const GameMode newMode) {
+ if (newMode != _gameMode && canSwitchGameMode(newMode, _gameMode)) {
+ switchGameMode(newMode, _gameMode);
+ _gameMode = newMode;
+ }
+}
+
+void PegasusEngine::switchGameMode(const GameMode newMode, const GameMode oldMode) {
+ // Start raising panels before lowering panels, to give the activating panel time
+ // to set itself up without cutting into the lowering panel's animation time.
+
+ if (_switchModesSync) {
+ if (newMode == kModeInventoryPick)
+ raiseInventoryDrawerSync();
+ else if (newMode == kModeBiochipPick)
+ raiseBiochipDrawerSync();
+ else if (newMode == kModeInfoScreen)
+ showInfoScreen();
+
+ if (oldMode == kModeInventoryPick)
+ lowerInventoryDrawerSync();
+ else if (oldMode == kModeBiochipPick)
+ lowerBiochipDrawerSync();
+ else if (oldMode == kModeInfoScreen)
+ hideInfoScreen();
+ } else {
+ if (newMode == kModeInventoryPick)
+ raiseInventoryDrawer();
+ else if (newMode == kModeBiochipPick)
+ raiseBiochipDrawer();
+ else if (newMode == kModeInfoScreen)
+ showInfoScreen();
+
+ if (oldMode == kModeInventoryPick)
+ lowerInventoryDrawer();
+ else if (oldMode == kModeBiochipPick)
+ lowerBiochipDrawer();
+ else if (oldMode == kModeInfoScreen)
+ hideInfoScreen();
+ }
+}
+
+bool PegasusEngine::canSwitchGameMode(const GameMode newMode, const GameMode oldMode) {
+ if (newMode == kModeInventoryPick && oldMode == kModeBiochipPick)
+ return false;
+ if (newMode == kModeBiochipPick && oldMode == kModeInventoryPick)
+ return false;
+ return true;
+}
+
+bool PegasusEngine::itemInLocation(const ItemID itemID, const NeighborhoodID neighborhood, const RoomID room, const DirectionConstant direction) {
+ NeighborhoodID itemNeighborhood;
+ RoomID itemRoom;
+ DirectionConstant itemDirection;
+
+ Item *item = _allItems.findItemByID(itemID);
+ item->getItemRoom(itemNeighborhood, itemRoom, itemDirection);
+
+ return itemNeighborhood == neighborhood && itemRoom == room && itemDirection == direction;
+}
+
+InventoryResult PegasusEngine::addItemToInventory(InventoryItem *item) {
+ InventoryResult result;
+
+ do {
+ if (g_interface)
+ result = g_interface->addInventoryItem(item);
+ else
+ result = _items.addItem(item);
+
+ if (result == kTooMuchWeight)
+ destroyInventoryItem(pickItemToDestroy());
+ } while (result != kInventoryOK);
+
+ GameState.setTakenItem(item, true);
+ if (g_neighborhood)
+ g_neighborhood->pickedUpItem(item);
+
+ g_AIArea->checkMiddleArea();
+
+ return result;
+}
+
+void PegasusEngine::useNeighborhood(Neighborhood *neighborhood) {
+ delete _neighborhood;
+ _neighborhood = neighborhood;
+
+ if (_neighborhood) {
+ InputHandler::setInputHandler(_neighborhood);
+ _neighborhood->init();
+ _neighborhood->moveNavTo(kNavAreaLeft, kNavAreaTop);
+ g_interface->setDate(_neighborhood->getDateResID());
+ } else {
+ InputHandler::setInputHandler(this);
+ }
+}
+
+void PegasusEngine::performJump(NeighborhoodID neighborhoodID) {
+ if (_neighborhood)
+ useNeighborhood(0);
+
+ // Sub chase is special
+ if (neighborhoodID == kNoradSubChaseID) {
+ throwAwayEverything();
+ _loadAllowed = false;
+ doSubChase();
+
+ if (shouldQuit())
+ return;
+
+ neighborhoodID = kNoradDeltaID;
+ GameState.setNextRoom(kNorad41);
+ GameState.setNextDirection(kEast);
+ _loadAllowed = true;
+ }
+
+ Neighborhood *neighborhood;
+ makeNeighborhood(neighborhoodID, neighborhood);
+ useNeighborhood(neighborhood);
+
+ // Update the CD variable (used just for saves currently)
+ _currentCD = getNeighborhoodCD(neighborhoodID);
+}
+
+void PegasusEngine::startNeighborhood() {
+ if (g_interface && _currentItemID != kNoItemID)
+ g_interface->setCurrentInventoryItemID(_currentItemID);
+
+ if (g_interface && _currentBiochipID != kNoItemID)
+ g_interface->setCurrentBiochipID(_currentBiochipID);
+
+ setGameMode(kModeNavigation);
+
+ if (_neighborhood)
+ _neighborhood->start();
+}
+
+void PegasusEngine::startNewGame() {
+ // WORKAROUND: The original game ignored the menu difficulty
+ // setting. We're going to pass it through here so that
+ // the menu actually makes sense now.
+ bool isWalkthrough = GameState.getWalkthroughMode();
+ GameState.resetGameState();
+ GameState.setWalkthroughMode(isWalkthrough);
+
+ // TODO: Enable erase
+ _gfx->doFadeOutSync();
+ useMenu(0);
+ _gfx->updateDisplay();
+ _gfx->enableUpdates();
+
+ createInterface();
+
+ if (isDemo()) {
+ setLastEnergyValue(kFullEnergy);
+ jumpToNewEnvironment(kPrehistoricID, kPrehistoric02, kSouth);
+ GameState.setPrehistoricSeenTimeStream(false);
+ GameState.setPrehistoricSeenFlyer1(false);
+ GameState.setPrehistoricSeenFlyer2(false);
+ GameState.setPrehistoricSeenBridgeZoom(false);
+ GameState.setPrehistoricBreakerThrown(false);
+ } else {
+ jumpToNewEnvironment(kCaldoriaID, kCaldoria00, kEast);
+ }
+
+ removeAllItemsFromInventory();
+ removeAllItemsFromBiochips();
+
+ BiochipItem *biochip = (BiochipItem *)_allItems.findItemByID(kAIBiochip);
+ addItemToBiochips(biochip);
+
+ if (isDemo()) {
+ biochip = (BiochipItem *)_allItems.findItemByID(kPegasusBiochip);
+ addItemToBiochips(biochip);
+ biochip = (BiochipItem *)_allItems.findItemByID(kMapBiochip);
+ addItemToBiochips(biochip);
+ InventoryItem *item = (InventoryItem *)_allItems.findItemByID(kKeyCard);
+ addItemToInventory(item);
+ item = (InventoryItem *)_allItems.findItemByID(kJourneymanKey);
+ addItemToInventory(item);
+ _currentItemID = kJourneymanKey;
+ } else {
+ _currentItemID = kNoItemID;
+ }
+
+ _currentBiochipID = kAIBiochip;
+
+ // Clear jump notification flags and just perform the jump...
+ _shellNotification.setNotificationFlags(0, kNeedNewJumpFlag);
+
+ performJump(GameState.getNextNeighborhood());
+
+ startNeighborhood();
+}
+
+void PegasusEngine::makeNeighborhood(NeighborhoodID neighborhoodID, Neighborhood *&neighborhood) {
+ // TODO: CD check
+
+ switch (neighborhoodID) {
+ case kCaldoriaID:
+ neighborhood = new Caldoria(g_AIArea, this);
+ break;
+ case kMarsID:
+ neighborhood = new Mars(g_AIArea, this);
+ break;
+ case kPrehistoricID:
+ neighborhood = new Prehistoric(g_AIArea, this);
+ break;
+ case kFullTSAID:
+ neighborhood = new FullTSA(g_AIArea, this);
+ break;
+ case kTinyTSAID:
+ neighborhood = new TinyTSA(g_AIArea, this);
+ break;
+ case kWSCID:
+ neighborhood = new WSC(g_AIArea, this);
+ break;
+ case kNoradAlphaID:
+ neighborhood = new NoradAlpha(g_AIArea, this);
+ break;
+ case kNoradDeltaID:
+ createInterface();
+ neighborhood = new NoradDelta(g_AIArea, this);
+ break;
+ default:
+ error("Unknown neighborhood %d", neighborhoodID);
+ }
+}
+
+bool PegasusEngine::wantsCursor() {
+ return _gameMenu == 0;
+}
+
+void PegasusEngine::updateCursor(const Common::Point, const Hotspot *cursorSpot) {
+ if (_itemDragger.isTracking()) {
+ _cursor->setCurrentFrameIndex(5);
+ } else {
+ if (!cursorSpot) {
+ _cursor->setCurrentFrameIndex(0);
+ } else {
+ uint32 id = cursorSpot->getObjectID();
+
+ switch (id) {
+ case kCurrentItemSpotID:
+ if (countInventoryItems() != 0)
+ _cursor->setCurrentFrameIndex(4);
+ else
+ _cursor->setCurrentFrameIndex(0);
+ break;
+ default:
+ HotSpotFlags flags = cursorSpot->getHotspotFlags();
+
+ if (flags & kZoomInSpotFlag)
+ _cursor->setCurrentFrameIndex(1);
+ else if (flags & kZoomOutSpotFlag)
+ _cursor->setCurrentFrameIndex(2);
+ else if (flags & (kPickUpItemSpotFlag | kPickUpBiochipSpotFlag))
+ _cursor->setCurrentFrameIndex(4);
+ else if (flags & kJMPClickingSpotFlags)
+ _cursor->setCurrentFrameIndex(3);
+ else
+ _cursor->setCurrentFrameIndex(0);
+ }
+ }
+ }
+}
+
+void PegasusEngine::toggleInventoryDisplay() {
+ if (_gameMode == kModeInventoryPick)
+ setGameMode(kModeNavigation);
+ else
+ setGameMode(kModeInventoryPick);
+}
+
+void PegasusEngine::toggleBiochipDisplay() {
+ if (_gameMode == kModeBiochipPick)
+ setGameMode(kModeNavigation);
+ else
+ setGameMode(kModeBiochipPick);
+}
+
+void PegasusEngine::showInfoScreen() {
+ if (g_neighborhood) {
+ // Break the input handler chain...
+ _savedHandler = InputHandler::getCurrentHandler();
+ InputHandler::setInputHandler(this);
+
+ Picture *pushPicture = ((Neighborhood *)g_neighborhood)->getTurnPushPicture();
+
+ _bigInfoMovie.shareSurface(pushPicture);
+ _smallInfoMovie.shareSurface(pushPicture);
+
+ g_neighborhood->hideNav();
+
+ _smallInfoMovie.initFromMovieFile("Images/Items/Info Right Movie");
+ _smallInfoMovie.setDisplayOrder(kInfoSpinOrder);
+ _smallInfoMovie.moveElementTo(kNavAreaLeft + 304, kNavAreaTop + 8);
+ _smallInfoMovie.moveMovieBoxTo(304, 8);
+ _smallInfoMovie.startDisplaying();
+ _smallInfoMovie.show();
+
+ TimeValue startTime, stopTime;
+ g_AIArea->getSmallInfoSegment(startTime, stopTime);
+ _smallInfoMovie.setSegment(startTime, stopTime);
+ _smallInfoMovie.setTime(startTime);
+ _smallInfoMovie.setFlags(kLoopTimeBase);
+
+ _bigInfoMovie.initFromMovieFile("Images/Items/Info Left Movie");
+ _bigInfoMovie.setDisplayOrder(kInfoBackgroundOrder);
+ _bigInfoMovie.moveElementTo(kNavAreaLeft, kNavAreaTop);
+ _bigInfoMovie.startDisplaying();
+ _bigInfoMovie.show();
+ _bigInfoMovie.setTime(g_AIArea->getBigInfoTime());
+
+ _bigInfoMovie.redrawMovieWorld();
+ _smallInfoMovie.redrawMovieWorld();
+ _smallInfoMovie.start();
+ }
+}
+
+void PegasusEngine::hideInfoScreen() {
+ if (g_neighborhood) {
+ InputHandler::setInputHandler(_savedHandler);
+
+ _bigInfoMovie.hide();
+ _bigInfoMovie.stopDisplaying();
+ _bigInfoMovie.releaseMovie();
+
+ _smallInfoMovie.hide();
+ _smallInfoMovie.stopDisplaying();
+ _smallInfoMovie.stop();
+ _smallInfoMovie.releaseMovie();
+
+ g_neighborhood->showNav();
+ }
+}
+
+void PegasusEngine::raiseInventoryDrawer() {
+ if (g_interface)
+ g_interface->raiseInventoryDrawer();
+}
+
+void PegasusEngine::raiseBiochipDrawer() {
+ if (g_interface)
+ g_interface->raiseBiochipDrawer();
+}
+
+void PegasusEngine::lowerInventoryDrawer() {
+ if (g_interface)
+ g_interface->lowerInventoryDrawer();
+}
+
+void PegasusEngine::lowerBiochipDrawer() {
+ if (g_interface)
+ g_interface->lowerBiochipDrawer();
+}
+
+void PegasusEngine::raiseInventoryDrawerSync() {
+ if (g_interface)
+ g_interface->raiseInventoryDrawerSync();
+}
+
+void PegasusEngine::raiseBiochipDrawerSync() {
+ if (g_interface)
+ g_interface->raiseBiochipDrawerSync();
+}
+
+void PegasusEngine::lowerInventoryDrawerSync() {
+ if (g_interface)
+ g_interface->lowerInventoryDrawerSync();
+}
+
+void PegasusEngine::lowerBiochipDrawerSync() {
+ if (g_interface)
+ g_interface->lowerBiochipDrawerSync();
+}
+
+void PegasusEngine::toggleInfo() {
+ if (_gameMode == kModeInfoScreen)
+ setGameMode(kModeNavigation);
+ else if (_gameMode == kModeNavigation)
+ setGameMode(kModeInfoScreen);
+}
+
+void PegasusEngine::dragTerminated(const Input &) {
+ Hotspot *finalSpot = _itemDragger.getLastHotspot();
+ InventoryResult result;
+
+ if (_dragType == kDragInventoryPickup) {
+ if (finalSpot && finalSpot->getObjectID() == kInventoryDropSpotID)
+ result = addItemToInventory((InventoryItem *)_draggingItem);
+ else
+ result = kTooMuchWeight;
+
+ if (result != kInventoryOK)
+ autoDragItemIntoRoom(_draggingItem, _draggingSprite);
+ else
+ delete _draggingSprite;
+ } else if (_dragType == kDragBiochipPickup) {
+ if (finalSpot && finalSpot->getObjectID() == kBiochipDropSpotID)
+ result = addItemToBiochips((BiochipItem *)_draggingItem);
+ else
+ result = kTooMuchWeight;
+
+ if (result != kInventoryOK)
+ autoDragItemIntoRoom(_draggingItem, _draggingSprite);
+ else
+ delete _draggingSprite;
+ } else if (_dragType == kDragInventoryUse) {
+ if (finalSpot && (finalSpot->getHotspotFlags() & kDropItemSpotFlag) != 0) {
+ // *** Need to decide on a case by case basis what to do here.
+ // the crowbar should break the cover off the Mars reactor if its frozen, the
+ // global transport card should slide through the slot, the oxygen mask should
+ // attach to the filling station, and so on...
+ _neighborhood->dropItemIntoRoom(_draggingItem, finalSpot);
+ delete _draggingSprite;
+ } else {
+ autoDragItemIntoInventory(_draggingItem, _draggingSprite);
+ }
+ }
+
+ _dragType = kDragNoDrag;
+
+ if (g_AIArea)
+ g_AIArea->unlockAI();
+}
+
+
+void PegasusEngine::dragItem(const Input &input, Item *item, DragType type) {
+ _draggingItem = item;
+ _dragType = type;
+
+ // Create the sprite.
+ _draggingSprite = _draggingItem->getDragSprite(kDraggingSpriteID);
+ Common::Point where;
+ input.getInputLocation(where);
+ Common::Rect r1;
+ _draggingSprite->getBounds(r1);
+ r1 = Common::Rect::center(where.x, where.y, r1.width(), r1.height());
+ _draggingSprite->setBounds(r1);
+
+ // Set up drag constraints.
+ DisplayElement *navMovie = _gfx->findDisplayElement(kNavMovieID);
+ Common::Rect r2;
+ navMovie->getBounds(r2);
+ r2.left -= r1.width() / 3;
+ r2.right += r1.width() / 3;
+ r2.top -= r1.height() / 3;
+ r2.bottom += r2.height() / 3;
+
+ r1 = Common::Rect(-30000, -30000, 30000, 30000);
+ _itemDragger.setDragConstraints(r2, r1);
+
+ // Start dragging.
+ _draggingSprite->setDisplayOrder(kDragSpriteOrder);
+ _draggingSprite->startDisplaying();
+ _draggingSprite->show();
+ _itemDragger.setDragSprite(_draggingSprite);
+ _itemDragger.setNextHandler(_neighborhood);
+ _itemDragger.startTracking(input);
+
+ if (g_AIArea)
+ g_AIArea->lockAIOut();
+}
+
+void PegasusEngine::shellGameInput(const Input &input, const Hotspot *cursorSpot) {
+ if (_gameMode == kModeInfoScreen) {
+ if (JMPPPInput::isToggleAIMiddleInput(input)) {
+ LowerClientSignature middleOwner = g_AIArea->getMiddleAreaOwner();
+ g_AIArea->toggleMiddleAreaOwner();
+
+ if (middleOwner != g_AIArea->getMiddleAreaOwner()) {
+ _bigInfoMovie.setTime(g_AIArea->getBigInfoTime());
+ _smallInfoMovie.stop();
+ _smallInfoMovie.setFlags(0);
+
+ TimeValue startTime, stopTime;
+ g_AIArea->getSmallInfoSegment(startTime, stopTime);
+ _smallInfoMovie.setSegment(startTime, stopTime);
+ _smallInfoMovie.setTime(startTime);
+ _smallInfoMovie.setFlags(kLoopTimeBase);
+
+ _bigInfoMovie.redrawMovieWorld();
+ _smallInfoMovie.redrawMovieWorld();
+ _smallInfoMovie.start();
+ }
+ }
+ } else {
+ if (JMPPPInput::isRaiseInventoryInput(input))
+ toggleInventoryDisplay();
+
+ if (JMPPPInput::isRaiseBiochipsInput(input))
+ toggleBiochipDisplay();
+
+ if (JMPPPInput::isTogglePauseInput(input) && _neighborhood)
+ pauseMenu(!isPaused());
+ }
+
+ if (JMPPPInput::isToggleInfoInput(input))
+ toggleInfo();
+}
+
+void PegasusEngine::activateHotspots() {
+ if (_gameMode == kModeInfoScreen) {
+ _allHotspots.activateOneHotspot(kInfoReturnSpotID);
+ } else {
+ // Set up hot spots.
+ if (_dragType == kDragInventoryPickup)
+ _allHotspots.activateOneHotspot(kInventoryDropSpotID);
+ else if (_dragType == kDragBiochipPickup)
+ _allHotspots.activateOneHotspot(kBiochipDropSpotID);
+ else if (_dragType == kDragNoDrag)
+ _allHotspots.activateMaskedHotspots(kShellSpotFlag);
+ }
+}
+
+bool PegasusEngine::isClickInput(const Input &input, const Hotspot *cursorSpot) {
+ if (_cursor->isVisible() && cursorSpot)
+ return JMPPPInput::isClickInput(input);
+ else
+ return false;
+}
+
+InputBits PegasusEngine::getClickFilter() {
+ return JMPPPInput::getClickInputFilter();
+}
+
+void PegasusEngine::clickInHotspot(const Input &input, const Hotspot *clickedSpot) {
+ if (clickedSpot->getObjectID() == kCurrentItemSpotID) {
+ InventoryItem *currentItem = getCurrentInventoryItem();
+ if (currentItem) {
+ removeItemFromInventory(currentItem);
+ dragItem(input, currentItem, kDragInventoryUse);
+ }
+ } else if (clickedSpot->getObjectID() == kInfoReturnSpotID) {
+ toggleInfo();
+ }
+}
+
+InventoryResult PegasusEngine::removeItemFromInventory(InventoryItem *item) {
+ InventoryResult result;
+
+ if (g_interface)
+ result = g_interface->removeInventoryItem(item);
+ else
+ result = _items.removeItem(item);
+
+ // This should never happen
+ assert(result == kInventoryOK);
+
+ return result;
+}
+
+void PegasusEngine::removeAllItemsFromInventory() {
+ if (g_interface)
+ g_interface->removeAllItemsFromInventory();
+ else
+ _items.removeAllItems();
+}
+
+/////////////////////////////////////////////
+//
+// Biochip handling.
+
+// Adding biochips to the biochip drawer is a little funny, because of two things:
+// -- We get the map biochip and pegasus biochip at the same time by dragging
+// one sprite in TSA
+// -- We can drag in more than one copy of the various biochips.
+// Because of this we need to make sure that no more than one copy of each biochip
+// is ever added.
+
+InventoryResult PegasusEngine::addItemToBiochips(BiochipItem *biochip) {
+ InventoryResult result;
+
+ if (g_interface)
+ result = g_interface->addBiochip(biochip);
+ else
+ result = _biochips.addItem(biochip);
+
+ // This can never happen
+ assert(result == kInventoryOK);
+
+ GameState.setTakenItem(biochip, true);
+
+ if (g_neighborhood)
+ g_neighborhood->pickedUpItem(biochip);
+
+ g_AIArea->checkMiddleArea();
+
+ return result;
+}
+
+void PegasusEngine::removeAllItemsFromBiochips() {
+ if (g_interface)
+ g_interface->removeAllItemsFromBiochips();
+ else
+ _biochips.removeAllItems();
+}
+
+void PegasusEngine::setSoundFXLevel(uint16 fxLevel) {
+ _FXLevel = fxLevel;
+ if (_neighborhood)
+ _neighborhood->setSoundFXLevel(fxLevel);
+ if (g_AIArea)
+ g_AIArea->setAIVolume(fxLevel);
+}
+
+void PegasusEngine::setAmbienceLevel(uint16 ambientLevel) {
+ _ambientLevel = ambientLevel;
+ if (_neighborhood)
+ _neighborhood->setAmbienceLevel(ambientLevel);
+}
+
+void PegasusEngine::pauseMenu(bool menuUp) {
+ if (menuUp) {
+ pauseEngine(true);
+ _screenDimmer.startDisplaying();
+ _screenDimmer.show();
+ _gfx->updateDisplay();
+ useMenu(new PauseMenu());
+ } else {
+ pauseEngine(false);
+ _screenDimmer.hide();
+ _screenDimmer.stopDisplaying();
+ useMenu(0);
+ g_AIArea->checkMiddleArea();
+ }
+}
+
+void PegasusEngine::autoDragItemIntoRoom(Item *item, Sprite *draggingSprite) {
+ if (g_AIArea)
+ g_AIArea->lockAIOut();
+
+ Common::Point start, stop;
+ draggingSprite->getLocation(start.x, start.y);
+
+ Hotspot *dropSpot = _neighborhood->getItemScreenSpot(item, draggingSprite);
+
+ if (dropSpot) {
+ dropSpot->getCenter(stop.x, stop.y);
+ } else {
+ stop.x = kNavAreaLeft + 256;
+ stop.y = kNavAreaTop + 128;
+ }
+
+ Common::Rect bounds;
+ draggingSprite->getBounds(bounds);
+ stop.x -= bounds.width() >> 1;
+ stop.y -= bounds.height() >> 1;
+
+ int dx = ABS(stop.x - start.x);
+ int dy = ABS(stop.y - start.y);
+ TimeValue time = MAX(dx, dy);
+
+ allowInput(false);
+ _autoDragger.autoDrag(draggingSprite, start, stop, time, kDefaultTimeScale);
+
+ while (_autoDragger.isDragging()) {
+ checkCallBacks();
+ refreshDisplay();
+ _system->delayMillis(10);
+ }
+
+ _neighborhood->dropItemIntoRoom(_draggingItem, dropSpot);
+ allowInput(true);
+ delete _draggingSprite;
+
+ if (g_AIArea)
+ g_AIArea->unlockAI();
+}
+
+void PegasusEngine::autoDragItemIntoInventory(Item *, Sprite *draggingSprite) {
+ if (g_AIArea)
+ g_AIArea->lockAIOut();
+
+ Common::Point start;
+ draggingSprite->getLocation(start.x, start.y);
+
+ Common::Rect r;
+ draggingSprite->getBounds(r);
+
+ Common::Point stop((76 + 172 - r.width()) / 2, 334 - (2 * r.height() / 3));
+
+ int dx = ABS(stop.x - start.x);
+ int dy = ABS(stop.y - start.y);
+ TimeValue time = MAX(dx, dy);
+
+ allowInput(false);
+ _autoDragger.autoDrag(draggingSprite, start, stop, time, kDefaultTimeScale);
+
+ while (_autoDragger.isDragging()) {
+ checkCallBacks();
+ refreshDisplay();
+ _system->delayMillis(10);
+ }
+
+ addItemToInventory((InventoryItem *)_draggingItem);
+ allowInput(true);
+ delete _draggingSprite;
+
+ if (g_AIArea)
+ g_AIArea->unlockAI();
+}
+
+NeighborhoodID PegasusEngine::getCurrentNeighborhoodID() const {
+ if (_neighborhood)
+ return _neighborhood->getObjectID();
+
+ return kNoNeighborhoodID;
+}
+
+void PegasusEngine::pauseEngineIntern(bool pause) {
+ Engine::pauseEngineIntern(pause);
+
+ if (pause) {
+ for (Common::List<TimeBase *>::iterator it = _timeBases.begin(); it != _timeBases.end(); it++)
+ (*it)->pause();
+ } else {
+ for (Common::List<TimeBase *>::iterator it = _timeBases.begin(); it != _timeBases.end(); it++)
+ (*it)->resume();
+ }
+}
+
+uint PegasusEngine::getRandomBit() {
+ return _rnd->getRandomBit();
+}
+
+uint PegasusEngine::getRandomNumber(uint max) {
+ return _rnd->getRandomNumber(max);
+}
+
+void PegasusEngine::shuffleArray(int32 *arr, int32 count) {
+ if (count > 1) {
+ for (int32 i = 1; i < count; ++i) {
+ int32 j = _rnd->getRandomNumber(i);
+ if (j != i)
+ SWAP(arr[i], arr[j]);
+ }
+ }
+}
+
+void PegasusEngine::playEndMessage() {
+ if (g_interface) {
+ allowInput(false);
+ g_interface->playEndMessage();
+ allowInput(true);
+ }
+
+ die(kPlayerWonGame);
+}
+
+void PegasusEngine::doSubChase() {
+ Video::VideoDecoder *video = new Video::QuickTimeDecoder();
+ if (!video->loadFile("Images/Norad Alpha/Sub Chase Movie"))
+ error("Failed to load sub chase");
+
+ video->setEndTime(Audio::Timestamp(0, 133200, 600));
+ video->start();
+
+ while (!shouldQuit() && !video->endOfVideo()) {
+ if (video->needsUpdate()) {
+ const Graphics::Surface *frame = video->decodeNextFrame();
+
+ if (frame)
+ drawScaledFrame(frame, 0, 0);
+ }
+
+ Common::Event event;
+ while (_eventMan->pollEvent(event))
+ ;
+
+ _system->delayMillis(10);
+ }
+
+ delete video;
+}
+
+template<typename PixelInt>
+static void scaleFrame(const PixelInt *src, PixelInt *dst, int w, int h, int srcPitch) {
+ assert((srcPitch % sizeof(PixelInt)) == 0); // sanity check; allows some simpler code
+
+ PixelInt *dst1 = dst;
+ PixelInt *dst2 = dst + w * 2;
+
+ int srcInc = (srcPitch / sizeof(PixelInt)) - w;
+ int dstInc = w * 2;
+
+ while (h--) {
+ for (int x = 0; x < w; x++) {
+ PixelInt pixel = *src++;
+ *dst1++ = pixel;
+ *dst1++ = pixel;
+ *dst2++ = pixel;
+ *dst2++ = pixel;
+ }
+
+ src += srcInc;
+ dst1 += dstInc;
+ dst2 += dstInc;
+ }
+}
+
+void PegasusEngine::drawScaledFrame(const Graphics::Surface *frame, uint16 x, uint16 y) {
+ // Scale up the frame doing some simple scaling
+ Graphics::Surface scaledFrame;
+ 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);
+ else
+ scaleFrame<uint32>((uint32 *)frame->pixels, (uint32 *)scaledFrame.pixels, frame->w, frame->h, frame->pitch);
+
+ _system->copyRectToScreen((byte *)scaledFrame.pixels, scaledFrame.pitch, x, y, scaledFrame.w, scaledFrame.h);
+ _system->updateScreen();
+ scaledFrame.free();
+}
+
+void PegasusEngine::destroyInventoryItem(const ItemID itemID) {
+ InventoryItem *item = (InventoryItem *)_allItems.findItemByID(itemID);
+
+ ItemExtraEntry entry;
+
+ switch (itemID) {
+ case kAirMask:
+ item->findItemExtra(kRemoveAirMask, entry);
+ item->setItemRoom(kMarsID, kMars49, kSouth);
+ break;
+ case kArgonCanister:
+ item->findItemExtra(kRemoveArgon, entry);
+ item->setItemRoom(kWSCID, kWSC02Morph, kSouth);
+ break;
+ case kCrowbar:
+ item->findItemExtra(kRemoveCrowbar, entry);
+ item->setItemRoom(kMarsID, kMars34, kSouth);
+ break;
+ case kJourneymanKey:
+ item->findItemExtra(kRemoveJourneymanKey, entry);
+ item->setItemRoom(kFullTSAID, kTSA22Red, kEast);
+ break;
+ case kMarsCard:
+ item->findItemExtra(kRemoveMarsCard, entry);
+ item->setItemRoom(kMarsID, kMars31South, kSouth);
+ break;
+ case kNitrogenCanister:
+ item->findItemExtra(kRemoveNitrogen, entry);
+ item->setItemRoom(kWSCID, kWSC02Messages, kSouth);
+ break;
+ case kOrangeJuiceGlassEmpty:
+ item->findItemExtra(kRemoveGlass, entry);
+ item->setItemRoom(kCaldoriaID, kCaldoriaReplicator, kNorth);
+ break;
+ case kPoisonDart:
+ item->findItemExtra(kRemoveDart, entry);
+ item->setItemRoom(kWSCID, kWSC01, kWest);
+ break;
+ case kSinclairKey:
+ item->findItemExtra(kRemoveSinclairKey, entry);
+ item->setItemRoom(kWSCID, kWSC02Morph, kSouth);
+ break;
+ default:
+ return;
+ }
+
+ g_interface->setCurrentInventoryItemID(itemID);
+ g_AIArea->playAIAreaSequence(kInventorySignature, kMiddleAreaSignature, entry.extraStart, entry.extraStop);
+ removeItemFromInventory(item);
+}
+
+ItemID PegasusEngine::pickItemToDestroy() {
+/*
+ Must pick an item to destroy
+
+ Part I: Polite -- try to find an item that's been used
+ Part II: Desperate -- return the first available item.
+*/
+
+ // Polite:
+ if (playerHasItemID(kOrangeJuiceGlassEmpty))
+ return kOrangeJuiceGlassEmpty;
+ if (playerHasItemID(kPoisonDart)) {
+ if (GameState.getCurrentNeighborhood() != kWSCID ||
+ GameState.getWSCAnalyzedDart())
+ return kPoisonDart;
+ }
+ if (playerHasItemID(kJourneymanKey)) {
+ if (GameState.getTSAState() >= kTSAPlayerGotHistoricalLog &&
+ GameState.getTSAState() != kPlayerOnWayToPrehistoric &&
+ GameState.getTSAState() != kPlayerWentToPrehistoric)
+ return kJourneymanKey;
+ }
+ if (playerHasItemID(kMarsCard)) {
+ if (GameState.getCurrentNeighborhood() != kMarsID || GameState.getMarsArrivedBelow())
+ return kMarsCard;
+ }
+
+ // Don't want to deal with deleting the sinclair key and argon canister, since it's
+ // impossible to pick them up one at a time.
+
+ if (playerHasItemID(kNitrogenCanister)) {
+ if (GameState.getScoringGotCardBomb() && GameState.getCurrentNeighborhood() != kMarsID)
+ return kNitrogenCanister;
+ }
+ if (playerHasItemID(kCrowbar)) {
+ if (GameState.getCurrentNeighborhood() == kWSCID) {
+ if (GameState.getCurrentRoom() >= kWSC62)
+ return kCrowbar;
+ } else if (GameState.getCurrentNeighborhood() == kMarsID) {
+ if (GameState.getScoringGotCardBomb())
+ return kCrowbar;
+ } else
+ return kCrowbar;
+ }
+ if (playerHasItemID(kAirMask)) {
+ if (GameState.getCurrentNeighborhood() == kMarsID) {
+ if (g_neighborhood->getAirQuality(GameState.getCurrentRoom()) == kAirQualityGood)
+ return kAirMask;
+ } else if (GameState.getCurrentNeighborhood() != kNoradAlphaID &&
+ GameState.getCurrentNeighborhood() != kNoradDeltaID) {
+ return kAirMask;
+ }
+ }
+
+ // Desperate:
+ if (playerHasItemID(kPoisonDart))
+ return kPoisonDart;
+ if (playerHasItemID(kJourneymanKey))
+ return kJourneymanKey;
+ if (playerHasItemID(kMarsCard))
+ return kMarsCard;
+ if (playerHasItemID(kNitrogenCanister))
+ return kNitrogenCanister;
+ if (playerHasItemID(kCrowbar))
+ return kCrowbar;
+ if (playerHasItemID(kAirMask))
+ return kAirMask;
+
+ // Should never get this far...
+ error("Could not find item to delete");
+
+ return kNoItemID;
+}
+
+uint PegasusEngine::getNeighborhoodCD(const NeighborhoodID neighborhood) const {
+ switch (neighborhood) {
+ case kCaldoriaID:
+ case kNoradAlphaID:
+ case kNoradSubChaseID:
+ return 1;
+ case kFullTSAID:
+ case kPrehistoricID:
+ return 2;
+ case kMarsID:
+ return 3;
+ case kWSCID:
+ case kNoradDeltaID:
+ return 4;
+ case kTinyTSAID:
+ // Tiny TSA exists on three of the CD's, so just continue
+ // with the CD we're on
+ return _currentCD;
+ }
+
+ // Can't really happen, but it's a good fallback anyway :P
+ return 1;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/pegasus.h b/engines/pegasus/pegasus.h
new file mode 100644
index 0000000000..2a8ba22470
--- /dev/null
+++ b/engines/pegasus/pegasus.h
@@ -0,0 +1,327 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_H
+#define PEGASUS_H
+
+#include "common/list.h"
+#include "common/macresman.h"
+#include "common/rect.h"
+#include "common/scummsys.h"
+#include "common/system.h"
+#include "common/util.h"
+
+#include "engines/engine.h"
+
+#include "pegasus/graphics.h"
+#include "pegasus/hotspot.h"
+#include "pegasus/input.h"
+#include "pegasus/notification.h"
+#include "pegasus/timers.h"
+#include "pegasus/items/autodragger.h"
+#include "pegasus/items/inventory.h"
+#include "pegasus/items/itemdragger.h"
+#include "pegasus/neighborhood/neighborhood.h"
+
+namespace Common {
+ class RandomSource;
+}
+
+namespace Video {
+ class VideoDecoder;
+}
+
+namespace Pegasus {
+
+class PegasusConsole;
+struct PegasusGameDescription;
+class SoundManager;
+class GraphicsManager;
+class Idler;
+class Cursor;
+class TimeBase;
+class GameMenu;
+class InventoryItem;
+class BiochipItem;
+class Neighborhood;
+
+class PegasusEngine : public ::Engine, public InputHandler, public NotificationManager {
+friend class InputHandler;
+
+public:
+ PegasusEngine(OSystem *syst, const PegasusGameDescription *gamedesc);
+ virtual ~PegasusEngine();
+
+ // Engine stuff
+ const PegasusGameDescription *_gameDescription;
+ bool hasFeature(EngineFeature f) const;
+ GUI::Debugger *getDebugger();
+ bool canLoadGameStateCurrently();
+ bool canSaveGameStateCurrently();
+ Common::Error loadGameState(int slot);
+ Common::Error saveGameState(int slot, const Common::String &desc);
+
+ // Base classes
+ GraphicsManager *_gfx;
+ Common::MacResManager *_resFork;
+ Cursor *_cursor;
+
+ // Menu
+ void useMenu(GameMenu *menu);
+ bool checkGameMenu();
+
+ // Misc.
+ bool isDemo() const;
+ void addIdler(Idler *idler);
+ void removeIdler(Idler *idler);
+ void addTimeBase(TimeBase *timeBase);
+ void removeTimeBase(TimeBase *timeBase);
+ void delayShell(TimeValue time, TimeScale scale);
+ void resetIntroTimer();
+ void introTimerExpired();
+ void refreshDisplay();
+ bool playerAlive();
+ void processShell();
+ void checkCallBacks();
+ void createInterface();
+ void setGameMode(const GameMode);
+ GameMode getGameMode() const { return _gameMode; }
+ uint getRandomBit();
+ uint getRandomNumber(uint max);
+ void shuffleArray(int32 *arr, int32 count);
+ void drawScaledFrame(const Graphics::Surface *frame, uint16 x, uint16 y);
+ HotspotList &getAllHotspots() { return _allHotspots; }
+
+ // Energy
+ void setLastEnergyValue(const int32 value) { _savedEnergyValue = value; }
+ int32 getSavedEnergyValue() { return _savedEnergyValue; }
+
+ // Death
+ void setEnergyDeathReason(const DeathReason reason) { _deathReason = reason; }
+ DeathReason getEnergyDeathReason() { return _deathReason; }
+ void resetEnergyDeathReason();
+ void die(const DeathReason);
+ void playEndMessage();
+
+ // Volume
+ uint16 getSoundFXLevel() { return _FXLevel; }
+ void setSoundFXLevel(uint16);
+ uint16 getAmbienceLevel() { return _ambientLevel; }
+ void setAmbienceLevel(uint16);
+
+ // Items
+ ItemList &getAllItems() { return _allItems; }
+ bool playerHasItem(const Item *);
+ bool playerHasItemID(const ItemID);
+ void checkFlashlight();
+ bool itemInLocation(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
+
+ // Inventory Items
+ InventoryItem *getCurrentInventoryItem();
+ bool itemInInventory(InventoryItem *);
+ bool itemInInventory(ItemID);
+ Inventory *getItemsInventory() { return &_items; }
+ InventoryResult addItemToInventory(InventoryItem *);
+ void removeAllItemsFromInventory();
+ InventoryResult removeItemFromInventory(InventoryItem *);
+ uint32 countInventoryItems() { return _items.getNumItems(); }
+
+ // Biochips
+ BiochipItem *getCurrentBiochip();
+ bool itemInBiochips(BiochipItem *);
+ bool itemInBiochips(ItemID);
+ Inventory *getBiochipsInventory() { return &_biochips; }
+ void removeAllItemsFromBiochips();
+ InventoryResult addItemToBiochips(BiochipItem *);
+
+ // AI
+ Common::String getBriefingMovie();
+ Common::String getEnvScanMovie();
+ uint getNumHints();
+ Common::String getHintMovie(uint);
+ bool canSolve();
+ void prepareForAIHint(const Common::String &);
+ void cleanUpAfterAIHint(const Common::String &);
+ Common::SeekableReadStream *_aiSaveStream;
+
+ // Neighborhood
+ void jumpToNewEnvironment(const NeighborhoodID, const RoomID, const DirectionConstant);
+ NeighborhoodID getCurrentNeighborhoodID() const;
+
+ // Dragging
+ void dragItem(const Input &, Item *, DragType);
+ bool isDragging() const { return _dragType != kDragNoDrag; }
+ DragType getDragType() const { return _dragType; }
+ Item *getDraggingItem() const { return _draggingItem; }
+ void dragTerminated(const Input &);
+ void autoDragItemIntoRoom(Item *, Sprite *);
+ void autoDragItemIntoInventory(Item *, Sprite*);
+
+ // Save/Load
+ void makeContinuePoint();
+ bool swapSaveAllowed(bool allow) {
+ bool old = _saveAllowed;
+ _saveAllowed = allow;
+ return old;
+ }
+ bool swapLoadAllowed(bool allow) {
+ bool old = _loadAllowed;
+ _loadAllowed = allow;
+ return old;
+ }
+ void requestSave() { _saveRequested = true; }
+ bool saveRequested() const { return _saveRequested; }
+ void requestLoad() { _loadRequested = true; }
+ bool loadRequested() const { return _loadRequested; }
+
+protected:
+ Common::Error run();
+ void pauseEngineIntern(bool pause);
+
+ Notification _shellNotification;
+ virtual void receiveNotification(Notification *notification, const NotificationFlags flags);
+
+ void handleInput(const Input &input, const Hotspot *cursorSpot);
+ virtual bool isClickInput(const Input &, const Hotspot *);
+ virtual InputBits getClickFilter();
+
+ void clickInHotspot(const Input &, const Hotspot *);
+ void activateHotspots(void);
+
+ void updateCursor(const Common::Point, const Hotspot *);
+ bool wantsCursor();
+
+private:
+ // Console
+ PegasusConsole *_console;
+
+ // Intro
+ void runIntro();
+ void stopIntroTimer();
+ bool detectOpeningClosingDirectory();
+ Common::String _introDirectory;
+ FuseFunction *_introTimer;
+
+ // Idlers
+ Idler *_idlerHead;
+ void giveIdleTime();
+
+ // Items
+ ItemList _allItems;
+ void createItems();
+ void createItem(ItemID itemID, NeighborhoodID neighborhoodID, RoomID roomID, DirectionConstant direction);
+ Inventory _items;
+ Inventory _biochips;
+ ItemID _currentItemID;
+ ItemID _currentBiochipID;
+ void destroyInventoryItem(const ItemID itemID);
+ ItemID pickItemToDestroy();
+
+ // TimeBases
+ Common::List<TimeBase *> _timeBases;
+
+ // Save/Load
+ bool loadFromStream(Common::ReadStream *stream);
+ bool writeToStream(Common::WriteStream *stream, int saveType);
+ void loadFromContinuePoint();
+ void writeContinueStream(Common::WriteStream *stream);
+ Common::SeekableReadStream *_continuePoint;
+ bool _saveAllowed, _loadAllowed; // It's so nice that this was in the original code already :P
+ Common::Error showLoadDialog();
+ Common::Error showSaveDialog();
+ bool _saveRequested, _loadRequested;
+
+ // Misc.
+ Hotspot _returnHotspot;
+ HotspotList _allHotspots;
+ InputHandler *_savedHandler;
+ void showTempScreen(const Common::String &fileName);
+ bool playMovieScaled(Video::VideoDecoder *video, uint16 x, uint16 y);
+ void throwAwayEverything();
+ void shellGameInput(const Input &input, const Hotspot *cursorSpot);
+ Common::RandomSource *_rnd;
+ void doSubChase();
+ uint getNeighborhoodCD(const NeighborhoodID neighborhood) const;
+ uint _currentCD;
+
+ // Menu
+ GameMenu *_gameMenu;
+ void doGameMenuCommand(const GameMenuCommand);
+ void doInterfaceOverview();
+ ScreenDimmer _screenDimmer;
+ void pauseMenu(bool menuUp);
+
+ // Energy
+ int32 _savedEnergyValue;
+
+ // Death
+ DeathReason _deathReason;
+ void doDeath();
+
+ // Neighborhood
+ Neighborhood *_neighborhood;
+ void useNeighborhood(Neighborhood *neighborhood);
+ void performJump(NeighborhoodID start);
+ void startNewGame();
+ void startNeighborhood();
+ void makeNeighborhood(NeighborhoodID, Neighborhood *&);
+
+ // Sound
+ uint16 _ambientLevel;
+ uint16 _FXLevel;
+
+ // Game Mode
+ GameMode _gameMode;
+ bool _switchModesSync;
+ void switchGameMode(const GameMode, const GameMode);
+ bool canSwitchGameMode(const GameMode, const GameMode);
+
+ // Dragging
+ ItemDragger _itemDragger;
+ Item *_draggingItem;
+ Sprite *_draggingSprite;
+ DragType _dragType;
+ AutoDragger _autoDragger;
+
+ // Interface
+ void toggleInventoryDisplay();
+ void toggleBiochipDisplay();
+ void raiseInventoryDrawer();
+ void raiseBiochipDrawer();
+ void lowerInventoryDrawer();
+ void lowerBiochipDrawer();
+ void raiseInventoryDrawerSync();
+ void raiseBiochipDrawerSync();
+ void lowerInventoryDrawerSync();
+ void lowerBiochipDrawerSync();
+ void showInfoScreen();
+ void hideInfoScreen();
+ void toggleInfo();
+ Movie _bigInfoMovie, _smallInfoMovie;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/scoring.h b/engines/pegasus/scoring.h
new file mode 100644
index 0000000000..fbf8641ecb
--- /dev/null
+++ b/engines/pegasus/scoring.h
@@ -0,0 +1,281 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_SCORING_H
+#define PEGASUS_SCORING_H
+
+#include "pegasus/types.h"
+
+namespace Pegasus {
+
+/////////////////////////////////////////////
+//
+// Scoring.
+
+static const CoordType kDeathScreenScoreLeft = 151;
+static const CoordType kDeathScreenScoreTop = 212;
+static const CoordType kDeathScreenScoreWidth = 124;
+static const CoordType kDeathScreenScoreHeight = 12;
+static const CoordType kDeathScreenScoreSkipVert = -16;
+
+// Caldoria & TSA
+
+static const GameScoreType kSawINNScore = 5;
+static const GameScoreType kTookShowerScore = 2;
+static const GameScoreType kFixedHairScore = 2;
+static const GameScoreType kGotKeyCardScore = 5;
+static const GameScoreType kReadPaperScore = 2;
+static const GameScoreType kLookThroughTelescopeScore = 2;
+static const GameScoreType kSawCaldoriaKioskScore = 2;
+static const GameScoreType kGoToTSAScore = 3;
+
+static const GameScoreType kEnterTSAScore = 2;
+static const GameScoreType kSawBust1Score = 2;
+static const GameScoreType kSawBust2Score = 2;
+static const GameScoreType kSawBust3Score = 2;
+static const GameScoreType kSawBust4Score = 2;
+static const GameScoreType kSawBust5Score = 2;
+static const GameScoreType kSawBust6Score = 2;
+static const GameScoreType kSawTheoryScore = 4;
+static const GameScoreType kSawBackgroundScore = 4;
+static const GameScoreType kSawProcedureScore = 4;
+static const GameScoreType kGotJourneymanKeyScore = 5;
+static const GameScoreType kGotPegasusBiochipScore = 5;
+static const GameScoreType kGotBiosuitScore = 5;
+static const GameScoreType kGoToPrehistoricScore = 5;
+
+static const GameScoreType kPutLogInReaderScore = 5;
+static const GameScoreType kSawCaldoriaNormalScore = 2;
+static const GameScoreType kSawCaldoriaAlteredScore = 2;
+static const GameScoreType kSawNoradNormalScore = 2;
+static const GameScoreType kSawNoradAlteredScore = 2;
+static const GameScoreType kSawMarsNormalScore = 2;
+static const GameScoreType kSawMarsAlteredScore = 2;
+static const GameScoreType kSawWSCNormalScore = 2;
+static const GameScoreType kSawWSCAlteredScore = 2;
+static const GameScoreType kWentToReadyRoom2Score = 5;
+static const GameScoreType kWentAfterSinclairScore = 5;
+static const GameScoreType kUsedCardBombScore = 10;
+static const GameScoreType kShieldedCardBombScore = 5;
+static const GameScoreType kStunnedSinclairScore = 10;
+static const GameScoreType kDisarmedNukeScore = 10;
+
+static const GameScoreType kMaxCaldoriaTSAScoreBefore = kSawINNScore +
+ kTookShowerScore +
+ kFixedHairScore +
+ kGotKeyCardScore +
+ kReadPaperScore +
+ kLookThroughTelescopeScore +
+ kSawCaldoriaKioskScore +
+ kGoToTSAScore +
+ kEnterTSAScore +
+ kSawBust1Score +
+ kSawBust2Score +
+ kSawBust3Score +
+ kSawBust4Score +
+ kSawBust5Score +
+ kSawBust6Score +
+ kSawTheoryScore +
+ kSawBackgroundScore +
+ kSawProcedureScore +
+ kGotJourneymanKeyScore +
+ kGotPegasusBiochipScore +
+ kGotBiosuitScore +
+ kGoToPrehistoricScore +
+ kPutLogInReaderScore +
+ kSawCaldoriaNormalScore +
+ kSawCaldoriaAlteredScore +
+ kSawNoradNormalScore +
+ kSawNoradAlteredScore +
+ kSawMarsNormalScore +
+ kSawMarsAlteredScore +
+ kSawWSCNormalScore +
+ kSawWSCAlteredScore +
+ kWentToReadyRoom2Score;
+
+static const GameScoreType kMaxCaldoriaTSAScoreAfter = kWentAfterSinclairScore +
+ kUsedCardBombScore +
+ kShieldedCardBombScore +
+ kStunnedSinclairScore +
+ kDisarmedNukeScore;
+
+static const GameScoreType kMaxCaldoriaTSAScore = kMaxCaldoriaTSAScoreBefore +
+ kMaxCaldoriaTSAScoreAfter;
+
+// Prehistoric
+
+static const GameScoreType kThrewBreakerScore = 10;
+static const GameScoreType kExtendedBridgeScore = 10;
+static const GameScoreType kGotHistoricalLogScore = 5;
+static const GameScoreType kFinishedPrehistoricScore = 10;
+
+static const GameScoreType kMaxPrehistoricScore = kThrewBreakerScore +
+ kExtendedBridgeScore +
+ kGotHistoricalLogScore +
+ kFinishedPrehistoricScore;
+
+// Mars
+
+static const GameScoreType kThrownByRobotScore = 3;
+static const GameScoreType kGotMarsCardScore = 5;
+static const GameScoreType kSawMarsKioskScore = 2;
+static const GameScoreType kSawTransportMapScore = 2;
+static const GameScoreType kGotCrowBarScore = 5;
+static const GameScoreType kTurnedOnTransportScore = 5;
+static const GameScoreType kGotOxygenMaskScore = 5;
+static const GameScoreType kAvoidedRobotScore = 5;
+static const GameScoreType kActivatedPlatformScore = 2;
+static const GameScoreType kUsedLiquidNitrogenScore = 3;
+static const GameScoreType kUsedCrowBarScore = 3;
+static const GameScoreType kFoundCardBombScore = 4;
+static const GameScoreType kDisarmedCardBombScore = 8;
+static const GameScoreType kGotCardBombScore = 5;
+static const GameScoreType kThreadedMazeScore = 5;
+static const GameScoreType kThreadedGearRoomScore = 2;
+static const GameScoreType kEnteredShuttleScore = 2;
+static const GameScoreType kEnteredLaunchTubeScore = 4;
+static const GameScoreType kStoppedRobotsShuttleScore = 10;
+static const GameScoreType kGotMarsOpMemChipScore = 10;
+static const GameScoreType kFinishedMarsScore = 10;
+
+static const GameScoreType kMaxMarsScore = kThrownByRobotScore +
+ kGotMarsCardScore +
+ kSawMarsKioskScore +
+ kSawTransportMapScore +
+ kGotCrowBarScore +
+ kTurnedOnTransportScore +
+ kGotOxygenMaskScore +
+ kAvoidedRobotScore +
+ kActivatedPlatformScore +
+ kUsedLiquidNitrogenScore +
+ kUsedCrowBarScore +
+ kFoundCardBombScore +
+ kDisarmedCardBombScore +
+ kGotCardBombScore +
+ kThreadedMazeScore +
+ kThreadedGearRoomScore +
+ kEnteredShuttleScore +
+ kEnteredLaunchTubeScore +
+ kStoppedRobotsShuttleScore +
+ kGotMarsOpMemChipScore +
+ kFinishedMarsScore;
+
+// Norad
+
+static const GameScoreType kSawSecurityMonitorScore = 5;
+static const GameScoreType kFilledOxygenCanisterScore = 5;
+static const GameScoreType kFilledArgonCanisterScore = 5;
+static const GameScoreType kSawUnconsciousOperatorScore = 5;
+static const GameScoreType kWentThroughPressureDoorScore = 5;
+static const GameScoreType kPreppedSubScore = 5;
+static const GameScoreType kEnteredSubScore = 5;
+static const GameScoreType kExitedSubScore = 10;
+static const GameScoreType kSawRobotAt54NorthScore = 5;
+static const GameScoreType kPlayedWithClawScore = 5;
+static const GameScoreType kUsedRetinalChipScore = 5;
+static const GameScoreType kFinishedGlobeGameScore = 10;
+static const GameScoreType kStoppedNoradRobotScore = 10;
+static const GameScoreType kGotNoradOpMemChipScore = 10;
+static const GameScoreType kFinishedNoradScore = 10;
+
+static const GameScoreType kMaxNoradScore = kSawSecurityMonitorScore +
+ kFilledOxygenCanisterScore +
+ kFilledArgonCanisterScore +
+ kSawUnconsciousOperatorScore +
+ kWentThroughPressureDoorScore +
+ kPreppedSubScore +
+ kEnteredSubScore +
+ kExitedSubScore +
+ kSawRobotAt54NorthScore +
+ kPlayedWithClawScore +
+ kUsedRetinalChipScore +
+ kFinishedGlobeGameScore +
+ kStoppedNoradRobotScore +
+ kGotNoradOpMemChipScore +
+ kFinishedNoradScore;
+
+// WSC
+
+static const GameScoreType kRemovedDartScore = 5;
+static const GameScoreType kAnalyzedDartScore = 5;
+static const GameScoreType kBuiltAntidoteScore = 5;
+static const GameScoreType kGotSinclairKeyScore = 5;
+static const GameScoreType kGotArgonCanisterScore = 5;
+static const GameScoreType kGotNitrogenCanisterScore = 5;
+static const GameScoreType kPlayedWithMessagesScore = 2;
+static const GameScoreType kSawMorphExperimentScore = 3;
+static const GameScoreType kEnteredSinclairOfficeScore = 2;
+static const GameScoreType kSawBrochureScore = 3;
+static const GameScoreType kSawSinclairEntry1Score = 3;
+static const GameScoreType kSawSinclairEntry2Score = 3;
+static const GameScoreType kSawSinclairEntry3Score = 3;
+static const GameScoreType kSawWSCDirectoryScore = 3;
+static const GameScoreType kUsedCrowBarInWSCScore = 5;
+static const GameScoreType kFinishedPlasmaDodgeScore = 10;
+static const GameScoreType kOpenedCatwalkScore = 3;
+static const GameScoreType kStoppedWSCRobotScore = 10;
+static const GameScoreType kGotWSCOpMemChipScore = 10;
+static const GameScoreType kFinishedWSCScore = 10;
+
+static const GameScoreType kMaxWSCScore = kRemovedDartScore +
+ kAnalyzedDartScore +
+ kBuiltAntidoteScore +
+ kGotSinclairKeyScore +
+ kGotArgonCanisterScore +
+ kGotNitrogenCanisterScore +
+ kPlayedWithMessagesScore +
+ kSawMorphExperimentScore +
+ kEnteredSinclairOfficeScore +
+ kSawBrochureScore +
+ kSawSinclairEntry1Score +
+ kSawSinclairEntry2Score +
+ kSawSinclairEntry3Score +
+ kSawWSCDirectoryScore +
+ kUsedCrowBarInWSCScore +
+ kFinishedPlasmaDodgeScore +
+ kOpenedCatwalkScore +
+ kStoppedWSCRobotScore +
+ kGotWSCOpMemChipScore +
+ kFinishedWSCScore;
+
+// Gandhi
+
+static const GameScoreType kMarsGandhiScore = 10;
+static const GameScoreType kNoradGandhiScore = 10;
+static const GameScoreType kWSCGandhiScore = 10;
+
+static const GameScoreType kMaxGandhiScore = kMarsGandhiScore +
+ kNoradGandhiScore +
+ kWSCGandhiScore;
+
+static const GameScoreType kMaxTotalScore = kMaxCaldoriaTSAScore +
+ kMaxPrehistoricScore +
+ kMaxMarsScore +
+ kMaxNoradScore +
+ kMaxWSCScore +
+ kMaxGandhiScore;
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/sound.cpp b/engines/pegasus/sound.cpp
new file mode 100644
index 0000000000..bf15858e80
--- /dev/null
+++ b/engines/pegasus/sound.cpp
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "audio/audiostream.h"
+#include "audio/decoders/aiff.h"
+#include "audio/decoders/quicktime.h"
+#include "common/file.h"
+#include "common/system.h"
+
+#include "pegasus/fader.h"
+#include "pegasus/sound.h"
+
+namespace Pegasus {
+
+Sound::Sound() {
+ _stream = 0;
+ _volume = 0xFF;
+ _fader = 0;
+}
+
+Sound::~Sound() {
+ disposeSound();
+}
+
+void Sound::disposeSound() {
+ stopSound();
+ delete _stream; _stream = 0;
+}
+
+void Sound::initFromAIFFFile(const Common::String &fileName) {
+ disposeSound();
+
+ Common::File *file = new Common::File();
+ if (!file->open(fileName)) {
+ warning("Failed to open AIFF file '%s'", fileName.c_str());
+ delete file;
+ return;
+ }
+
+ _stream = Audio::makeAIFFStream(file, DisposeAfterUse::YES);
+}
+
+void Sound::initFromQuickTime(const Common::String &fileName) {
+ disposeSound();
+
+ _stream = Audio::makeQuickTimeStream(fileName);
+
+ if (!_stream)
+ warning("Failed to open QuickTime file '%s'", fileName.c_str());
+}
+
+void Sound::attachFader(SoundFader *fader) {
+ if (_fader)
+ _fader->attachSound(0);
+
+ _fader = fader;
+
+ if (_fader)
+ _fader->attachSound(this);
+}
+
+void Sound::playSound() {
+ if (!isSoundLoaded())
+ return;
+
+ stopSound();
+
+ if (_fader)
+ setVolume(_fader->getFaderValue());
+
+ g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_handle, _stream, -1, _volume, 0, DisposeAfterUse::NO);
+}
+
+void Sound::loopSound() {
+ if (!isSoundLoaded())
+ return;
+
+ stopSound();
+
+ // Create a looping stream
+ Audio::AudioStream *loopStream = new Audio::LoopingAudioStream(_stream, 0, DisposeAfterUse::NO);
+
+ // Assume that if there is a fader, we're going to fade the sound in.
+ if (_fader)
+ setVolume(0);
+
+ g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_handle, loopStream, -1, _volume, 0, DisposeAfterUse::YES);
+}
+
+void Sound::playSoundSegment(uint32 start, uint32 end) {
+ if (!isSoundLoaded())
+ return;
+
+ stopSound();
+
+ Audio::AudioStream *subStream = new Audio::SubSeekableAudioStream(_stream, Audio::Timestamp(0, start, 600), Audio::Timestamp(0, end, 600), DisposeAfterUse::NO);
+
+ g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_handle, subStream, -1, _volume, 0, DisposeAfterUse::YES);
+}
+
+void Sound::stopSound() {
+ g_system->getMixer()->stopHandle(_handle);
+}
+
+void Sound::setVolume(const uint16 volume) {
+ // Clipping the volume to [0x00, 0xFF] instead of Apple's [0, 0x100]
+ // We store the volume in case SetVolume is called before the sound starts
+
+ _volume = (volume == 0x100) ? 0xFF : volume;
+ g_system->getMixer()->setChannelVolume(_handle, _volume);
+}
+
+bool Sound::isPlaying() {
+ return isSoundLoaded() && g_system->getMixer()->isSoundHandleActive(_handle);
+}
+
+bool Sound::isSoundLoaded() const {
+ return _stream != 0;
+}
+
+SoundTimeBase::SoundTimeBase() {
+ setScale(600);
+ _startScale = 600;
+ _stopScale = 600;
+ _setToStart = false;
+}
+
+void SoundTimeBase::playSoundSegment(uint32 startTime, uint32 endTime) {
+ _startTime = startTime;
+ _stopTime = endTime;
+ _setToStart = true;
+ _time = Common::Rational(startTime, getScale());
+ setRate(1);
+ Sound::playSoundSegment(startTime, endTime);
+}
+
+void SoundTimeBase::updateTime() {
+ if (_setToStart) {
+ if (isPlaying()) {
+ // Not at the end, let's get the time
+ uint numFrames = g_system->getMixer()->getSoundElapsedTime(_handle) * 600 / 1000;
+
+ // WORKAROUND: Our mixer is woefully inaccurate and quite often returns
+ // times that exceed the actual length of the clip. We'll just fake times
+ // that are under the final time to ensure any trigger for the end time is
+ // only sent when the sound has actually stopped.
+ if (numFrames >= (_stopTime - _startTime))
+ numFrames = _stopTime - _startTime - 1;
+
+ _time = Common::Rational(_startTime + numFrames, getScale());
+ } else {
+ // Assume we reached the end
+ _setToStart = false;
+ _time = Common::Rational(_stopTime, getScale());
+ }
+ }
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/sound.h b/engines/pegasus/sound.h
new file mode 100644
index 0000000000..57cfd52e41
--- /dev/null
+++ b/engines/pegasus/sound.h
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_SOUND_H
+#define PEGASUS_SOUND_H
+
+#include "audio/mixer.h"
+#include "common/str.h"
+#include "pegasus/timers.h"
+
+namespace Audio {
+ class SeekableAudioStream;
+}
+
+namespace Pegasus {
+
+class SoundFader;
+
+// Things you might want to do with sound:
+// - Start it
+// - Stop it
+// - Loop it
+// - Pause it
+// - Set the volume
+// - Set the pitch (rate)
+// - Pan the sound
+// - Change these settings dynamically over time
+
+class Sound {
+public:
+ Sound();
+ ~Sound();
+
+ // We only have one access point here because we should
+ // only be opening an AIFF file from a file name. We're
+ // not using the resource fork string resources.
+ void initFromAIFFFile(const Common::String &fileName);
+
+ // Unlike the original game, we're going to use a regular
+ // audio stream for sound spots. The original treated them
+ // as movies.
+ void initFromQuickTime(const Common::String &fileName);
+
+ void disposeSound();
+ bool isSoundLoaded() const;
+ void playSound();
+ void loopSound();
+ void playSoundSegment(uint32 start, uint32 end);
+ void stopSound();
+ void setVolume(const uint16 volume);
+ bool isPlaying();
+
+ void attachFader(SoundFader *fader);
+
+protected:
+ Audio::SeekableAudioStream *_stream;
+ Audio::SoundHandle _handle;
+ byte _volume;
+
+ SoundFader *_fader;
+};
+
+// TODO: Make this class follow TimeBase better
+// Right now it's just a loose wrapper to plug callbacks
+// into sounds. Since this is only used for spot sounds,
+// I'm not too worried about it right now as its usage
+// is very limited.
+// At the very least, the regular TimeBase functions for
+// setting/getting should be neutered.
+class SoundTimeBase : public Sound, public TimeBase {
+public:
+ SoundTimeBase();
+ ~SoundTimeBase() {}
+
+ void playSoundSegment(uint32 start, uint32 end);
+
+protected:
+ void updateTime();
+
+private:
+ bool _setToStart;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/surface.cpp b/engines/pegasus/surface.cpp
new file mode 100644
index 0000000000..cdcb3c6e79
--- /dev/null
+++ b/engines/pegasus/surface.cpp
@@ -0,0 +1,396 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/file.h"
+#include "common/macresman.h"
+#include "common/stream.h"
+#include "common/system.h"
+#include "graphics/surface.h"
+#include "graphics/decoders/pict.h"
+#include "video/video_decoder.h"
+
+#include "pegasus/pegasus.h"
+#include "pegasus/surface.h"
+
+namespace Pegasus {
+
+Surface::Surface() {
+ _ownsSurface = false;
+ _surface = 0;
+}
+
+Surface::~Surface() {
+ deallocateSurface();
+}
+
+void Surface::deallocateSurface() {
+ if (_surface) {
+ if (_ownsSurface) {
+ _surface->free();
+ delete _surface;
+ }
+
+ _surface = 0;
+ _bounds = Common::Rect();
+ _ownsSurface = false;
+ }
+}
+
+void Surface::shareSurface(Surface *surface) {
+ deallocateSurface();
+
+ if (surface) {
+ _ownsSurface = false;
+ _surface = surface->getSurface();
+ surface->getSurfaceBounds(_bounds);
+ }
+}
+
+void Surface::allocateSurface(const Common::Rect &bounds) {
+ deallocateSurface();
+
+ if (bounds.isEmpty())
+ return;
+
+ _bounds = bounds;
+ _surface = new Graphics::Surface();
+ _surface->create(bounds.width(), bounds.height(), g_system->getScreenFormat());
+ _ownsSurface = true;
+}
+
+void Surface::getImageFromPICTFile(const Common::String &fileName) {
+ Common::File pict;
+ if (!pict.open(fileName))
+ error("Could not open picture '%s'", fileName.c_str());
+
+ if (!getImageFromPICTStream(&pict))
+ error("Failed to load PICT '%s'", fileName.c_str());
+}
+
+void Surface::getImageFromPICTResource(Common::MacResManager *resFork, uint16 id) {
+ Common::SeekableReadStream *res = resFork->getResource(MKTAG('P', 'I', 'C', 'T'), id);
+ if (!res)
+ error("Could not open PICT resource %d from '%s'", id, resFork->getBaseFileName().c_str());
+
+ if (!getImageFromPICTStream(res))
+ error("Failed to load PICT resource %d from '%s'", id, resFork->getBaseFileName().c_str());
+
+ delete res;
+}
+
+bool Surface::getImageFromPICTStream(Common::SeekableReadStream *stream) {
+ Graphics::PICTDecoder pict;
+
+ if (!pict.loadStream(*stream))
+ return false;
+
+ _surface = pict.getSurface()->convertTo(g_system->getScreenFormat(), pict.getPalette());
+ _ownsSurface = true;
+ _bounds = Common::Rect(0, 0, _surface->w, _surface->h);
+ return true;
+}
+
+void Surface::getImageFromMovieFrame(Video::VideoDecoder *video, TimeValue time) {
+ video->seek(Audio::Timestamp(0, time, 600));
+ const Graphics::Surface *frame = video->decodeNextFrame();
+
+ if (frame) {
+ if (!_surface)
+ _surface = new Graphics::Surface();
+
+ _surface->copyFrom(*frame);
+ _ownsSurface = true;
+ _bounds = Common::Rect(0, 0, _surface->w, _surface->h);
+ } else {
+ deallocateSurface();
+ }
+}
+
+void Surface::copyToCurrentPort() const {
+ copyToCurrentPort(_bounds);
+}
+
+void Surface::copyToCurrentPortTransparent() const {
+ copyToCurrentPortTransparent(_bounds);
+}
+
+void Surface::copyToCurrentPort(const Common::Rect &rect) const {
+ copyToCurrentPort(rect, rect);
+}
+
+void Surface::copyToCurrentPortTransparent(const Common::Rect &rect) const {
+ copyToCurrentPortTransparent(rect, rect);
+}
+
+void Surface::copyToCurrentPort(const Common::Rect &srcRect, const Common::Rect &dstRect) const {
+ Graphics::Surface *screen = ((PegasusEngine *)g_engine)->_gfx->getCurSurface();
+ byte *src = (byte *)_surface->getBasePtr(srcRect.left, srcRect.top);
+ byte *dst = (byte *)screen->getBasePtr(dstRect.left, dstRect.top);
+
+ int lineSize = srcRect.width() * _surface->format.bytesPerPixel;
+
+ for (int y = 0; y < srcRect.height(); y++) {
+ memcpy(dst, src, lineSize);
+ src += _surface->pitch;
+ dst += screen->pitch;
+ }
+}
+
+void Surface::copyToCurrentPortTransparent(const Common::Rect &srcRect, const Common::Rect &dstRect) const {
+ Graphics::Surface *screen = ((PegasusEngine *)g_engine)->_gfx->getCurSurface();
+ byte *src = (byte *)_surface->getBasePtr(srcRect.left, srcRect.top);
+ byte *dst = (byte *)screen->getBasePtr(dstRect.left, dstRect.top);
+
+ int lineSize = srcRect.width() * _surface->format.bytesPerPixel;
+
+ for (int y = 0; y < srcRect.height(); y++) {
+ for (int x = 0; x < srcRect.width(); x++) {
+ if (g_system->getScreenFormat().bytesPerPixel == 2) {
+ uint16 color = READ_UINT16(src);
+ if (!isTransparent(color))
+ memcpy(dst, src, 2);
+ } else if (g_system->getScreenFormat().bytesPerPixel == 4) {
+ uint32 color = READ_UINT32(src);
+ if (!isTransparent(color))
+ memcpy(dst, src, 4);
+ }
+
+ src += g_system->getScreenFormat().bytesPerPixel;
+ dst += g_system->getScreenFormat().bytesPerPixel;
+ }
+
+ src += _surface->pitch - lineSize;
+ dst += screen->pitch - lineSize;
+ }
+}
+
+void Surface::copyToCurrentPortMasked(const Common::Rect &srcRect, const Common::Rect &dstRect, const Surface *mask) const {
+ Graphics::Surface *screen = ((PegasusEngine *)g_engine)->_gfx->getCurSurface();
+ byte *src = (byte *)_surface->getBasePtr(srcRect.left, srcRect.top);
+ byte *dst = (byte *)screen->getBasePtr(dstRect.left, dstRect.top);
+
+ int lineSize = srcRect.width() * _surface->format.bytesPerPixel;
+
+ for (int y = 0; y < srcRect.height(); y++) {
+ byte *maskSrc = (byte *)mask->getSurface()->getBasePtr(0, y);
+
+ for (int x = 0; x < srcRect.width(); x++) {
+ if (g_system->getScreenFormat().bytesPerPixel == 2) {
+ uint16 color = READ_UINT16(maskSrc);
+ if (!isTransparent(color))
+ memcpy(dst, src, 2);
+ } else if (g_system->getScreenFormat().bytesPerPixel == 4) {
+ uint32 color = READ_UINT32(maskSrc);
+ if (!isTransparent(color))
+ memcpy(dst, src, 4);
+ }
+
+ src += g_system->getScreenFormat().bytesPerPixel;
+ maskSrc += g_system->getScreenFormat().bytesPerPixel;
+ dst += g_system->getScreenFormat().bytesPerPixel;
+ }
+
+ src += _surface->pitch - lineSize;
+ dst += screen->pitch - lineSize;
+ }
+}
+
+void Surface::copyToCurrentPortTransparentGlow(const Common::Rect &srcRect, const Common::Rect &dstRect) const {
+ // This is the same as copyToCurrentPortTransparent(), but turns the red value of each
+ // pixel all the way up.
+
+ Graphics::Surface *screen = ((PegasusEngine *)g_engine)->_gfx->getCurSurface();
+ byte *src = (byte *)_surface->getBasePtr(srcRect.left, srcRect.top);
+ byte *dst = (byte *)screen->getBasePtr(dstRect.left, dstRect.top);
+
+ int lineSize = srcRect.width() * _surface->format.bytesPerPixel;
+
+ for (int y = 0; y < srcRect.height(); y++) {
+ for (int x = 0; x < srcRect.width(); x++) {
+ if (g_system->getScreenFormat().bytesPerPixel == 2) {
+ uint16 color = READ_UINT16(src);
+ if (!isTransparent(color))
+ WRITE_UINT16(dst, getGlowColor(color));
+ } else if (g_system->getScreenFormat().bytesPerPixel == 4) {
+ uint32 color = READ_UINT32(src);
+ if (!isTransparent(color))
+ WRITE_UINT32(dst, getGlowColor(color));
+ }
+
+ src += g_system->getScreenFormat().bytesPerPixel;
+ dst += g_system->getScreenFormat().bytesPerPixel;
+ }
+
+ src += _surface->pitch - lineSize;
+ dst += screen->pitch - lineSize;
+ }
+}
+
+void Surface::scaleTransparentCopy(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);
+
+ Graphics::Surface *screen = ((PegasusEngine *)g_engine)->_gfx->getCurSurface();
+
+ int srcW = srcRect.width();
+ int srcH = srcRect.height();
+ int dstW = dstRect.width();
+ int dstH = dstRect.height();
+
+ for (int y = 0; y < dstH; y++) {
+ for (int x = 0; x < dstW; x++) {
+ if (g_system->getScreenFormat().bytesPerPixel == 2) {
+ uint16 color = READ_UINT16((byte *)_surface->getBasePtr(
+ x * srcW / dstW + srcRect.left,
+ y * srcH / dstH + srcRect.top));
+ if (!isTransparent(color))
+ WRITE_UINT16((byte *)screen->getBasePtr(x + dstRect.left, y + dstRect.top), color);
+ } else if (g_system->getScreenFormat().bytesPerPixel == 4) {
+ uint32 color = READ_UINT32((byte *)_surface->getBasePtr(
+ x * srcW / dstW + srcRect.left,
+ y * srcH / dstH + srcRect.top));
+ if (!isTransparent(color))
+ WRITE_UINT32((byte *)screen->getBasePtr(x + dstRect.left, y + dstRect.top), color);
+ }
+ }
+ }
+}
+
+void Surface::scaleTransparentCopyGlow(const Common::Rect &srcRect, const Common::Rect &dstRect) const {
+ // This is the same as scaleTransparentCopy(), but turns the red value of each
+ // pixel all the way up.
+
+ Graphics::Surface *screen = ((PegasusEngine *)g_engine)->_gfx->getCurSurface();
+
+ int srcW = srcRect.width();
+ int srcH = srcRect.height();
+ int dstW = dstRect.width();
+ int dstH = dstRect.height();
+
+ for (int y = 0; y < dstH; y++) {
+ for (int x = 0; x < dstW; x++) {
+ if (g_system->getScreenFormat().bytesPerPixel == 2) {
+ uint16 color = READ_UINT16((byte *)_surface->getBasePtr(
+ x * srcW / dstW + srcRect.left,
+ y * srcH / dstH + srcRect.top));
+ if (!isTransparent(color))
+ WRITE_UINT16((byte *)screen->getBasePtr(x + dstRect.left, y + dstRect.top), getGlowColor(color));
+ } else if (g_system->getScreenFormat().bytesPerPixel == 4) {
+ uint32 color = READ_UINT32((byte *)_surface->getBasePtr(
+ x * srcW / dstW + srcRect.left,
+ y * srcH / dstH + srcRect.top));
+ if (!isTransparent(color))
+ WRITE_UINT32((byte *)screen->getBasePtr(x + dstRect.left, y + dstRect.top), getGlowColor(color));
+ }
+ }
+ }
+}
+
+uint32 Surface::getGlowColor(uint32 color) const {
+ // Can't just 'or' it on like the original did :P
+ byte r, g, b;
+ g_system->getScreenFormat().colorToRGB(color, r, g, b);
+ return g_system->getScreenFormat().RGBToColor(0xff, g, b);
+}
+
+bool Surface::isTransparent(uint32 color) const {
+ // HACK: Seems we're truncating some color data somewhere...
+ uint32 transColor1 = g_system->getScreenFormat().RGBToColor(0xff, 0xff, 0xff);
+ uint32 transColor2 = g_system->getScreenFormat().RGBToColor(0xf8, 0xf8, 0xf8);
+
+ return color == transColor1 || color == transColor2;
+}
+
+PixelImage::PixelImage() {
+ _transparent = false;
+}
+
+void PixelImage::drawImage(const Common::Rect &sourceBounds, const Common::Rect &destBounds) {
+ if (!isSurfaceValid())
+ return;
+
+ // Draw from sourceBounds to destBounds based on _transparent
+ if (_transparent)
+ copyToCurrentPortTransparent(sourceBounds, destBounds);
+ else
+ copyToCurrentPort(sourceBounds, destBounds);
+}
+
+void Frame::initFromPICTFile(const Common::String &fileName, bool transparent) {
+ getImageFromPICTFile(fileName);
+ _transparent = transparent;
+}
+
+void Frame::initFromPICTResource(Common::MacResManager *resFork, uint16 id, bool transparent) {
+ getImageFromPICTResource(resFork, id);
+ _transparent = transparent;
+}
+
+void Frame::initFromMovieFrame(Video::VideoDecoder *video, TimeValue time, bool transparent) {
+ getImageFromMovieFrame(video, time);
+ _transparent = transparent;
+}
+
+void Picture::draw(const Common::Rect &r) {
+ Common::Rect surfaceBounds;
+ getSurfaceBounds(surfaceBounds);
+ Common::Rect r1 = r;
+
+ Common::Rect bounds;
+ getBounds(bounds);
+ surfaceBounds.moveTo(bounds.left, bounds.top);
+ r1 = r1.findIntersectingRect(surfaceBounds);
+ getSurfaceBounds(surfaceBounds);
+
+ Common::Rect r2 = r1;
+ r2.translate(surfaceBounds.left - bounds.left, surfaceBounds.top - bounds.top);
+ drawImage(r2, r1);
+}
+
+void Picture::initFromPICTFile(const Common::String &fileName, bool transparent) {
+ Frame::initFromPICTFile(fileName, transparent);
+
+ Common::Rect surfaceBounds;
+ getSurfaceBounds(surfaceBounds);
+ sizeElement(surfaceBounds.width(), surfaceBounds.height());
+}
+
+void Picture::initFromPICTResource(Common::MacResManager *resFork, uint16 id, bool transparent) {
+ Frame::initFromPICTResource(resFork, id, transparent);
+
+ Common::Rect surfaceBounds;
+ getSurfaceBounds(surfaceBounds);
+ sizeElement(surfaceBounds.width(), surfaceBounds.height());
+}
+
+void Picture::initFromMovieFrame(Video::VideoDecoder *video, TimeValue time, bool transparent) {
+ Frame::initFromMovieFrame(video, time, transparent);
+
+ Common::Rect surfaceBounds;
+ getSurfaceBounds(surfaceBounds);
+ sizeElement(surfaceBounds.width(), surfaceBounds.height());
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/surface.h b/engines/pegasus/surface.h
new file mode 100644
index 0000000000..47e3ef538c
--- /dev/null
+++ b/engines/pegasus/surface.h
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_SURFACE_H
+#define PEGASUS_SURFACE_H
+
+#include "common/rect.h"
+#include "common/str.h"
+
+#include "pegasus/elements.h"
+#include "pegasus/types.h"
+
+namespace Common {
+ class MacResManager;
+}
+
+namespace Graphics {
+ struct Surface;
+}
+
+namespace Video {
+ class VideoDecoder;
+}
+
+namespace Pegasus {
+
+// Surface bounds are always normalized.
+
+class Surface {
+public:
+ Surface();
+ virtual ~Surface();
+
+ virtual void allocateSurface(const Common::Rect &);
+ virtual void deallocateSurface();
+ virtual void shareSurface(Surface *surface);
+ bool isSurfaceValid() const { return _surface != 0; }
+
+ Graphics::Surface *getSurface() const { return _surface; }
+ void getSurfaceBounds(Common::Rect &r) { r = _bounds; }
+
+ // None of the copyToCurrentPort* functions do any sanity checks.
+ // It's up to clients to make sure that the Surface is valid.
+ void copyToCurrentPort() const;
+ void copyToCurrentPortTransparent() const;
+ void copyToCurrentPort(const Common::Rect &) const;
+ void copyToCurrentPortTransparent(const Common::Rect &) const;
+ void copyToCurrentPort(const Common::Rect &, const Common::Rect &) const;
+ void copyToCurrentPortTransparent(const Common::Rect &, const Common::Rect &) const;
+ void copyToCurrentPortMasked(const Common::Rect &, const Common::Rect &, const Surface *) const;
+ void copyToCurrentPortTransparentGlow(const Common::Rect &, const Common::Rect &) const;
+ void scaleTransparentCopy(const Common::Rect &, const Common::Rect &) const;
+ void scaleTransparentCopyGlow(const Common::Rect &, const Common::Rect &) const;
+
+ virtual void getImageFromPICTFile(const Common::String &fileName);
+ virtual void getImageFromPICTResource(Common::MacResManager *resFork, uint16 id);
+ virtual void getImageFromMovieFrame(Video::VideoDecoder *, TimeValue);
+
+protected:
+ bool _ownsSurface;
+ Graphics::Surface *_surface;
+ Common::Rect _bounds;
+
+private:
+ bool getImageFromPICTStream(Common::SeekableReadStream *stream);
+
+ uint32 getGlowColor(uint32 color) const;
+ bool isTransparent(uint32 color) const;
+};
+
+class PixelImage : public Surface {
+public:
+ PixelImage();
+ virtual ~PixelImage() {}
+
+ void drawImage(const Common::Rect &, const Common::Rect &);
+
+protected:
+ virtual void setTransparent(bool transparent) { _transparent = transparent; }
+
+ bool _transparent;
+};
+
+class Frame : public PixelImage {
+public:
+ Frame() {}
+ virtual ~Frame() {}
+
+ virtual void initFromPICTFile(const Common::String &fileName, bool transparent = false);
+ virtual void initFromPICTResource(Common::MacResManager *resFork, uint16 id, bool transparent = false);
+ virtual void initFromMovieFrame(Video::VideoDecoder *, TimeValue, bool transparent = false);
+};
+
+class SpriteFrame : public Frame {
+friend class Sprite;
+public:
+ SpriteFrame() { _referenceCount = 0; }
+ virtual ~SpriteFrame() {}
+
+protected:
+ uint32 _referenceCount;
+};
+
+class Picture : public DisplayElement, public Frame {
+public:
+ Picture(const DisplayElementID id) : DisplayElement(id) {}
+ virtual ~Picture() {}
+
+ virtual void initFromPICTFile(const Common::String &fileName, bool transparent = false);
+ virtual void initFromPICTResource(Common::MacResManager *resFork, uint16 id, bool transparent = false);
+ virtual void initFromMovieFrame(Video::VideoDecoder *, TimeValue, bool transparent = false);
+
+ virtual void draw(const Common::Rect &);
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/timers.cpp b/engines/pegasus/timers.cpp
new file mode 100644
index 0000000000..3b875038cc
--- /dev/null
+++ b/engines/pegasus/timers.cpp
@@ -0,0 +1,429 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "pegasus/pegasus.h"
+#include "pegasus/notification.h"
+#include "pegasus/timers.h"
+
+namespace Pegasus {
+
+Idler::Idler() {
+ _isIdling = false;
+ _nextIdler = 0;
+ _prevIdler = 0;
+}
+
+Idler::~Idler() {
+ stopIdling();
+}
+
+void Idler::startIdling() {
+ if (!isIdling()) {
+ ((PegasusEngine *)g_engine)->addIdler(this);
+ _isIdling = true;
+ }
+}
+
+void Idler::stopIdling() {
+ if (isIdling()) {
+ ((PegasusEngine *)g_engine)->removeIdler(this);
+ _isIdling = false;
+ }
+}
+
+TimeBase::TimeBase(const TimeScale preferredScale) {
+ _preferredScale = preferredScale;
+ _callBackList = 0;
+ _paused = false;
+ _flags = 0;
+ _lastMillis = 0;
+ _time = 0;
+ _rate = 0;
+ _startTime = 0;
+ _startScale = 1;
+ _stopTime = 0xffffffff;
+ _stopScale = 1;
+ _master = 0;
+ _pausedRate = 0;
+ _pauseStart = 0;
+
+ ((PegasusEngine *)g_engine)->addTimeBase(this);
+}
+
+TimeBase::~TimeBase() {
+ if (_master)
+ _master->_slaves.remove(this);
+
+ ((PegasusEngine *)g_engine)->removeTimeBase(this);
+ disposeAllCallBacks();
+
+ // TODO: Remove slaves? Make them remove themselves?
+}
+
+void TimeBase::setTime(const TimeValue time, const TimeScale scale) {
+ _time = Common::Rational(time, (scale == 0) ? _preferredScale : scale);
+ _lastMillis = 0;
+}
+
+TimeValue TimeBase::getTime(const TimeScale scale) {
+ return _time.getNumerator() * ((scale == 0) ? _preferredScale : scale) / _time.getDenominator();
+}
+
+void TimeBase::setRate(const Common::Rational rate) {
+ _rate = rate;
+
+ if (_rate == 0)
+ _paused = false;
+}
+
+Common::Rational TimeBase::getEffectiveRate() const {
+ return _rate * ((_master == 0) ? 1 : _master->getEffectiveRate());
+}
+
+void TimeBase::start() {
+ if (_paused)
+ _pausedRate = 1;
+ else
+ setRate(1);
+}
+
+void TimeBase::stop() {
+ setRate(0);
+ _paused = false;
+}
+
+void TimeBase::pause() {
+ if (isRunning() && !_paused) {
+ _pausedRate = getRate();
+ stop();
+ _paused = true;
+ _pauseStart = g_system->getMillis();
+ }
+}
+
+void TimeBase::resume() {
+ if (_paused) {
+ setRate(_pausedRate);
+ _paused = false;
+
+ if (isRunning())
+ _lastMillis += g_system->getMillis() - _pauseStart;
+ }
+}
+
+bool TimeBase::isRunning() {
+ if (_paused && _pausedRate != 0)
+ return true;
+
+ Common::Rational rate = getRate();
+
+ if (rate == 0)
+ return false;
+
+ if (getFlags() & kLoopTimeBase)
+ return true;
+
+ if (rate > 0)
+ return getTime() != getStop();
+
+ return getTime() != getStart();
+}
+
+void TimeBase::setStart(const TimeValue startTime, const TimeScale scale) {
+ _startTime = startTime;
+ _startScale = (scale == 0) ? _preferredScale : scale;
+}
+
+TimeValue TimeBase::getStart(const TimeScale scale) const {
+ if (scale)
+ return _startTime * scale / _startScale;
+
+ return _startTime * _preferredScale / _startScale;
+}
+
+void TimeBase::setStop(const TimeValue stopTime, const TimeScale scale) {
+ _stopTime = stopTime;
+ _stopScale = (scale == 0) ? _preferredScale : scale;
+}
+
+TimeValue TimeBase::getStop(const TimeScale scale) const {
+ if (scale)
+ return _stopTime * scale / _stopScale;
+
+ return _stopTime * _preferredScale / _stopScale;
+}
+
+void TimeBase::setSegment(const TimeValue startTime, const TimeValue stopTime, const TimeScale scale) {
+ setStart(startTime, scale);
+ setStop(stopTime, scale);
+}
+
+void TimeBase::getSegment(TimeValue &startTime, TimeValue &stopTime, const TimeScale scale) const {
+ startTime = getStart(scale);
+ stopTime = getStop(scale);
+}
+
+TimeValue TimeBase::getDuration(const TimeScale scale) const {
+ TimeValue startTime, stopTime;
+ getSegment(startTime, stopTime, scale);
+ return stopTime - startTime;
+}
+
+void TimeBase::setMasterTimeBase(TimeBase *tb) {
+ // TODO: We're just ignoring the master (except for effective rate)
+ // for now to simplify things
+ if (_master)
+ _master->_slaves.remove(this);
+
+ _master = tb;
+
+ if (_master)
+ _master->_slaves.push_back(this);
+}
+
+void TimeBase::updateTime() {
+ if (_lastMillis == 0) {
+ _lastMillis = g_system->getMillis();
+ } else {
+ uint32 curTime = g_system->getMillis();
+ if (_lastMillis == curTime) // No change
+ return;
+
+ _time += Common::Rational(curTime - _lastMillis, 1000) * getEffectiveRate();
+ _lastMillis = curTime;
+ }
+}
+
+void TimeBase::checkCallBacks() {
+ // Nothing to do if we're paused or not running
+ if (_paused || !isRunning())
+ return;
+
+ Common::Rational startTime = Common::Rational(_startTime, _startScale);
+ Common::Rational stopTime = Common::Rational(_stopTime, _stopScale);
+
+ // First step: update the times
+ updateTime();
+
+ // Clip time to the boundaries
+ if (_time >= stopTime)
+ _time = stopTime;
+ else if (_time <= startTime)
+ _time = startTime;
+
+ // TODO: Update the slaves?
+
+ Common::Rational time = Common::Rational(getTime(), getScale());
+
+ // Check if we've triggered any callbacks
+ for (TimeBaseCallBack *runner = _callBackList; runner != 0; runner = runner->_nextCallBack) {
+ if (runner->_hasBeenTriggered)
+ continue;
+
+ if (runner->_type == kCallBackAtTime && runner->_trigger == kTriggerTimeFwd) {
+ if (getTime() >= (runner->_param2 * _preferredScale / runner->_param3) && getRate() > 0) {
+ uint param2 = runner->_param2, param3 = runner->_param3;
+ runner->callBack();
+ // HACK: Only stop future time forward callbacks if the parameters have not been changed
+ // This fixes striding callbacks. Since only striding callbacks do this kind of
+ // craziness, I'm not too worried about this.
+ runner->_hasBeenTriggered = (runner->_param2 == param2 && runner->_param3 == param3);
+ }
+ } else if (runner->_type == kCallBackAtExtremes) {
+ if (runner->_trigger == kTriggerAtStop) {
+ if (time == stopTime) {
+ runner->callBack();
+ runner->_hasBeenTriggered = true;
+ }
+ } else if (runner->_trigger == kTriggerAtStart) {
+ if (time == startTime) {
+ runner->callBack();
+ runner->_hasBeenTriggered = true;
+ }
+ }
+ }
+ }
+
+ if (getFlags() & kLoopTimeBase) {
+ // Loop if necessary
+ if (getRate() < 0 && time == startTime)
+ setTime(_stopTime, _stopScale);
+ else if (getRate() > 0 && time == stopTime)
+ setTime(_startTime, _startScale);
+ } else {
+ // Stop at the end
+ if ((getRate() > 0 && time == stopTime) || (getRate() < 0 && time == startTime))
+ stop();
+ }
+}
+
+// Protected functions only called by TimeBaseCallBack.
+
+void TimeBase::addCallBack(TimeBaseCallBack *callBack) {
+ callBack->_nextCallBack = _callBackList;
+ _callBackList = callBack;
+}
+
+void TimeBase::removeCallBack(TimeBaseCallBack *callBack) {
+ if (_callBackList == callBack) {
+ _callBackList = callBack->_nextCallBack;
+ } else {
+ TimeBaseCallBack *runner, *prevRunner;
+
+ for (runner = _callBackList->_nextCallBack, prevRunner = _callBackList; runner != callBack; prevRunner = runner, runner = runner->_nextCallBack)
+ ;
+
+ prevRunner->_nextCallBack = runner->_nextCallBack;
+ }
+
+ callBack->_nextCallBack = 0;
+}
+
+void TimeBase::disposeAllCallBacks() {
+ TimeBaseCallBack *nextRunner;
+
+ for (TimeBaseCallBack *runner = _callBackList; runner != 0; runner = nextRunner) {
+ nextRunner = runner->_nextCallBack;
+ runner->disposeCallBack();
+ runner->_nextCallBack = 0;
+ }
+
+ _callBackList = 0;
+}
+
+TimeBaseCallBack::TimeBaseCallBack() {
+ _timeBase = 0;
+ _nextCallBack = 0;
+ _trigger = kTriggerNone;
+ _type = kCallBackNone;
+ _hasBeenTriggered = false;
+}
+
+TimeBaseCallBack::~TimeBaseCallBack() {
+ releaseCallBack();
+}
+
+void TimeBaseCallBack::initCallBack(TimeBase *tb, CallBackType type) {
+ releaseCallBack();
+ _timeBase = tb;
+ _timeBase->addCallBack(this);
+ _type = type;
+}
+
+void TimeBaseCallBack::releaseCallBack() {
+ if (_timeBase)
+ _timeBase->removeCallBack(this);
+ disposeCallBack();
+}
+
+void TimeBaseCallBack::disposeCallBack() {
+ _timeBase = 0;
+ _hasBeenTriggered = false;
+}
+
+void TimeBaseCallBack::scheduleCallBack(CallBackTrigger trigger, uint32 param2, uint32 param3) {
+ // TODO: Rename param2/param3?
+ _trigger = trigger;
+ _param2 = param2;
+ _param3 = param3;
+ _hasBeenTriggered = false;
+}
+
+void TimeBaseCallBack::cancelCallBack() {
+ _trigger = kTriggerNone;
+ _hasBeenTriggered = false;
+}
+
+IdlerTimeBase::IdlerTimeBase() {
+ _lastTime = 0xffffffff;
+ startIdling();
+}
+
+void IdlerTimeBase::useIdleTime() {
+ uint32 currentTime = getTime();
+ if (currentTime != _lastTime) {
+ _lastTime = currentTime;
+ timeChanged(_lastTime);
+ }
+}
+
+NotificationCallBack::NotificationCallBack() {
+ _callBackFlag = 0;
+ _notifier = 0;
+}
+
+void NotificationCallBack::callBack() {
+ if (_notifier)
+ _notifier->setNotificationFlags(_callBackFlag, _callBackFlag);
+}
+
+static const NotificationFlags kFuseExpiredFlag = 1;
+
+Fuse::Fuse() : _fuseNotification(0, (NotificationManager *)((PegasusEngine *)g_engine)) {
+ _fuseNotification.notifyMe(this, kFuseExpiredFlag, kFuseExpiredFlag);
+ _fuseCallBack.setNotification(&_fuseNotification);
+ _fuseCallBack.initCallBack(&_fuseTimer, kCallBackAtExtremes);
+ _fuseCallBack.setCallBackFlag(kFuseExpiredFlag);
+}
+
+void Fuse::primeFuse(const TimeValue frequency, const TimeScale scale) {
+ stopFuse();
+ _fuseTimer.setScale(scale);
+ _fuseTimer.setSegment(0, frequency);
+ _fuseTimer.setTime(0);
+}
+
+void Fuse::lightFuse() {
+ if (!_fuseTimer.isRunning()) {
+ _fuseCallBack.scheduleCallBack(kTriggerAtStop, 0, 0);
+ _fuseTimer.start();
+ }
+}
+
+void Fuse::stopFuse() {
+ _fuseTimer.stop();
+ _fuseCallBack.cancelCallBack();
+ // Make sure the fuse has not triggered but not been caught yet...
+ _fuseNotification.setNotificationFlags(0, 0xffffffff);
+}
+
+void Fuse::advanceFuse(const TimeValue time) {
+ if (_fuseTimer.isRunning()) {
+ _fuseTimer.stop();
+ _fuseTimer.setTime(_fuseTimer.getTime() + time);
+ _fuseTimer.start();
+ }
+}
+
+TimeValue Fuse::getTimeRemaining() {
+ return _fuseTimer.getStop() - _fuseTimer.getTime();
+}
+
+void Fuse::receiveNotification(Notification *, const NotificationFlags) {
+ stopFuse();
+ invokeAction();
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/timers.h b/engines/pegasus/timers.h
new file mode 100644
index 0000000000..bcdca6e860
--- /dev/null
+++ b/engines/pegasus/timers.h
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_TIMERS_H
+#define PEGASUS_TIMERS_H
+
+#include "common/list.h"
+#include "common/rational.h"
+#include "common/func.h"
+
+#include "pegasus/constants.h"
+#include "pegasus/notification.h"
+#include "pegasus/util.h"
+
+namespace Pegasus {
+
+class Idler {
+friend class PegasusEngine;
+
+public:
+ Idler();
+ virtual ~Idler();
+
+ virtual void startIdling();
+ virtual void stopIdling();
+ bool isIdling() const { return _isIdling; }
+
+protected:
+ virtual void useIdleTime() {}
+
+ bool _isIdling;
+ Idler *_nextIdler, *_prevIdler;
+};
+
+enum {
+ kLoopTimeBase = 1,
+ kPalindromeLoopTimeBase = 2,
+ kMaintainTimeBaseZero = 4
+};
+
+class TimeBaseCallBack;
+
+class TimeBase {
+friend class TimeBaseCallBack;
+public:
+ TimeBase(const TimeScale = kDefaultTimeScale);
+ virtual ~TimeBase();
+
+ virtual void setTime(const TimeValue, const TimeScale = 0);
+ virtual TimeValue getTime(const TimeScale = 0);
+
+ virtual void setScale(const TimeScale scale) { _preferredScale = scale; }
+ virtual TimeScale getScale() const { return _preferredScale; }
+
+ virtual void setRate(const Common::Rational);
+ virtual Common::Rational getRate() const { return _rate; }
+
+ virtual void start();
+ virtual void stop();
+ virtual bool isRunning();
+
+ virtual void pause();
+ virtual void resume();
+ bool isPaused() const { return _paused; }
+
+ virtual void setFlags(const uint32 flags) { _flags = flags; }
+ virtual uint32 getFlags() const { return _flags; }
+
+ virtual void setStart(const TimeValue, const TimeScale = 0);
+ virtual TimeValue getStart(const TimeScale = 0) const;
+
+ virtual void setStop(const TimeValue, const TimeScale = 0);
+ virtual TimeValue getStop(const TimeScale = 0) const;
+
+ virtual void setSegment(const TimeValue, const TimeValue, const TimeScale = 0);
+ virtual void getSegment(TimeValue&, TimeValue&, const TimeScale = 0) const;
+
+ virtual TimeValue getDuration(const TimeScale = 0) const;
+
+ virtual void setMasterTimeBase(TimeBase *timeBase);
+
+ void disposeAllCallBacks();
+
+ // ScummVM's API additions (to replace the need for actual timers)
+ virtual void checkCallBacks();
+
+protected:
+ void addCallBack(TimeBaseCallBack *);
+ void removeCallBack(TimeBaseCallBack *);
+ virtual void updateTime();
+
+ TimeBase *_master;
+ TimeScale _preferredScale;
+ TimeBaseCallBack *_callBackList;
+ Common::Rational _rate, _pausedRate;
+ bool _paused;
+ uint32 _startTime, _startScale;
+ uint32 _stopTime, _stopScale;
+ uint32 _flags;
+
+ Common::Rational _time;
+ uint32 _lastMillis, _pauseStart;
+
+private:
+ Common::Rational getEffectiveRate() const;
+
+ Common::List<TimeBase *> _slaves;
+};
+
+// Type passed to initCallBack()
+enum CallBackType {
+ kCallBackNone = 0,
+ kCallBackAtTime = 1,
+ kCallBackAtExtremes = 4
+};
+
+// Trigger passed to scheduleCallBack()
+enum CallBackTrigger {
+ kTriggerNone = 0,
+
+ // AtTime flags
+ kTriggerTimeFwd = 1,
+
+ // AtExtremes flags
+ kTriggerAtStart = 1,
+ kTriggerAtStop = 2
+};
+
+class TimeBaseCallBack {
+friend class TimeBase;
+
+public:
+ TimeBaseCallBack();
+ virtual ~TimeBaseCallBack();
+
+ void initCallBack(TimeBase *, CallBackType type);
+
+ void releaseCallBack();
+
+ void scheduleCallBack(CallBackTrigger trigger, uint32 param2, uint32 param3);
+ void cancelCallBack();
+
+protected:
+ virtual void callBack() = 0;
+
+ TimeBase *_timeBase;
+
+ // Owned and operated by TimeBase;
+ TimeBaseCallBack *_nextCallBack;
+
+ // Our storage of the QuickTime timer crap
+ CallBackType _type;
+ CallBackTrigger _trigger;
+ uint32 _param2, _param3;
+ bool _hasBeenTriggered;
+
+private:
+ void disposeCallBack();
+};
+
+class IdlerTimeBase : public Idler, public TimeBase {
+public:
+ IdlerTimeBase();
+ virtual ~IdlerTimeBase() { stopIdling(); }
+
+ TimeValue getLastTime() const { return _lastTime; }
+
+protected:
+ virtual void useIdleTime();
+ virtual void timeChanged(const TimeValue) {}
+
+ TimeValue _lastTime;
+
+};
+
+class NotificationCallBack : public TimeBaseCallBack {
+public:
+ NotificationCallBack();
+ virtual ~NotificationCallBack() {}
+
+ void setNotification(Notification *notifier) { _notifier = notifier; }
+
+ void setCallBackFlag(const NotificationFlags flag) { _callBackFlag = flag; }
+ NotificationFlags getCallBackFlag() const { return _callBackFlag; }
+
+protected:
+ void callBack();
+
+ Notification *_notifier;
+ NotificationFlags _callBackFlag;
+};
+
+class DynamicElement : public TimeBase {
+public:
+ TimeValue percentSeconds(const uint32 percent) { return getScale() * percent / 100; }
+};
+
+class Fuse : private NotificationReceiver {
+public:
+ Fuse();
+ virtual ~Fuse() {}
+
+ void primeFuse(const TimeValue, const TimeScale = 1); // An appropriately named function :P
+ void lightFuse();
+ void stopFuse();
+ bool isFuseLit() { return _fuseTimer.isRunning() || _fuseTimer.isPaused(); }
+ void advanceFuse(const TimeValue);
+ TimeValue getTimeRemaining();
+ TimeScale getFuseScale() { return _fuseTimer.getScale(); }
+
+ void pauseFuse() { _fuseTimer.pause(); }
+ void resumeFuse() { _fuseTimer.resume(); }
+ bool isFusePaused() { return _fuseTimer.isPaused(); }
+
+protected:
+ virtual void receiveNotification(Notification *, const NotificationFlags);
+ virtual void invokeAction() {}
+
+ TimeBase _fuseTimer;
+ NotificationCallBack _fuseCallBack;
+ Notification _fuseNotification;
+};
+
+class FuseFunction : public Fuse {
+public:
+ FuseFunction() : _functor(0) {}
+ virtual ~FuseFunction() { delete _functor; }
+
+ void setFunctor(Common::Functor0<void> *functor) { delete _functor; _functor = functor; }
+protected:
+ virtual void invokeAction() { if (_functor && _functor->isValid()) (*_functor)(); }
+
+ Common::Functor0<void> *_functor;
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/transition.cpp b/engines/pegasus/transition.cpp
new file mode 100644
index 0000000000..1ae212df85
--- /dev/null
+++ b/engines/pegasus/transition.cpp
@@ -0,0 +1,200 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 "graphics/surface.h"
+
+#include "pegasus/transition.h"
+
+namespace Pegasus {
+
+ScreenFader::ScreenFader() {
+ _isBlack = true;
+ // Initially, assume screens are on at full brightness.
+ Fader::setFaderValue(100);
+ _screen = new Graphics::Surface();
+}
+
+ScreenFader::~ScreenFader() {
+ _screen->free();
+ delete _screen;
+}
+
+void ScreenFader::doFadeOutSync(const TimeValue duration, const TimeValue scale, bool isBlack) {
+ _isBlack = isBlack;
+ _screen->copyFrom(*g_system->lockScreen());
+ g_system->unlockScreen();
+
+ FaderMoveSpec spec;
+ spec.makeTwoKnotFaderSpec(scale, 0, getFaderValue(), duration, 0);
+ startFaderSync(spec);
+
+ _screen->free();
+}
+
+void ScreenFader::doFadeInSync(const TimeValue duration, const TimeValue scale, bool isBlack) {
+ _isBlack = isBlack;
+ _screen->copyFrom(*g_system->lockScreen());
+ g_system->unlockScreen();
+
+ FaderMoveSpec spec;
+ spec.makeTwoKnotFaderSpec(scale, 0, getFaderValue(), duration, 100);
+ startFaderSync(spec);
+
+ _screen->free();
+}
+
+void ScreenFader::setFaderValue(const int32 value) {
+ if (value != getFaderValue()) {
+ Fader::setFaderValue(value);
+
+ if (_screen->pixels) {
+ // 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.
+ Graphics::Surface *screen = g_system->lockScreen();
+
+ for (uint y = 0; y < _screen->h; y++) {
+ for (uint x = 0; x < _screen->w; x++) {
+ if (_screen->format.bytesPerPixel == 2)
+ WRITE_UINT16(screen->getBasePtr(x, y), fadePixel(READ_UINT16(_screen->getBasePtr(x, y)), value));
+ else
+ WRITE_UINT32(screen->getBasePtr(x, y), fadePixel(READ_UINT32(_screen->getBasePtr(x, y)), value));
+ }
+ }
+
+ g_system->unlockScreen();
+ g_system->updateScreen();
+ }
+ }
+}
+
+static inline byte fadeComponent(byte comp, int32 percent) {
+ return comp * percent / 100;
+}
+
+uint32 ScreenFader::fadePixel(uint32 color, int32 percent) const {
+ byte r, g, b;
+ g_system->getScreenFormat().colorToRGB(color, r, g, b);
+
+ if (_isBlack) {
+ r = fadeComponent(r, percent);
+ g = fadeComponent(g, percent);
+ b = fadeComponent(b, percent);
+ } else {
+ r = 0xFF - fadeComponent(0xFF - r, percent);
+ g = 0xFF - fadeComponent(0xFF - g, percent);
+ b = 0xFF - fadeComponent(0xFF - b, percent);
+ }
+
+ return g_system->getScreenFormat().RGBToColor(r, g, b);
+}
+
+Transition::Transition(const DisplayElementID id) : FaderAnimation(id) {
+ _outPicture = 0;
+ _inPicture = 0;
+}
+
+void Transition::setBounds(const Common::Rect &r) {
+ FaderAnimation::setBounds(r);
+ _boundsWidth = _bounds.width();
+ _boundsHeight = _bounds.height();
+}
+
+void Transition::setInAndOutElements(DisplayElement *inElement, DisplayElement *outElement) {
+ _inPicture = inElement;
+ _outPicture = outElement;
+
+ Common::Rect r;
+
+ if (_outPicture)
+ _outPicture->getBounds(r);
+ else if (_inPicture)
+ _inPicture->getBounds(r);
+
+ setBounds(r);
+}
+
+void Slide::draw(const Common::Rect &r) {
+ Common::Rect oldBounds, newBounds;
+
+ adjustSlideRects(oldBounds, newBounds);
+ drawElements(r, oldBounds, newBounds);
+}
+
+void Slide::adjustSlideRects(Common::Rect &oldBounds, Common::Rect &newBounds) {
+ oldBounds = _bounds;
+ newBounds = _bounds;
+}
+
+void Slide::drawElements(const Common::Rect &drawRect, const Common::Rect &oldBounds, const Common::Rect &newBounds) {
+ drawSlideElement(drawRect, oldBounds, _outPicture);
+ drawSlideElement(drawRect, newBounds, _inPicture);
+}
+
+void Slide::drawSlideElement(const Common::Rect &drawRect, const Common::Rect &oldBounds, DisplayElement *picture) {
+ if (picture && drawRect.intersects(oldBounds)) {
+ picture->moveElementTo(oldBounds.left, oldBounds.top);
+ picture->draw(drawRect.findIntersectingRect(oldBounds));
+ }
+}
+
+void Push::adjustSlideRects(Common::Rect &oldBounds, Common::Rect &newBounds) {
+ switch (_direction & kSlideHorizMask) {
+ case kSlideLeftMask:
+ newBounds.left = oldBounds.right = _bounds.right - pegasusRound(getFaderValue() * _boundsWidth, kTransitionRange);
+ newBounds.right = newBounds.left + _boundsWidth;
+ oldBounds.left = oldBounds.right - _boundsWidth;
+ break;
+ case kSlideRightMask:
+ oldBounds.left = newBounds.right = _bounds.left + pegasusRound(getFaderValue() * _boundsWidth, kTransitionRange);
+ oldBounds.right = oldBounds.left + _boundsWidth;
+ newBounds.left = newBounds.right - _boundsWidth;
+ break;
+ default:
+ newBounds.left = oldBounds.left = _bounds.left;
+ newBounds.right = oldBounds.right = _bounds.right;
+ break;
+ }
+
+ switch (_direction & kSlideVertMask) {
+ case kSlideDownMask:
+ oldBounds.top = newBounds.bottom = _bounds.top + pegasusRound(getFaderValue() * _boundsHeight, kTransitionRange);
+ oldBounds.bottom = oldBounds.top + _boundsHeight;
+ newBounds.top = newBounds.bottom - _boundsHeight;
+ break;
+ case kSlideUpMask:
+ newBounds.top = oldBounds.bottom = _bounds.bottom - pegasusRound(getFaderValue() * _boundsHeight, kTransitionRange);
+ newBounds.bottom = newBounds.top + _boundsHeight;
+ oldBounds.top = oldBounds.bottom - _boundsHeight;
+ break;
+ default:
+ newBounds.top = oldBounds.top = _bounds.top;
+ newBounds.bottom = oldBounds.bottom = _bounds.bottom;
+ break;
+ }
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/transition.h b/engines/pegasus/transition.h
new file mode 100644
index 0000000000..84241a2bd2
--- /dev/null
+++ b/engines/pegasus/transition.h
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_TRANSITION_H
+#define PEGASUS_TRANSITION_H
+
+#include "pegasus/fader.h"
+
+namespace Graphics {
+struct Surface;
+}
+
+namespace Pegasus {
+
+class ScreenFader : public Fader {
+public:
+ ScreenFader();
+ virtual ~ScreenFader();
+
+ void doFadeOutSync(const TimeValue = kOneSecondPerThirtyTicks, const TimeScale = kThirtyTicksPerSecond, bool isBlack = true);
+ void doFadeInSync(const TimeValue = kHalfSecondPerThirtyTicks, const TimeScale = kThirtyTicksPerSecond, bool isBlack = true);
+
+ void setFaderValue(const int32);
+
+private:
+ bool _isBlack;
+ uint32 fadePixel(uint32 color, int32 percent) const;
+ Graphics::Surface *_screen;
+};
+
+// Transitions are faders that range over [0,1000], which makes their
+// "resolution" one tenth of a percent
+
+static const int kTransitionBottom = 0;
+static const int kTransitionTop = 1000;
+
+static const int kTransitionRange = kTransitionTop - kTransitionBottom;
+
+class Transition : public FaderAnimation {
+public:
+ Transition(const DisplayElementID id);
+ virtual ~Transition() {}
+
+ virtual void setBounds(const Common::Rect &);
+
+ virtual void setInAndOutElements(DisplayElement *, DisplayElement *);
+ DisplayElement *getInElement() { return _inPicture; }
+ DisplayElement *getOutElement() { return _outPicture; }
+
+protected:
+ DisplayElement *_outPicture;
+ DisplayElement *_inPicture;
+
+ CoordType _boundsWidth, _boundsHeight;
+};
+
+class Slide : public Transition {
+public:
+ Slide(const DisplayElementID id) : Transition(id) {}
+ virtual ~Slide() {}
+
+ virtual void setSlideDirection(SlideDirection dir) { _direction = dir; }
+ virtual void draw(const Common::Rect &);
+
+ virtual void setDirection(const SlideDirection dir) { _direction = dir; }
+
+protected:
+ virtual void adjustSlideRects(Common::Rect &, Common::Rect &);
+ virtual void drawElements(const Common::Rect &, const Common::Rect &, const Common::Rect &);
+ virtual void drawSlideElement(const Common::Rect &, const Common::Rect &, DisplayElement *);
+
+ SlideDirection _direction;
+};
+
+class Push : public Slide {
+public:
+ Push(const DisplayElementID id) : Slide(id) {}
+ virtual ~Push() {}
+
+protected:
+ virtual void adjustSlideRects(Common::Rect &, Common::Rect &);
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/types.h b/engines/pegasus/types.h
new file mode 100644
index 0000000000..64ab4e5bb2
--- /dev/null
+++ b/engines/pegasus/types.h
@@ -0,0 +1,161 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_TYPES_H
+#define PEGASUS_TYPES_H
+
+#include "common/scummsys.h"
+
+namespace Pegasus {
+
+// TODO: Probably all of these don't really need to be typedef'd...
+
+typedef int32 DisplayElementID;
+typedef int32 DisplayOrder;
+
+typedef int16 HotSpotID;
+typedef uint32 HotSpotFlags;
+
+typedef byte ButtonState;
+typedef uint32 InputBits;
+
+typedef int32 NotificationID;
+typedef uint32 NotificationFlags;
+
+// Mac types.
+typedef int16 ResIDType;
+typedef int16 CoordType;
+
+enum SlideDirection {
+ kSlideLeftMask = 1,
+ kSlideRightMask = kSlideLeftMask << 1,
+ kSlideUpMask = kSlideRightMask << 1 << 1,
+ kSlideDownMask = kSlideUpMask << 1,
+
+ kSlideHorizMask = kSlideLeftMask | kSlideRightMask,
+ kSlideVertMask = kSlideUpMask | kSlideDownMask,
+
+ kSlideUpLeftMask = kSlideLeftMask | kSlideUpMask,
+ kSlideUpRightMask = kSlideRightMask | kSlideUpMask,
+ kSlideDownLeftMask = kSlideLeftMask | kSlideDownMask,
+ kSlideDownRightMask = kSlideRightMask | kSlideDownMask
+};
+
+// ScummVM QuickTime/QuickDraw replacement types
+typedef uint TimeValue;
+typedef uint TimeScale;
+
+typedef int16 GameID;
+
+typedef GameID ItemID;
+typedef GameID ActorID;
+typedef GameID RoomID;
+typedef GameID NeighborhoodID;
+typedef byte AlternateID;
+typedef int8 HotSpotActivationID;
+
+typedef int16 WeightType;
+
+typedef byte DirectionConstant;
+typedef byte TurnDirection;
+
+// Meant to be room in low 16 bits and direction in high 16 bits.
+typedef uint32 RoomViewID;
+
+#define MakeRoomView(room, direction) (((RoomViewID) (room)) | (((RoomViewID) (direction)) << 16))
+
+typedef uint32 ExtraID;
+
+typedef int16 GameMode;
+
+typedef int16 WeightType;
+
+typedef int16 ItemState;
+
+typedef int8 DeathReason;
+
+typedef int32 GameMenuCommand;
+
+typedef int32 GameScoreType;
+
+typedef long CanMoveForwardReason;
+
+typedef long CanTurnReason;
+
+typedef long CanOpenDoorReason;
+
+enum InventoryResult {
+ kInventoryOK,
+ kTooMuchWeight,
+ kItemNotInInventory
+};
+
+typedef int32 InteractionID;
+
+typedef int32 AIConditionID;
+
+enum EnergyStage {
+ kStageNoStage,
+ kStageCasual, // more than 50% energy
+ kStageWorried, // more than 25% energy
+ kStageNervous, // more than 5% energy
+ kStagePanicStricken // less than 5% energy
+};
+
+enum NoradSubPrepState {
+ kSubNotPrepped,
+ kSubPrepped,
+ kSubDamaged
+};
+
+enum LowerClientSignature {
+ kNoClientSignature,
+ kInventorySignature,
+ kBiochipSignature,
+ kAISignature
+};
+
+enum LowerAreaSignature {
+ kLeftAreaSignature,
+ kMiddleAreaSignature,
+ kRightAreaSignature
+};
+
+enum AirQuality {
+ kAirQualityGood,
+ kAirQualityDirty,
+ kAirQualityVacuum
+};
+
+enum DragType {
+ kDragNoDrag,
+ kDragInventoryPickup,
+ kDragBiochipPickup,
+ kDragInventoryUse
+};
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/pegasus/util.cpp b/engines/pegasus/util.cpp
new file mode 100644
index 0000000000..59df610c33
--- /dev/null
+++ b/engines/pegasus/util.cpp
@@ -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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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/random.h"
+#include "common/system.h"
+#include "common/util.h"
+
+#include "pegasus/util.h"
+
+namespace Pegasus {
+
+IDObject::IDObject(const int32 id) {
+ _objectID = id;
+}
+
+IDObject::~IDObject() {
+}
+
+int32 IDObject::getObjectID() const {
+ return _objectID;
+}
+
+int operator==(const IDObject &arg1, const IDObject &arg2) {
+ return arg1.getObjectID() == arg2.getObjectID();
+}
+
+int operator!=(const IDObject &arg1, const IDObject &arg2) {
+ return arg1.getObjectID() != arg2.getObjectID();
+}
+
+int32 pegasusRound(const int32 a, const int32 b) {
+ if (b < 0)
+ if (a < 0)
+ return -((a - (-b >> 1)) / -b);
+ else
+ return -((a + (-b >> 1)) / -b);
+ else
+ if (a < 0)
+ return (a - (b >> 1)) / b;
+ else
+ return (a + (b >> 1)) / b;
+}
+
+int32 linearInterp(const int32 start1, const int32 stop1, const int32 current1, const int32 start2, const int32 stop2) {
+ if (start2 == stop2)
+ return start2;
+ else
+ return start2 + pegasusRound((current1 - start1) * (stop2 - start2), (stop1 - start1));
+}
+
+uint32 tickCount() {
+ return g_system->getMillis() * 60 / 1000;
+}
+
+} // End of namespace Pegasus
diff --git a/engines/pegasus/util.h b/engines/pegasus/util.h
new file mode 100644
index 0000000000..97ba1c20c3
--- /dev/null
+++ b/engines/pegasus/util.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.
+ *
+ * Additional copyright for this file:
+ * Copyright (C) 1995-1997 Presto Studios, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public 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 PEGASUS_UTIL_H
+#define PEGASUS_UTIL_H
+
+#include "common/stream.h"
+
+#include "pegasus/types.h"
+
+namespace Common {
+ class RandomSource;
+}
+
+namespace Pegasus {
+
+class IDObject {
+public:
+ IDObject(const int32 id);
+ ~IDObject();
+
+ int32 getObjectID() const;
+
+private:
+ int32 _objectID;
+};
+
+#define NUM_FLAGS (sizeof(Unit) * 8)
+#define BIT_INDEX_SHIFT (sizeof(Unit) + 2 - (sizeof(Unit)) / 3)
+#define BIT_INDEX_MASK (NUM_FLAGS - 1)
+
+template <typename Unit, uint32 kNumFlags>
+class FlagsArray {
+public:
+ FlagsArray() { clearAllFlags(); }
+ void clearAllFlags() { memset(_flags, 0, sizeof(_flags)); }
+ void setAllFlags() { memset(_flags, ~((Unit)0), sizeof(_flags)); }
+ void setFlag(uint32 flag) { _flags[flag >> BIT_INDEX_SHIFT] |= 1 << (flag & BIT_INDEX_MASK); }
+ void clearFlag(uint32 flag) { _flags[flag >> BIT_INDEX_SHIFT] &= ~(1 << (flag & BIT_INDEX_MASK)); }
+ void setFlag(uint32 flag, bool val) { if (val) setFlag(flag); else clearFlag(flag); }
+ bool getFlag(uint32 flag) { return (_flags[flag >> BIT_INDEX_SHIFT] & (1 << (flag & BIT_INDEX_MASK))) != 0; }
+ bool anyFlagSet() {
+ for (uint32 i = 0; i < sizeof(_flags); i++)
+ if (_flags[i] != 0)
+ return true;
+ return false;
+ }
+
+ void readFromStream(Common::ReadStream *stream) {
+ // Shortcut
+ if (sizeof(Unit) == 1) {
+ stream->read(_flags, sizeof(_flags));
+ return;
+ }
+
+ for (uint32 i = 0; i < ARRAYSIZE(_flags); i++) {
+ if (sizeof(Unit) == 2)
+ _flags[i] = stream->readUint16BE();
+ else /* if (sizeof(Unit) == 4) */
+ _flags[i] = stream->readUint32BE();
+ }
+ }
+
+ void writeToStream(Common::WriteStream *stream) {
+ // Shortcut
+ if (sizeof(Unit) == 1) {
+ stream->write(_flags, sizeof(_flags));
+ return;
+ }
+
+ for (uint32 i = 0; i < ARRAYSIZE(_flags); i++) {
+ if (sizeof(Unit) == 2)
+ stream->writeUint16BE(_flags[i]);
+ else /* if (sizeof(Unit) == 4) */
+ stream->writeUint32BE(_flags[i]);
+ }
+ }
+
+private:
+ Unit _flags[(kNumFlags - 1) / NUM_FLAGS + 1];
+};
+
+#undef NUM_FLAGS
+#undef BIT_INDEX_SHIFT
+#undef BIT_INDEX_MASK
+
+int32 linearInterp(const int32 start1, const int32 stop1, const int32 current1, const int32 start2, const int32 stop2);
+
+int32 pegasusRound(const int32 a, const int32 b);
+
+uint32 tickCount();
+
+} // End of namespace Pegasus
+
+#endif
diff --git a/engines/plugins_table.h b/engines/plugins_table.h
index c07dbc66a4..e5ac5efeb4 100644
--- a/engines/plugins_table.h
+++ b/engines/plugins_table.h
@@ -59,6 +59,9 @@ LINK_PLUGIN(MOHAWK)
#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
diff --git a/engines/queen/display.cpp b/engines/queen/display.cpp
index 83dc1a9f60..cd9a1075fa 100644
--- a/engines/queen/display.cpp
+++ b/engines/queen/display.cpp
@@ -23,9 +23,13 @@
#include "common/system.h"
#include "common/events.h"
+#include "common/stream.h"
+#include "common/memstream.h"
#include "graphics/cursorman.h"
#include "graphics/palette.h"
+#include "graphics/surface.h"
+#include "graphics/decoders/pcx.h"
#include "queen/display.h"
#include "queen/input.h"
@@ -806,28 +810,22 @@ void Display::fill(uint8 *dstBuf, uint16 dstPitch, uint16 x, uint16 y, uint16 w,
}
void Display::decodePCX(const uint8 *src, uint32 srcSize, uint8 *dst, uint16 dstPitch, uint16 *w, uint16 *h, uint8 *pal, uint16 palStart, uint16 palEnd) {
- *w = READ_LE_UINT16(src + 12);
- *h = READ_LE_UINT16(src + 14);
+ Common::MemoryReadStream str(src, srcSize);
+
+ ::Graphics::PCXDecoder pcx;
+ if (!pcx.loadStream(str))
+ error("Error while reading PCX image");
+
+ const ::Graphics::Surface *pcxSurface = pcx.getSurface();
+ if (pcxSurface->format.bytesPerPixel != 1)
+ error("Invalid bytes per pixel in PCX surface (%d)", pcxSurface->format.bytesPerPixel);
+ *w = pcxSurface->w;
+ *h = pcxSurface->h;
assert(palStart <= palEnd && palEnd <= 256);
- const uint8 *palData = src + srcSize - 768;
- memcpy(pal, palData + palStart * 3, (palEnd - palStart) * 3);
-
- src += 128;
- for (int y = 0; y < *h; ++y) {
- uint8 *p = dst;
- while (p < dst + *w) {
- uint8 col = *src++;
- if ((col & 0xC0) == 0xC0) {
- uint8 len = col & 0x3F;
- memset(p, *src++, len);
- p += len;
- } else {
- *p++ = col;
- }
- }
- dst += dstPitch;
- }
+ memcpy(pal, pcx.getPalette() + palStart * 3, (palEnd - palStart) * 3);
+ for (uint16 y = 0; y < pcxSurface->h; y++)
+ memcpy(dst + y * dstPitch, pcxSurface->getBasePtr(0, y), pcxSurface->w);
}
void Display::decodeLBM(const uint8 *src, uint32 srcSize, uint8 *dst, uint16 dstPitch, uint16 *w, uint16 *h, uint8 *pal, uint16 palStart, uint16 palEnd, uint8 colorBase) {
diff --git a/engines/queen/queen.cpp b/engines/queen/queen.cpp
index f3b183c84f..c403536e22 100644
--- a/engines/queen/queen.cpp
+++ b/engines/queen/queen.cpp
@@ -113,12 +113,12 @@ int QueenMetaEngine::getMaximumSaveSlot() const { return 99; }
const ExtraGuiOptions QueenMetaEngine::getExtraGuiOptions(const Common::String &target) const {
Common::String guiOptions;
ExtraGuiOptions options;
-
+
if (target.empty()) {
options.push_back(queenExtraGuiOption);
return options;
}
-
+
if (ConfMan.hasKey("guioptions", target)) {
guiOptions = ConfMan.get("guioptions", target);
guiOptions = parseGameGUIOptions(guiOptions);
diff --git a/engines/saga/script.cpp b/engines/saga/script.cpp
index 96746b538c..3efc554cb3 100644
--- a/engines/saga/script.cpp
+++ b/engines/saga/script.cpp
@@ -948,7 +948,7 @@ void Script::opSpeak(SCRIPTOP_PARAMS) {
// scripts change to scene 5, but do not clear the cutaway that appears
// before Gorrister's speech starts, resulting in a deadlock. We do this
// manually here.
- if (_vm->getGameId() == GID_IHNM && _vm->_scene->currentChapterNumber() == 1 &&
+ if (_vm->getGameId() == GID_IHNM && _vm->_scene->currentChapterNumber() == 1 &&
_vm->_scene->currentSceneNumber() == 5 && _vm->_anim->hasCutaway()) {
_vm->_anim->returnFromCutaway();
}
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index 1889d53480..5ae8245e5a 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -2882,17 +2882,17 @@ bool Console::cmdDisassemble(int argc, const char **argv) {
reg_t addr = NULL_REG;
if (!obj) {
- DebugPrintf("Not an object.");
+ DebugPrintf("Not an object.\n");
return true;
}
if (selectorId < 0) {
- DebugPrintf("Not a valid selector name.");
+ DebugPrintf("Not a valid selector name.\n");
return true;
}
if (lookupSelector(_engine->_gamestate->_segMan, objAddr, selectorId, NULL, &addr) != kSelectorMethod) {
- DebugPrintf("Not a method.");
+ DebugPrintf("Not a method.\n");
return true;
}
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp
index 58ac5f1fa6..ebad3d039a 100644
--- a/engines/sci/detection.cpp
+++ b/engines/sci/detection.cpp
@@ -103,6 +103,7 @@ static const PlainGameDescriptor s_sciGameTitles[] = {
{"pq4", "Police Quest IV: Open Season"}, // floppy is SCI2, CD SCI2.1
{"qfg4", "Quest for Glory IV: Shadows of Darkness"}, // floppy is SCI2, CD SCI2.1
// === SCI2.1 games ========================================================
+ {"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"},
@@ -132,6 +133,7 @@ static const GameIdStrToEnum s_gameIdStrToEnum[] = {
{ "astrochicken", GID_ASTROCHICKEN },
{ "camelot", GID_CAMELOT },
{ "castlebrain", GID_CASTLEBRAIN },
+ { "chest", GID_CHEST },
{ "christmas1988", GID_CHRISTMAS1988 },
{ "christmas1990", GID_CHRISTMAS1990 },
{ "christmas1992", GID_CHRISTMAS1992 },
@@ -208,6 +210,7 @@ struct OldNewIdTableEntry {
};
static const OldNewIdTableEntry s_oldNewTable[] = {
+ { "archive", "chest", SCI_VERSION_NONE },
{ "arthur", "camelot", SCI_VERSION_NONE },
{ "brain", "castlebrain", SCI_VERSION_1_MIDDLE }, // Amiga
{ "brain", "castlebrain", SCI_VERSION_1_LATE },
@@ -834,12 +837,16 @@ Common::Error SciEngine::saveGameState(int slot, const Common::String &desc) {
return Common::kNoError;
}
+// Before enabling the load option in the ScummVM menu, the main game loop must
+// have run at least once. When the game loop runs, kGameIsRestarting is invoked,
+// thus the speed throttler is initialized. Hopefully fixes bug #3565505.
+
bool SciEngine::canLoadGameStateCurrently() {
- return !_gamestate->executionStackBase;
+ return !_gamestate->executionStackBase && (_gamestate->_throttleLastTime > 0 || _gamestate->_throttleTrigger);
}
bool SciEngine::canSaveGameStateCurrently() {
- return !_gamestate->executionStackBase;
+ return !_gamestate->executionStackBase && (_gamestate->_throttleLastTime > 0 || _gamestate->_throttleTrigger);
}
} // End of namespace Sci
diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h
index b978f40aba..8e8b818854 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -129,6 +129,16 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 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", "", {
+ {"resource.map", 0, "a1deac2647ad09472c63656bfb950a4d", 2739},
+ {"resource.000", 0, "27ec5fa09cd12a7fd16e86d96a2ed245", 347071},
+ {"resource.001", 0, "13e81e1839cd7b216d2bb5615c1ca160", 356812},
+ {"resource.002", 0, "583d348c908f89f94f8551d7fe0a2eca", 991752},
+ {"resource.003", 0, "6c3d1bb26ad532c94046bc9ac49b5ff4", 728315},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+
// Castle of Dr. Brain - English DOS Floppy 1.1
{"castlebrain", "", {
{"resource.map", 0, "f77728304c70017c54793eb6ca648174", 2745},
@@ -162,6 +172,16 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::ES_ESP, Common::kPlatformPC, 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
+ // SCI interpreter version 2.000.000
+ {"chest", "", {
+ {"resource.map", 0, "9dd015e79cac4f91e7de805448f39775", 1912},
+ {"resource.000", 0, "e4efcd042f86679dd4e1834bb3a38edb", 3770943},
+ AD_LISTEND},
+ Common::EN_ANY, Common::kPlatformPC, ADGF_UNSTABLE, GUIO3(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_FB01_MIDI) },
+#endif
+
// Christmas Card 1988 - English DOS
// SCI interpreter version 0.000.294
{"christmas1988", "", {
@@ -268,7 +288,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "08050329aa113a9f14ed99cbfe3536ec", 232942},
{"resource.007", 0, "64f342463f6f35ba71b3509ef696ae3f", 267702},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformPC, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ Common::EN_ANY, Common::kPlatformPC, 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"
diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp
index 22c0a1479d..49e2bfc79f 100644
--- a/engines/sci/engine/features.cpp
+++ b/engines/sci/engine/features.cpp
@@ -466,6 +466,14 @@ bool GameFeatures::autoDetectSci21KernelType() {
// This case doesn't occur in early SCI2.1 games, and we've only
// 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) {
+ _sci21KernelType = SCI_VERSION_2;
+ return true;
+ }
+
warning("autoDetectSci21KernelType(): Sound object not loaded, assuming a SCI2.1 table");
_sci21KernelType = SCI_VERSION_2_1;
return true;
diff --git a/engines/sci/engine/file.cpp b/engines/sci/engine/file.cpp
index a0f7ebf4a2..3dc042389e 100644
--- a/engines/sci/engine/file.cpp
+++ b/engines/sci/engine/file.cpp
@@ -95,7 +95,7 @@ reg_t file_open(EngineState *s, const Common::String &filename, int mode, bool u
outFile = saveFileMan->openForSaving(wrappedName, isCompressed);
if (!outFile)
debugC(kDebugLevelFile, " -> file_open(_K_FILE_MODE_CREATE): failed to create file '%s'", englishName.c_str());
-
+
// QfG1 opens the character export file with _K_FILE_MODE_CREATE first,
// closes it immediately and opens it again with this here. Perhaps
// other games use this for read access as well. I guess changing this
@@ -387,7 +387,7 @@ uint32 VirtualIndexFile::read(char *buffer, uint32 size) {
uint32 VirtualIndexFile::write(const char *buffer, uint32 size) {
_changed = true;
uint32 curPos = _ptr - _buffer;
-
+
// Check if the buffer needs to be resized
if (curPos + size >= _bufferSize) {
_bufferSize = curPos + size + 1;
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index f5f46285be..d0c9b9b1cf 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -94,7 +94,7 @@ static const SciKernelMapSubEntry kDoSound_subops[] = {
{ SIG_SOUNDSCI0, 7, MAP_CALL(DoSoundResumeAfterRestore), "", NULL },
{ SIG_SOUNDSCI0, 8, MAP_CALL(DoSoundMasterVolume), "(i)", NULL },
{ SIG_SOUNDSCI0, 9, MAP_CALL(DoSoundUpdate), "o", NULL },
- { SIG_SOUNDSCI0, 10, MAP_CALL(DoSoundFade), "o", kDoSoundFade_workarounds },
+ { SIG_SOUNDSCI0, 10, MAP_CALL(DoSoundFade), "[o0]", kDoSoundFade_workarounds },
{ SIG_SOUNDSCI0, 11, MAP_CALL(DoSoundGetPolyphony), "", NULL },
{ SIG_SOUNDSCI0, 12, MAP_CALL(DoSoundStopAll), "", NULL },
{ SIG_SOUNDSCI1EARLY, 0, MAP_CALL(DoSoundMasterVolume), NULL, NULL },
@@ -524,7 +524,7 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(PalCycle), SIG_EVERYWHERE, "i(.*)", NULL, NULL },
// SCI2 Empty functions
-
+
// Debug function used to track resources
{ MAP_EMPTY(ResourceTrack), SIG_EVERYWHERE, "(.*)", NULL, NULL },
// Future TODO: This call is used in the floppy version of QFG4 to add
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index f7cc4f44b5..e977f15c0c 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -340,7 +340,7 @@ reg_t kFileIOClose(EngineState *s, int argc, reg_t *argv) {
if (argv[0] == SIGNAL_REG)
return s->r_acc;
-
+
uint16 handle = argv[0].toUint16();
#ifdef ENABLE_SCI32
@@ -624,7 +624,7 @@ reg_t kFileIOExists(EngineState *s, int argc, reg_t *argv) {
// Special case for KQ6 Mac: The game checks for two video files to see
// if they exist before it plays them. Since we support multiple naming
// schemes for resource fork files, we also need to support that here in
- // case someone has a "HalfDome.bin" file, etc.
+ // case someone has a "HalfDome.bin" file, etc.
if (!exists && g_sci->getGameId() == GID_KQ6 && g_sci->getPlatform() == Common::kPlatformMacintosh &&
(name == "HalfDome" || name == "Kq6Movie"))
exists = Common::MacResManager::exists(name);
@@ -998,7 +998,7 @@ reg_t kMakeSaveFileName(EngineState *s, int argc, reg_t *argv) {
if ((virtualId < SAVEGAMEID_OFFICIALRANGE_START) || (virtualId > SAVEGAMEID_OFFICIALRANGE_END))
error("kMakeSaveFileName: invalid savegame ID specified");
uint saveSlot = virtualId - SAVEGAMEID_OFFICIALRANGE_START;
-
+
Common::Array<SavegameDesc> saves;
listSavegames(saves);
diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp
index 002ef1ff07..b839ac51c3 100644
--- a/engines/sci/engine/kpathing.cpp
+++ b/engines/sci/engine/kpathing.cpp
@@ -31,6 +31,9 @@
#include "common/debug-channels.h"
#include "common/list.h"
#include "common/system.h"
+#include "common/math.h"
+
+//#define DEBUG_MERGEPOLY
namespace Sci {
@@ -71,11 +74,25 @@ enum {
struct FloatPoint {
FloatPoint() : x(0), y(0) {}
FloatPoint(float x_, float y_) : x(x_), y(y_) {}
+ FloatPoint(Common::Point p) : x(p.x), y(p.y) {}
Common::Point toPoint() {
return Common::Point((int16)(x + 0.5), (int16)(y + 0.5));
}
+ float operator*(const FloatPoint &p) const {
+ return x*p.x + y*p.y;
+ }
+ FloatPoint operator*(float l) const {
+ return FloatPoint(l*x, l*y);
+ }
+ FloatPoint operator-(const FloatPoint &p) const {
+ return FloatPoint(x-p.x, y-p.y);
+ }
+ float norm() const {
+ return x*x+y*y;
+ }
+
float x, y;
};
@@ -135,15 +152,20 @@ public:
return _head;
}
- void insertHead(Vertex *elm) {
+ void insertAtEnd(Vertex *elm) {
if (_head == NULL) {
elm->_next = elm->_prev = elm;
+ _head = elm;
} else {
elm->_next = _head;
elm->_prev = _head->_prev;
_head->_prev = elm;
elm->_prev->_next = elm;
}
+ }
+
+ void insertHead(Vertex *elm) {
+ insertAtEnd(elm);
_head = elm;
}
@@ -788,10 +810,10 @@ int PathfindingState::findNearPoint(const Common::Point &p, Polygon *polygon, Co
* including the vertices themselves)
* Parameters: (const Common::Point &) a, b: The line segment (a, b)
* (Vertex *) vertex: The first vertex of the edge
- * Returns : (int) FP_OK on success, PF_ERROR otherwise
+ * Returns : (int) PF_OK on success, PF_ERROR otherwise
* (FloatPoint) *ret: The intersection point
*/
-static int intersection(const Common::Point &a, const Common::Point &b, Vertex *vertex, FloatPoint *ret) {
+static int intersection(const Common::Point &a, const Common::Point &b, const Vertex *vertex, FloatPoint *ret) {
// Parameters of parametric equations
float s, t;
// Numerator and denominator of equations
@@ -1344,7 +1366,16 @@ static void AStar(PathfindingState *s) {
// other, while we apply a penalty to paths traversing it.
// This difference might lead to problems, but none are
// known at the time of writing.
- if (s->pointOnScreenBorder(vertex->v))
+
+ // WORKAROUND: This check fails in QFG1VGA, room 81 (bug report #3568452).
+ // However, it is needed in other SCI1.1 games, such as LB2. Therefore, we
+ // add this workaround for that scene in QFG1VGA, until our algorithm matches
+ // better what SSCI is doing. With this workaround, QFG1VGA no longer freezes
+ // in that scene.
+ bool qfg1VgaWorkaround = (g_sci->getGameId() == GID_QFG1VGA &&
+ g_sci->getEngineState()->currentRoomNumber() == 81);
+
+ if (s->pointOnScreenBorder(vertex->v) && !qfg1VgaWorkaround)
new_dist += 10000;
if (new_dist < vertex->costG) {
@@ -1783,39 +1814,619 @@ reg_t kIntersections(EngineState *s, int argc, reg_t *argv) {
}
}
+// ==========================================================================
+// kMergePoly utility functions
+
+// Compute square of the distance of p to the segment a-b.
+static float pointSegDistance(const Common::Point &a, const Common::Point &b,
+ const Common::Point &p) {
+ FloatPoint ba(b-a);
+ FloatPoint pa(p-a);
+ FloatPoint bp(b-p);
+
+ // Check if the projection of p on the line a-b lies between a and b
+ if (ba*pa >= 0.0f && ba*bp >= 0.0f) {
+ // If yes, return the (squared) distance of p to the line a-b:
+ // translate a to origin, project p and subtract
+ float linedist = (ba*((ba*pa)/(ba*ba)) - pa).norm();
+
+ return linedist;
+ } else {
+ // If no, return the (squared) distance to either a or b, whichever
+ // is closest.
+
+ // distance to a:
+ float adist = pa.norm();
+ // distance to b:
+ float bdist = FloatPoint(p-b).norm();
+
+ return MIN(adist, bdist);
+ }
+}
+
+// find intersection between edges of two polygons.
+// endpoints count, except v2->_next
+static bool segSegIntersect(const Vertex *v1, const Vertex *v2, Common::Point &intp) {
+ const Common::Point &a = v1->v;
+ const Common::Point &b = v1->_next->v;
+ const Common::Point &c = v2->v;
+ const Common::Point &d = v2->_next->v;
+
+ // First handle the endpoint cases manually
+
+ if (collinear(a, b, c) && collinear(a, b, d))
+ return false;
+
+ if (collinear(a, b, c)) {
+ // a, b, c collinear
+ // return true/c if c is between a and b
+ intp = c;
+ if (a.x != b.x) {
+ if ((a.x <= c.x && c.x <= b.x) || (b.x <= c.x && c.x <= a.x))
+ return true;
+ } else {
+ if ((a.y <= c.y && c.y <= b.y) || (b.y <= c.y && c.y <= a.y))
+ return true;
+ }
+ }
+
+ if (collinear(a, b, d)) {
+ intp = d;
+ // a, b, d collinear
+ // return false/d if d is between a and b
+ if (a.x != b.x) {
+ if ((a.x <= d.x && d.x <= b.x) || (b.x <= d.x && d.x <= a.x))
+ return false;
+ } else {
+ if ((a.y <= d.y && d.y <= b.y) || (b.y <= d.y && d.y <= a.y))
+ return false;
+ }
+ }
+
+ int len_dc = c.sqrDist(d);
+
+ if (!len_dc) error("zero length edge in polygon");
+
+ if (pointSegDistance(c, d, a) <= 2.0f) {
+ intp = a;
+ return true;
+ }
+
+ if (pointSegDistance(c, d, b) <= 2.0f) {
+ intp = b;
+ return true;
+ }
+
+ // If not an endpoint, call the generic intersection function
+
+ FloatPoint p;
+ if (intersection(a, b, v2, &p) == PF_OK) {
+ intp = p.toPoint();
+ return true;
+ } else {
+ return false;
+ }
+}
+
+// For intersecting polygon segments, determine if
+// * the v2 edge enters polygon 1 at this intersection: positive return value
+// * the v2 edge and the v1 edges are parallel: zero return value
+// * the v2 edge exits polygon 1 at this intersection: negative return value
+static int intersectDir(const Vertex *v1, const Vertex *v2) {
+ Common::Point p1 = v1->_next->v - v1->v;
+ Common::Point p2 = v2->_next->v - v2->v;
+ return (p1.x*p2.y - p2.x*p1.y);
+}
+
+// Direction of edge in degrees from pos. x-axis, between -180 and 180
+static int edgeDir(const Vertex *v) {
+ Common::Point p = v->_next->v - v->v;
+ int deg = (int)Common::rad2deg(atan2((double)p.y, (double)p.x));
+ if (deg < -180) deg += 360;
+ if (deg > 180) deg -= 360;
+ return deg;
+}
+
+// For points p1, p2 on the polygon segment v, determine if
+// * p1 lies before p2: negative return value
+// * p1 and p2 are the same: zero return value
+// * p1 lies after p2: positive return value
+static int liesBefore(const Vertex *v, const Common::Point &p1, const Common::Point &p2) {
+ return v->v.sqrDist(p1) - v->v.sqrDist(p2);
+}
+
+// Structure describing an "extension" to the work polygon following edges
+// of the polygon being merged.
+
+// The patch begins on the point intersection1, being the intersection
+// of the edges starting at indexw1/vertexw1 on the work polygon, and at
+// indexp1/vertexp1 on the polygon being merged.
+// It ends with the point intersection2, being the analogous intersection.
+struct Patch {
+ unsigned int indexw1;
+ unsigned int indexp1;
+ const Vertex *vertexw1;
+ const Vertex *vertexp1;
+ Common::Point intersection1;
+
+ unsigned int indexw2;
+ unsigned int indexp2;
+ const Vertex *vertexw2;
+ const Vertex *vertexp2;
+ Common::Point intersection2;
+
+ bool disabled; // If true, this Patch was made superfluous by another Patch
+};
+
+
+// Check if the given vertex on the work polygon is bypassed by this patch.
+static bool isVertexCovered(const Patch &p, unsigned int wi) {
+
+ // / v (outside)
+ // ---w1--1----p----w2--2----
+ // ^ \ (inside)
+ if (wi > p.indexw1 && wi <= p.indexw2)
+ return true;
+
+ // v / (outside)
+ // ---w2--2----p----w1--1----
+ // \ ^ (inside)
+ if (p.indexw1 > p.indexw2 && (wi <= p.indexw2 || wi > p.indexw1))
+ return true;
+
+ // v / (outside)
+ // ---w1--2--1-------p-----
+ // w2 \ ^ (inside)
+ if (p.indexw1 == p.indexw2 && liesBefore(p.vertexw1, p.intersection1, p.intersection2) > 0)
+ return true; // This patch actually covers _all_ vertices on work
+
+ return false;
+}
+
+// Check if patch p1 makes patch p2 superfluous.
+static bool isPatchCovered(const Patch &p1, const Patch &p2) {
+
+ // Same exit and entry points
+ if (p1.intersection1 == p2.intersection1 && p1.intersection2 == p2.intersection2)
+ return true;
+
+ // / * v (outside)
+ // ---p1w1--1----p2w1-1---p1w2--2----
+ // ^ * \ (inside)
+ if (p1.indexw1 < p2.indexw1 && p2.indexw1 < p1.indexw2)
+ return true;
+ if (p1.indexw1 > p1.indexw2 && (p2.indexw1 > p1.indexw1 || p2.indexw1 < p1.indexw2))
+ return true;
+
+
+ // / * v (outside)
+ // ---p1w1--11----p2w2-2---p1w2--12----
+ // ^ * \ (inside)
+ if (p1.indexw1 < p2.indexw2 && p2.indexw2 < p1.indexw2)
+ return true;
+ if (p1.indexw1 > p1.indexw2 && (p2.indexw2 > p1.indexw1 || p2.indexw2 < p1.indexw2))
+ return true;
+
+ // Opposite of two above situations
+ if (p2.indexw1 < p1.indexw1 && p1.indexw1 < p2.indexw2)
+ return false;
+ if (p2.indexw1 > p2.indexw2 && (p1.indexw1 > p2.indexw1 || p1.indexw1 < p2.indexw2))
+ return false;
+
+ if (p2.indexw1 < p1.indexw2 && p1.indexw2 < p2.indexw2)
+ return false;
+ if (p2.indexw1 > p2.indexw2 && (p1.indexw2 > p2.indexw1 || p1.indexw2 < p2.indexw2))
+ return false;
+
+
+ // The above checks covered the cases where one patch covers the other and
+ // the intersections of the patches are on different edges.
+
+ // So, if we passed the above checks, we have to check the order of
+ // intersections on edges.
+
+
+ if (p1.indexw1 != p1.indexw2) {
+
+ // / * v (outside)
+ // ---p1w1--11---21--------p1w2--2----
+ // p2w1 ^ * \ (inside)
+ if (p1.indexw1 == p2.indexw1)
+ return (liesBefore(p1.vertexw1, p1.intersection1, p2.intersection1) < 0);
+
+ // / * v (outside)
+ // ---p1w1--11---------p1w2--21---12----
+ // ^ p2w1 * \ (inside)
+ if (p1.indexw2 == p2.indexw1)
+ return (liesBefore(p1.vertexw2, p1.intersection2, p2.intersection1) > 0);
+
+ // If neither of the above, then the intervals of the polygon
+ // covered by patch1 and patch2 are disjoint
+ return false;
+ }
+
+ // p1w1 == p1w2
+ // Also, p1w1/p1w2 isn't strictly between p2
+
+
+ // v / * (outside)
+ // ---p1w1--12--11-------p2w1-21----
+ // p1w2 \ ^ * (inside)
+
+ // v / / (outside)
+ // ---p1w1--12--21--11---------
+ // p1w2 \ ^ ^ (inside)
+ // p2w1
+ if (liesBefore(p1.vertexw1, p1.intersection1, p1.intersection2) > 0)
+ return (p1.indexw1 != p2.indexw1);
+
+ // CHECKME: This is meaningless if p2w1 != p2w2 ??
+ if (liesBefore(p2.vertexw1, p2.intersection1, p2.intersection2) > 0)
+ return false;
+
+ // CHECKME: This is meaningless if p1w1 != p2w1 ??
+ if (liesBefore(p2.vertexw1, p2.intersection1, p1.intersection1) <= 0)
+ return false;
+
+ // CHECKME: This is meaningless if p1w2 != p2w1 ??
+ if (liesBefore(p2.vertexw1, p2.intersection1, p1.intersection2) >= 0)
+ return false;
+
+ return true;
+}
+
+// Merge a single polygon into the work polygon.
+// If there is an intersection between work and polygon, this function
+// returns true, and replaces the vertex list of work by an extended version,
+// that covers polygon.
+//
+// NOTE: The strategy used matches qfg1new closely, and is a bit error-prone.
+// A more robust strategy would be inserting all intersection points directly
+// into both vertex lists as a first pass. This would make finding the merged
+// polygon a much more straightforward edge-walk, and avoid cases where SSCI's
+// algorithm mixes up the order of multiple intersections on a single edge.
+bool mergeSinglePolygon(Polygon &work, const Polygon &polygon) {
+#ifdef DEBUG_MERGEPOLY
+ const Vertex *vertex;
+ debugN("work:");
+ CLIST_FOREACH(vertex, &(work.vertices)) {
+ debugN(" (%d,%d) ", vertex->v.x, vertex->v.y);
+ }
+ debugN("\n");
+ debugN("poly:");
+ CLIST_FOREACH(vertex, &(polygon.vertices)) {
+ debugN(" (%d,%d) ", vertex->v.x, vertex->v.y);
+ }
+ debugN("\n");
+#endif
+ uint workSize = work.vertices.size();
+ uint polygonSize = polygon.vertices.size();
+
+ int patchCount = 0;
+ Patch patchList[8];
+
+ const Vertex *workv = work.vertices._head;
+ const Vertex *polyv = polygon.vertices._head;
+ for (uint wi = 0; wi < workSize; ++wi, workv = workv->_next) {
+ for (uint pi = 0; pi < polygonSize; ++pi, polyv = polyv->_next) {
+ Common::Point intersection1;
+ Common::Point intersection2;
+
+ bool intersects = segSegIntersect(workv, polyv, intersection1);
+ if (!intersects)
+ continue;
+
+#ifdef DEBUG_MERGEPOLY
+ debug("mergePoly: intersection at work %d, poly %d", wi, pi);
+#endif
+
+ if (intersectDir(workv, polyv) >= 0)
+ continue;
+
+#ifdef DEBUG_MERGEPOLY
+ debug("mergePoly: intersection in right direction");
+#endif
+
+ int angle = 0;
+ int baseAngle = edgeDir(workv);
+
+ // We now found the point where an edge of 'polygon' left 'work'.
+ // Now find the re-entry point.
+
+ // NOTE: The order in which this searches does not always work
+ // properly if the correct patch would only use a single partial
+ // edge of poly. Because it starts at polyv->_next, it will skip
+ // the correct re-entry and proceed to the next.
+
+ const Vertex *workv2;
+ const Vertex *polyv2 = polyv->_next;
+
+ intersects = false;
+
+ uint pi2, wi2;
+ for (pi2 = 0; pi2 < polygonSize; ++pi2, polyv2 = polyv2->_next) {
+
+ int newAngle = edgeDir(polyv2);
+
+ int relAngle = newAngle - baseAngle;
+ if (relAngle > 180) relAngle -= 360;
+ if (relAngle < -180) relAngle += 360;
+
+ angle += relAngle;
+ baseAngle = newAngle;
+
+ workv2 = workv;
+ for (wi2 = 0; wi2 < workSize; ++wi2, workv2 = workv2->_next) {
+ intersects = segSegIntersect(workv2, polyv2, intersection2);
+ if (!intersects)
+ continue;
+#ifdef DEBUG_MERGEPOLY
+ debug("mergePoly: re-entry intersection at work %d, poly %d", (wi + wi2) % workSize, (pi + 1 + pi2) % polygonSize);
+#endif
+
+ if (intersectDir(workv2, polyv2) > 0) {
+#ifdef DEBUG_MERGEPOLY
+ debug("mergePoly: re-entry intersection in right direction, angle = %d", angle);
+#endif
+ break; // found re-entry point
+ }
+
+ }
+
+ if (intersects)
+ break;
+
+ }
+
+ if (!intersects || angle < 0)
+ continue;
+
+
+ if (patchCount >= 8)
+ error("kMergePoly: Too many patches");
+
+ // convert relative to absolute vertex indices
+ pi2 = (pi + 1 + pi2) % polygonSize;
+ wi2 = (wi + wi2) % workSize;
+
+ Patch &newPatch = patchList[patchCount];
+ newPatch.indexw1 = wi;
+ newPatch.vertexw1 = workv;
+ newPatch.indexp1 = pi;
+ newPatch.vertexp1 = polyv;
+ newPatch.intersection1 = intersection1;
+
+ newPatch.indexw2 = wi2;
+ newPatch.vertexw2 = workv2;
+ newPatch.indexp2 = pi2;
+ newPatch.vertexp2 = polyv2;
+ newPatch.intersection2 = intersection2;
+ newPatch.disabled = false;
+
+#ifdef DEBUG_MERGEPOLY
+ debug("mergePoly: adding patch at work %d, poly %d", wi, pi);
+#endif
+
+ if (patchCount == 0) {
+ patchCount++;
+ continue;
+ }
+
+ bool necessary = true;
+ for (int i = 0; i < patchCount; ++i) {
+ if (isPatchCovered(patchList[i], newPatch)) {
+ necessary = false;
+ break;
+ }
+ }
+
+ if (!necessary)
+ continue;
+
+ patchCount++;
+
+ if (patchCount > 1) {
+ // check if this patch makes other patches superfluous
+ for (int i = 0; i < patchCount-1; ++i)
+ if (isPatchCovered(newPatch, patchList[i]))
+ patchList[i].disabled = true;
+ }
+ }
+ }
+
+
+ if (patchCount == 0)
+ return false; // nothing changed
+
+
+ // Determine merged work by doing a walk over the edges
+ // of work, crossing over to polygon when encountering a patch.
+
+ Polygon output(0);
+
+ workv = work.vertices._head;
+ for (uint wi = 0; wi < workSize; ++wi, workv = workv->_next) {
+
+ bool covered = false;
+ for (int p = 0; p < patchCount; ++p) {
+ if (patchList[p].disabled) continue;
+ if (isVertexCovered(patchList[p], wi)) {
+ covered = true;
+ break;
+ }
+ }
+
+ if (!covered) {
+ // Add vertex to output
+ output.vertices.insertAtEnd(new Vertex(workv->v));
+ }
+
+
+ // CHECKME: Why is this the correct order in which to process
+ // the patches? (What if two of them start on this line segment
+ // in the opposite order?)
+
+ for (int p = 0; p < patchCount; ++p) {
+
+ const Patch &patch = patchList[p];
+ if (patch.disabled) continue;
+ if (patch.indexw1 != wi) continue;
+ if (patch.intersection1 != workv->v) {
+ // Add intersection point to output
+ output.vertices.insertAtEnd(new Vertex(patch.intersection1));
+ }
+
+ // Add vertices from polygon between vertexp1 (excl) and vertexp2 (incl)
+ for (polyv = patch.vertexp1->_next; polyv != patch.vertexp2; polyv = polyv->_next)
+ output.vertices.insertAtEnd(new Vertex(polyv->v));
+
+ output.vertices.insertAtEnd(new Vertex(patch.vertexp2->v));
+
+ if (patch.intersection2 != patch.vertexp2->v) {
+ // Add intersection point to output
+ output.vertices.insertAtEnd(new Vertex(patch.intersection2));
+ }
+
+ // TODO: We could continue after the re-entry point here?
+ }
+ }
+ // Remove last vertex if it's the same as the first vertex
+ if (output.vertices._head->v == output.vertices._head->_prev->v)
+ output.vertices.remove(output.vertices._head->_prev);
+
+
+ // Slight hack: swap vertex lists of output and work polygons.
+ SWAP(output.vertices._head, work.vertices._head);
+
+ return true;
+}
+
+
/**
* This is a quite rare kernel function. An example of when it's called
* is in QFG1VGA, after killing any monster.
+ *
+ * It takes a polygon, and extends it to also cover any polygons from the
+ * input list with which it intersects. Any of those polygons so covered
+ * from the input list are marked by adding 0x10 to their type field.
*/
reg_t kMergePoly(EngineState *s, int argc, reg_t *argv) {
-#if 0
// 3 parameters: raw polygon data, polygon list, list size
reg_t polygonData = argv[0];
List *list = s->_segMan->lookupList(argv[1]);
- Node *node = s->_segMan->lookupNode(list->first);
- // List size is not needed
- Polygon *polygon;
- int count = 0;
+ // The size of the "work" point list SSCI uses. We use a dynamic one instead
+ //reg_t listSize = argv[2];
+
+ SegmentRef pointList = s->_segMan->dereference(polygonData);
+ if (!pointList.isValid() || pointList.skipByte) {
+ warning("kMergePoly: Polygon data pointer is invalid");
+ return make_reg(0, 0);
+ }
+
+ Node *node;
+
+#ifdef DEBUG_MERGEPOLY
+ node = s->_segMan->lookupNode(list->first);
+ while (node) {
+ draw_polygon(s, node->value, 320, 190);
+ node = s->_segMan->lookupNode(node->succ);
+ }
+ Common::Point prev, first;
+ prev = first = readPoint(pointList, 0);
+ for (int i = 1; readPoint(pointList, i).x != 0x7777; i++) {
+ Common::Point point = readPoint(pointList, i);
+ draw_line(s, prev, point, 1, 320, 190);
+ prev = point;
+ }
+ draw_line(s, prev, first, 1, 320, 190);
+ // Update the whole screen
+ g_sci->_gfxScreen->copyToScreen();
+ g_system->updateScreen();
+ g_system->delayMillis(1000);
+#endif
+
+ // The work polygon which we're going to merge with the polygons in list
+ Polygon work(0);
+
+ for (int i = 0; true; ++i) {
+ Common::Point p = readPoint(pointList, i);
+ if (p.x == POLY_LAST_POINT)
+ break;
+ Vertex *vertex = new Vertex(p);
+ work.vertices.insertAtEnd(vertex);
+ }
+
+ // TODO: Check behaviour for single-vertex polygons
+ node = s->_segMan->lookupNode(list->first);
while (node) {
- polygon = convert_polygon(s, node->value);
+ Polygon *polygon = convert_polygon(s, node->value);
if (polygon) {
- count += readSelectorValue(s->_segMan, node->value, SELECTOR(size));
+ // CHECKME: Confirm vertex order that convert_polygon and
+ // fix_vertex_order output. For now, we re-reverse the order since
+ // convert_polygon reads the vertices reversed, and fix up head.
+ polygon->vertices.reverse();
+ polygon->vertices._head = polygon->vertices._head->_next;
+
+ // Merge this polygon into the work polygon if there is an
+ // intersection.
+ bool intersected = mergeSinglePolygon(work, *polygon);
+
+ // If so, flag it
+ if (intersected) {
+ writeSelectorValue(s->_segMan, node->value,
+ SELECTOR(type), polygon->type + 0x10);
+#ifdef DEBUG_MERGEPOLY
+ debugN("Merged polygon: ");
+ // Iterate over edges
+ Vertex *vertex;
+ CLIST_FOREACH(vertex, &(work.vertices)) {
+ debugN(" (%d,%d) ", vertex->v.x, vertex->v.y);
+ }
+ debugN("\n");
+#endif
+ }
}
node = s->_segMan->lookupNode(node->succ);
}
-#endif
- // TODO: actually merge the polygon. We return an empty polygon for now.
- // In QFG1VGA, you can walk over enemy bodies after killing them, since
- // this is a stub.
- reg_t output = allocateOutputArray(s->_segMan, 1);
+
+ // Allocate output array
+ reg_t output = allocateOutputArray(s->_segMan, work.vertices.size()+1);
SegmentRef arrayRef = s->_segMan->dereference(output);
- writePoint(arrayRef, 0, Common::Point(POLY_LAST_POINT, POLY_LAST_POINT));
- warning("Stub: kMergePoly");
+
+ // Copy work.vertices into arrayRef
+ Vertex *vertex;
+ unsigned int n = 0;
+ CLIST_FOREACH(vertex, &work.vertices) {
+ if (vertex == work.vertices._head || vertex->v != vertex->_prev->v)
+ writePoint(arrayRef, n++, vertex->v);
+ }
+
+ writePoint(arrayRef, n, Common::Point(POLY_LAST_POINT, POLY_LAST_POINT));
+
+#ifdef DEBUG_MERGEPOLY
+ prev = first = readPoint(arrayRef, 0);
+ for (int i = 1; readPoint(arrayRef, i).x != 0x7777; i++) {
+ Common::Point point = readPoint(arrayRef, i);
+ draw_line(s, prev, point, 3, 320, 190);
+ prev = point;
+ }
+
+ draw_line(s, prev, first, 3, 320, 190);
+
+ // Update the whole screen
+ g_sci->_gfxScreen->copyToScreen();
+ g_system->updateScreen();
+ if (!g_sci->_gfxPaint16)
+ g_system->delayMillis(1000);
+
+ debug("kMergePoly done");
+#endif
+
return output;
}
diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp
index c22d7c7b1e..c4db0b891c 100644
--- a/engines/sci/engine/kstring.cpp
+++ b/engines/sci/engine/kstring.cpp
@@ -165,6 +165,7 @@ reg_t kReadNumber(EngineState *s, int argc, reg_t *argv) {
// do clipping. In SQ4 we get the door code in here and that's even
// larger than uint32!
if (*source == '-') {
+ // FIXME: Setting result to -1 does _not_ negate the output.
result = -1;
source++;
}
diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp
index 6bf9aff2fe..9b0cb38f51 100644
--- a/engines/sci/engine/kvideo.cpp
+++ b/engines/sci/engine/kvideo.cpp
@@ -275,7 +275,7 @@ reg_t kRobot(EngineState *s, int argc, reg_t *argv) {
// Signal the engine scripts that the video is done
writeSelector(s->_segMan, argv[1], SELECTOR(signal), SIGNAL_REG);
} else {
- writeSelector(s->_segMan, argv[1], SELECTOR(signal), NULL_REG);
+ writeSelector(s->_segMan, argv[1], SELECTOR(signal), NULL_REG);
}
break;
default:
diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp
index 037f4ab700..36d2841b07 100644
--- a/engines/sci/engine/script.cpp
+++ b/engines/sci/engine/script.cpp
@@ -144,7 +144,7 @@ void Script::load(int script_nr, ResourceManager *resMan) {
_heapStart = _buf + _scriptSize;
- assert(_bufSize - _scriptSize <= heap->size);
+ assert(_bufSize - _scriptSize >= heap->size);
memcpy(_heapStart, heap->data, heap->size);
}
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index 659c13b13e..8639b6ef71 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -848,10 +848,47 @@ const uint16 qfg1vgaPatchFightEvents[] = {
PATCH_END
};
+// Script 814 of QFG1VGA is responsible for showing dialogs. However, the death
+// screen message shown when the hero dies in room 64 (ghost room) is too large
+// (254 chars long). Since the window header and main text are both stored in
+// temp space, this is an issue, as the scripts read the window header, then the
+// 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.
+
+// Patch 1: Increase temp space
+const byte qfg1vgaSignatureTempSpace[] = {
+ 4,
+ 0x3f, 0xba, // link 0xba
+ 0x87, 0x00, // lap 0
+ 0
+};
+
+const uint16 qfg1vgaPatchTempSpace[] = {
+ 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 qfg1vgaPatchDialogHeader[] = {
+ 0x5b, 0x04, 0x90, // lea temp[0x90]
+ 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 },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -915,9 +952,53 @@ const uint16 qfg3PatchImportDialog[] = {
PATCH_END
};
+
+
+// ===========================================================================
+// Patch for the Woo dialog option in Uhura's conversation. Bug #3040722
+// 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
+// Teller::doChild to open the submenu. However, there is no actual submenu
+// defined for option -75 since -75 does not show up in uhuraTell::keys.
+// This will cause Teller::doChild to run out of bounds while scanning through
+// uhuraTell::keys.
+// Strategy: there is another conversation option in uhuraTell::doChild calling
+// 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
+};
+
+const uint16 qfg3PatchWooDialog[] = {
+ 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 },
SCI_SIGNATUREENTRY_TERMINATOR
};
diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp
index d3abb9ff41..b2f22aa985 100644
--- a/engines/sci/engine/scriptdebug.cpp
+++ b/engines/sci/engine/scriptdebug.cpp
@@ -514,7 +514,7 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) {
if (!objType) {
debugN("End of script object (#0) encountered.\n");
- debugN("Classes: %i, Objects: %i, Export: %i,\n Var: %i (all base 10)",
+ debugN("Classes: %i, Objects: %i, Export: %i,\n Var: %i (all base 10)\n",
objectctr[6], objectctr[1], objectctr[7], objectctr[10]);
return;
}
@@ -527,7 +527,8 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) {
_seeker += objsize;
- objectctr[objType]++;
+ if (objType >= 0 && objType < ARRAYSIZE(objectctr))
+ objectctr[objType]++;
switch (objType) {
case SCI_OBJ_OBJECT:
diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp
index 951fc7c363..04c1dab158 100644
--- a/engines/sci/engine/seg_manager.cpp
+++ b/engines/sci/engine/seg_manager.cpp
@@ -825,7 +825,7 @@ byte *SegManager::allocDynmem(int size, const char *descr, reg_t *addr) {
}
bool SegManager::freeDynmem(reg_t addr) {
- if (addr.getSegment() < 1 || addr.getSegment() >= _heap.size() ||
+ if (addr.getSegment() < 1 || addr.getSegment() >= _heap.size() ||
!_heap[addr.getSegment()] || _heap[addr.getSegment()]->getType() != SEG_TYPE_DYNMEM)
return false; // error
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index 3f43966976..ef8f165084 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -228,7 +228,7 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP
uint32 exportAddr = scr->validateExportFunc(pubfunct, false);
if (!exportAddr)
return NULL;
-
+
// Check if a breakpoint is set on this method
g_sci->checkExportBreakpoint(script, pubfunct);
diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp
index 9fa0368784..db510c2545 100644
--- a/engines/sci/engine/workarounds.cpp
+++ b/engines/sci/engine/workarounds.cpp
@@ -243,9 +243,6 @@ const SciWorkaroundEntry kDisposeScript_workarounds[] = {
// gameID, room,script,lvl, object-name, method-name, call,index, workaround
const SciWorkaroundEntry kDoSoundFade_workarounds[] = {
- { GID_CAMELOT, -1, 989, 0, "rmMusic", "fade", -1, 0, { WORKAROUND_IGNORE, 0 } }, // gets called frequently with a NULL reference (i.e. 0:0) - bug #3035149
- { GID_KQ1, -1, 989, 0, "gameSound", "fade", -1, 0, { WORKAROUND_IGNORE, 0 } }, // gets called in several scenes (e.g. graham cracker) with 0:0
- { GID_KQ4, -1, 989, 0, "mySound", "", -1, 0, { WORKAROUND_IGNORE, 0 } }, // gets called in the demo when trying to open the non-existent menu with 0:0 - bug #3036942
{ GID_KQ5, 213, 989, 0, "globalSound3", "fade", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // english floppy: when bandits leave the secret temple, parameter 4 is an object - bug #3037594
{ 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
diff --git a/engines/sci/graphics/controls32.cpp b/engines/sci/graphics/controls32.cpp
index ad1d9e8623..5535a7408a 100644
--- a/engines/sci/graphics/controls32.cpp
+++ b/engines/sci/graphics/controls32.cpp
@@ -68,7 +68,7 @@ void GfxControls32::kernelTexteditChange(reg_t controlObject) {
while (captureEvents) {
curEvent = g_sci->getEventManager()->getSciEvent(SCI_EVENT_KEYBOARD | SCI_EVENT_PEEK);
-
+
if (curEvent.type == SCI_EVENT_NONE) {
eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event
} else {
@@ -170,11 +170,11 @@ void GfxControls32::kernelTexteditChange(reg_t controlObject) {
// Note: the following checkAltInput call might make the text
// too wide to fit, but SSCI fails to check that too.
}
-
+
reg_t hunkId = readSelector(_segMan, controlObject, SELECTOR(bitmap));
Common::Rect nsRect = g_sci->_gfxCompare->getNSRect(controlObject);
//texteditCursorErase(); // TODO: Cursor
-
+
// Write back string
_segMan->strcpy(textReference, text.c_str());
// Modify the buffer and show it
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index 968014c032..8b7fa2c384 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -197,7 +197,7 @@ void GfxFrameout::kernelUpdatePlane(reg_t object) {
} else {
it->planeOffsetX = 0;
}
-
+
if (it->planeRect.top < 0) {
it->planeOffsetY = -it->planeRect.top;
it->planeRect.top = 0;
@@ -420,7 +420,7 @@ void GfxFrameout::deletePlaneItems(reg_t planeObject) {
} else {
objectMatches = true;
}
-
+
if (objectMatches) {
FrameoutEntry *itemEntry = *listIterator;
listIterator = _screenItems.erase(listIterator);
@@ -661,7 +661,7 @@ void GfxFrameout::kernelFrameout() {
if (!itemEntry->visible)
continue;
-
+
if (itemEntry->object.isNull()) {
// Picture cel data
_coordAdjuster->fromScriptToDisplay(itemEntry->y, itemEntry->x);
@@ -703,7 +703,7 @@ void GfxFrameout::kernelFrameout() {
view->getCelRect(itemEntry->loopNo, itemEntry->celNo,
itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->celRect);
else
- view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo,
+ view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo,
itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->scaleX,
itemEntry->scaleY, itemEntry->celRect);
@@ -755,10 +755,10 @@ void GfxFrameout::kernelFrameout() {
if (view) {
if (!clipRect.isEmpty()) {
if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128))
- view->draw(itemEntry->celRect, clipRect, translatedClipRect,
+ view->draw(itemEntry->celRect, clipRect, translatedClipRect,
itemEntry->loopNo, itemEntry->celNo, 255, 0, view->isSci2Hires());
else
- view->drawScaled(itemEntry->celRect, clipRect, translatedClipRect,
+ view->drawScaled(itemEntry->celRect, clipRect, translatedClipRect,
itemEntry->loopNo, itemEntry->celNo, 255, itemEntry->scaleX, itemEntry->scaleY);
}
}
@@ -817,7 +817,7 @@ void GfxFrameout::printPlaneItemList(Console *con, reg_t planeObject) {
for (FrameoutList::iterator listIterator = _screenItems.begin(); listIterator != _screenItems.end(); listIterator++) {
FrameoutEntry *e = *listIterator;
reg_t itemPlane = readSelector(_segMan, e->object, SELECTOR(plane));
-
+
if (planeObject == itemPlane) {
Common::String curItemName = _segMan->getObjectName(e->object);
Common::Rect icr = e->celRect;
diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp
index 89f3625e2c..d20aa80c77 100644
--- a/engines/sci/graphics/paint16.cpp
+++ b/engines/sci/graphics/paint16.cpp
@@ -559,8 +559,8 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) {
SciTrackOriginReply originReply;
SciWorkaroundSolution solution = trackOriginAndFindWorkaround(0, kDisplay_workarounds, &originReply);
if (solution.type == WORKAROUND_NONE)
- error("Unknown kDisplay argument (%04x:%04x) from method %s::%s (script %d, localCall %x)",
- PRINT_REG(displayArg), originReply.objectName.c_str(), originReply.methodName.c_str(),
+ error("Unknown kDisplay argument (%04x:%04x) from method %s::%s (script %d, localCall %x)",
+ PRINT_REG(displayArg), originReply.objectName.c_str(), originReply.methodName.c_str(),
originReply.scriptNr, originReply.localCallOffset);
assert(solution.type == WORKAROUND_IGNORE);
break;
diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp
index 6b4c8180bf..8acdeed763 100644
--- a/engines/sci/graphics/ports.cpp
+++ b/engines/sci/graphics/ports.cpp
@@ -380,17 +380,50 @@ Window *GfxPorts::addWindow(const Common::Rect &dims, const Common::Rect *restor
int16 oldtop = pwnd->dims.top;
int16 oldleft = pwnd->dims.left;
- if (wmprect.top > pwnd->dims.top)
+ // WORKAROUND: We also adjust the restore rect when adjusting the window
+ // rect.
+ // SSCI does not do this. It wasn't necessary in the original interpreter,
+ // but it is needed for Freddy Pharkas CD. This version does not normally
+ // have text, but we allow this by modifying the text/speech setting
+ // according to what is set in the ScummVM GUI (refer to syncIngameAudioOptions()
+ // in sci.cpp). Since the text used in Freddy Pharkas CD is quite large in
+ // some cases, it ends up being offset in order to fit inside the screen,
+ // but the associated restore rect isn't adjusted accordingly, leading to
+ // artifacts being left on screen when some text boxes are removed. The
+ // fact that the restore rect wasn't ever adjusted doesn't make sense, and
+ // adjusting it shouldn't have any negative side-effects (it *should* be
+ // adjusted, normally, but SCI doesn't do it). The big text boxes are still
+ // odd-looking, because the text rect is drawn outside the text window rect,
+ // but at least there aren't any leftover textbox artifacts left when the
+ // boxes are removed. Adjusting the text window rect would require more
+ // invasive changes than this one, thus it's not really worth the effort
+ // for a feature that was not present in the original game, and its
+ // implementation is buggy in the first place.
+ // Adjusting the restore rect properly fixes bug #3575276.
+
+ if (wmprect.top > pwnd->dims.top) {
pwnd->dims.moveTo(pwnd->dims.left, wmprect.top);
+ if (restoreRect)
+ pwnd->restoreRect.moveTo(pwnd->restoreRect.left, wmprect.top);
+ }
- if (wmprect.bottom < pwnd->dims.bottom)
+ if (wmprect.bottom < pwnd->dims.bottom) {
pwnd->dims.moveTo(pwnd->dims.left, wmprect.bottom - pwnd->dims.bottom + pwnd->dims.top);
+ if (restoreRect)
+ pwnd->restoreRect.moveTo(pwnd->restoreRect.left, wmprect.bottom - pwnd->restoreRect.bottom + pwnd->restoreRect.top);
+ }
- if (wmprect.right < pwnd->dims.right)
+ if (wmprect.right < pwnd->dims.right) {
pwnd->dims.moveTo(wmprect.right + pwnd->dims.left - pwnd->dims.right, pwnd->dims.top);
+ if (restoreRect)
+ pwnd->restoreRect.moveTo(wmprect.right + pwnd->restoreRect.left - pwnd->restoreRect.right, pwnd->restoreRect.top);
+ }
- if (wmprect.left > pwnd->dims.left)
+ if (wmprect.left > pwnd->dims.left) {
pwnd->dims.moveTo(wmprect.left, pwnd->dims.top);
+ if (restoreRect)
+ pwnd->restoreRect.moveTo(wmprect.left, pwnd->restoreRect.top);
+ }
pwnd->rect.moveTo(pwnd->rect.left + pwnd->dims.left - oldleft, pwnd->rect.top + pwnd->dims.top - oldtop);
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index 42ae00b525..15b18ce8e6 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -876,6 +876,7 @@ void SciEngine::syncIngameAudioOptions() {
if (getGameId() == GID_SQ4
|| getGameId() == GID_FREDDYPHARKAS
|| getGameId() == GID_ECOQUEST
+ || getGameId() == GID_LSL6
// TODO: The following need script patches for simultaneous speech and subtitles
//|| getGameId() == GID_KQ6
//|| getGameId() == GID_LAURABOW2
diff --git a/engines/sci/sci.h b/engines/sci/sci.h
index 9f18219cb7..3b9844b326 100644
--- a/engines/sci/sci.h
+++ b/engines/sci/sci.h
@@ -110,6 +110,7 @@ enum SciGameId {
GID_ASTROCHICKEN,
GID_CAMELOT,
GID_CASTLEBRAIN,
+ GID_CHEST,
GID_CHRISTMAS1988,
GID_CHRISTMAS1990,
GID_CHRISTMAS1992,
@@ -228,6 +229,26 @@ public:
bool canLoadGameStateCurrently();
bool canSaveGameStateCurrently();
void syncSoundSettings();
+
+ /**
+ * Syncs the audio options of the ScummVM launcher (speech, subtitles or
+ * both) with the in-game audio options of certain CD game versions. For
+ * some games, this allows simultaneous playing of speech and subtitles,
+ * even if the original games didn't support this feature.
+ *
+ * SCI1.1 games which support simultaneous speech and subtitles:
+ * - EcoQuest 1 CD
+ * - Leisure Suit Larry 6 CD
+ * SCI1.1 games which don't support simultaneous speech and subtitles,
+ * and we add this functionality in ScummVM:
+ * - Space Quest 4 CD
+ * - Freddy Pharkas 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
+ */
void syncIngameAudioOptions();
const SciGameId &getGameId() const { return _gameId; }
diff --git a/engines/sci/sound/drivers/fmtowns.cpp b/engines/sci/sound/drivers/fmtowns.cpp
index 6d8bb2e525..21cb2f1e43 100644
--- a/engines/sci/sound/drivers/fmtowns.cpp
+++ b/engines/sci/sound/drivers/fmtowns.cpp
@@ -52,8 +52,8 @@ public:
uint16 _duration;
private:
- uint8 _id;
- uint8 _velo;
+ uint8 _id;
+ uint8 _velo;
uint8 _program;
MidiDriver_FMTowns *_drv;
@@ -76,7 +76,7 @@ public:
void addChannels(int num);
void dropChannels(int num);
-
+
uint8 currentProgram() const;
private:
@@ -132,7 +132,7 @@ private:
TownsMidiPart **_parts;
TownsChannel **_out;
-
+
uint8 _masterVolume;
bool _soundOn;
@@ -590,7 +590,7 @@ void MidiDriver_FMTowns::addMissingChannels() {
avlChan -= _parts[i]->_chanMissing;
uint8 m = _parts[i]->_chanMissing;
_parts[i]->_chanMissing = 0;
- _parts[i]->addChannels(m);
+ _parts[i]->addChannels(m);
} else {
_parts[i]->_chanMissing -= avlChan;
_parts[i]->addChannels(avlChan);
@@ -601,7 +601,7 @@ void MidiDriver_FMTowns::addMissingChannels() {
void MidiDriver_FMTowns::updateParser() {
if (_timerProc)
- _timerProc(_timerProcPara);
+ _timerProc(_timerProcPara);
}
void MidiDriver_FMTowns::updateChannels() {
diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp
index 422948f975..4e54797960 100644
--- a/engines/sci/sound/midiparser_sci.cpp
+++ b/engines/sci/sound/midiparser_sci.cpp
@@ -98,7 +98,7 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in
midiMixChannels();
}
- _num_tracks = 1;
+ _numTracks = 1;
_tracks[0] = _mixedData;
if (_pSnd)
setTrack(0);
@@ -144,7 +144,7 @@ byte *MidiParser_SCI::midiMixChannels() {
_mixedData = outData;
long ticker = 0;
byte channelNr, curDelta;
- byte midiCommand = 0, midiParam, global_prev = 0;
+ byte midiCommand = 0, midiParam, globalPrev = 0;
long newDelta;
SoundResource::Channel *channel;
@@ -190,13 +190,13 @@ byte *MidiParser_SCI::midiMixChannels() {
byte midiChannel = midiCommand & 0xF;
_channelUsed[midiChannel] = true;
- if (midiCommand != global_prev)
+ if (midiCommand != globalPrev)
*outData++ = midiCommand;
*outData++ = midiParam;
if (nMidiParams[(midiCommand >> 4) - 8] == 2)
*outData++ = channel->data[channel->curPos++];
channel->prev = midiCommand;
- global_prev = midiCommand;
+ globalPrev = midiCommand;
}
}
@@ -372,8 +372,8 @@ void MidiParser_SCI::unloadMusic() {
resetTracking();
allNotesOff();
}
- _num_tracks = 0;
- _active_track = 255;
+ _numTracks = 0;
+ _activeTrack = 255;
_resetOnPause = false;
if (_mixedData) {
@@ -454,26 +454,26 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
debugC(4, kDebugLevelSound, "signal %04x", _signalToSet);
}
- info.start = _position._play_pos;
+ info.start = _position._playPos;
info.delta = 0;
- while (*_position._play_pos == 0xF8) {
+ while (*_position._playPos == 0xF8) {
info.delta += 240;
- _position._play_pos++;
+ _position._playPos++;
}
- info.delta += *(_position._play_pos++);
+ info.delta += *(_position._playPos++);
// Process the next info.
- if ((_position._play_pos[0] & 0xF0) >= 0x80)
- info.event = *(_position._play_pos++);
+ if ((_position._playPos[0] & 0xF0) >= 0x80)
+ info.event = *(_position._playPos++);
else
- info.event = _position._running_status;
+ info.event = _position._runningStatus;
if (info.event < 0x80)
return;
- _position._running_status = info.event;
+ _position._runningStatus = info.event;
switch (info.command()) {
case 0xC:
- info.basic.param1 = *(_position._play_pos++);
+ info.basic.param1 = *(_position._playPos++);
info.basic.param2 = 0;
if (info.channel() == 0xF) {// SCI special case
if (info.basic.param1 != kSetSignalLoop) {
@@ -488,23 +488,23 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
// 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._play_tick || info.delta) {
+ _position._playTick || info.delta) {
_signalSet = true;
_signalToSet = info.basic.param1;
}
} else {
- _loopTick = _position._play_tick + info.delta;
+ _loopTick = _position._playTick + info.delta;
}
}
break;
case 0xD:
- info.basic.param1 = *(_position._play_pos++);
+ info.basic.param1 = *(_position._playPos++);
info.basic.param2 = 0;
break;
case 0xB:
- info.basic.param1 = *(_position._play_pos++);
- info.basic.param2 = *(_position._play_pos++);
+ 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
@@ -588,8 +588,8 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
case 0x9:
case 0xA:
case 0xE:
- info.basic.param1 = *(_position._play_pos++);
- info.basic.param2 = *(_position._play_pos++);
+ 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;
@@ -598,12 +598,12 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
case 0xF: // System Common, Meta or SysEx event
switch (info.event & 0x0F) {
case 0x2: // Song Position Pointer
- info.basic.param1 = *(_position._play_pos++);
- info.basic.param2 = *(_position._play_pos++);
+ info.basic.param1 = *(_position._playPos++);
+ info.basic.param2 = *(_position._playPos++);
break;
case 0x3: // Song Select
- info.basic.param1 = *(_position._play_pos++);
+ info.basic.param1 = *(_position._playPos++);
info.basic.param2 = 0;
break;
@@ -617,16 +617,16 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
break;
case 0x0: // SysEx
- info.length = readVLQ(_position._play_pos);
- info.ext.data = _position._play_pos;
- _position._play_pos += info.length;
+ info.length = readVLQ(_position._playPos);
+ info.ext.data = _position._playPos;
+ _position._playPos += info.length;
break;
case 0xF: // META event
- info.ext.type = *(_position._play_pos++);
- info.length = readVLQ(_position._play_pos);
- info.ext.data = _position._play_pos;
- _position._play_pos += info.length;
+ 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--;
@@ -677,21 +677,21 @@ void MidiParser_SCI::allNotesOff() {
// Turn off all active notes
for (i = 0; i < 128; ++i) {
for (j = 0; j < 16; ++j) {
- if ((_active_notes[i] & (1 << j)) && (_channelRemap[j] != -1)){
+ if ((_activeNotes[i] & (1 << j)) && (_channelRemap[j] != -1)){
sendToDriver(0x80 | j, i, 0);
}
}
}
// Turn off all hanging notes
- for (i = 0; i < ARRAYSIZE(_hanging_notes); i++) {
- byte midiChannel = _hanging_notes[i].channel;
- if ((_hanging_notes[i].time_left) && (_channelRemap[midiChannel] != -1)) {
- sendToDriver(0x80 | midiChannel, _hanging_notes[i].note, 0);
- _hanging_notes[i].time_left = 0;
+ for (i = 0; i < ARRAYSIZE(_hangingNotes); i++) {
+ byte midiChannel = _hangingNotes[i].channel;
+ if ((_hangingNotes[i].timeLeft) && (_channelRemap[midiChannel] != -1)) {
+ sendToDriver(0x80 | midiChannel, _hangingNotes[i].note, 0);
+ _hangingNotes[i].timeLeft = 0;
}
}
- _hanging_notes_count = 0;
+ _hangingNotesCount = 0;
// To be sure, send an "All Note Off" event (but not all MIDI devices
// support this...).
@@ -703,7 +703,7 @@ void MidiParser_SCI::allNotesOff() {
}
}
- memset(_active_notes, 0, sizeof(_active_notes));
+ memset(_activeNotes, 0, sizeof(_activeNotes));
}
void MidiParser_SCI::setMasterVolume(byte masterVolume) {
diff --git a/engines/sci/sound/midiparser_sci.h b/engines/sci/sound/midiparser_sci.h
index 82f34070a4..d3fd337644 100644
--- a/engines/sci/sound/midiparser_sci.h
+++ b/engines/sci/sound/midiparser_sci.h
@@ -65,7 +65,7 @@ public:
void setMasterVolume(byte masterVolume);
void setVolume(byte volume);
void stop() {
- _abort_parse = true;
+ _abortParse = true;
allNotesOff();
}
void pause() {
diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp
index 5d32f40f18..7782ab4e48 100644
--- a/engines/sci/sound/soundcmd.cpp
+++ b/engines/sci/sound/soundcmd.cpp
@@ -340,6 +340,12 @@ reg_t SoundCommandParser::kDoSoundMasterVolume(int argc, reg_t *argv, reg_t acc)
reg_t SoundCommandParser::kDoSoundFade(int argc, reg_t *argv, reg_t acc) {
reg_t obj = argv[0];
+ // The object can be null in several SCI0 games (e.g. Camelot, KQ1, KQ4, MUMG).
+ // Check bugs #3035149, #3036942 and #3578335.
+ // In this case, we just ignore the call.
+ if (obj.isNull() && argc == 1)
+ return acc;
+
MusicEntry *musicSlot = _music->getSlot(obj);
if (!musicSlot) {
debugC(kDebugLevelSound, "kDoSound(fade): Slot not found (%04x:%04x)", PRINT_REG(obj));
diff --git a/engines/sci/video/robot_decoder.cpp b/engines/sci/video/robot_decoder.cpp
index 608c77136f..0337a8d306 100644
--- a/engines/sci/video/robot_decoder.cpp
+++ b/engines/sci/video/robot_decoder.cpp
@@ -109,13 +109,13 @@ bool RobotDecoder::loadStream(Common::SeekableReadStream *stream) {
}
bool RobotDecoder::load(GuiResourceId id) {
- // TODO: RAMA's robot 1003 cannot be played (shown at the menu screen) -
+ // TODO: RAMA's robot 1003 cannot be played (shown at the menu screen) -
// its drawn at odd coordinates. SV can't play it either (along with some
// others), so it must be some new functionality added in RAMA's robot
// videos. Skip it for now.
if (g_sci->getGameId() == GID_RAMA && id == 1003)
return false;
-
+
// TODO: The robot video in the Lighthouse demo gets stuck
if (g_sci->getGameId() == GID_LIGHTHOUSE && id == 16)
return false;
@@ -247,7 +247,7 @@ void RobotDecoder::readNextPacket() {
audioTrack->queueBuffer(g_sci->_audio->getDecodedRobotAudioFrame(_fileStream, audioChunkSize), audioChunkSize * 2);
} else {
_fileStream->skip(audioChunkSize);
- }
+ }
}
void RobotDecoder::readHeaderChunk() {
diff --git a/engines/sci/video/robot_decoder.h b/engines/sci/video/robot_decoder.h
index ebc3262939..437954f7fb 100644
--- a/engines/sci/video/robot_decoder.h
+++ b/engines/sci/video/robot_decoder.h
@@ -45,13 +45,13 @@ public:
bool loadStream(Common::SeekableReadStream *stream);
bool load(GuiResourceId id);
void close();
-
+
void setPos(uint16 x, uint16 y) { _pos = Common::Point(x, y); }
Common::Point getPos() const { return _pos; }
protected:
void readNextPacket();
-
+
private:
class RobotVideoTrack : public FixedRateVideoTrack {
public:
diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp
index b8722b6963..0c375efcdd 100644
--- a/engines/scumm/actor.cpp
+++ b/engines/scumm/actor.cpp
@@ -573,19 +573,19 @@ bool Actor_v2::checkWalkboxesHaveDirectPath(Common::Point &foundPath) {
return false;
}
-bool Actor_v0::intersectLineSegments(const Common::Point &line1Start, const Common::Point &line1End,
- const Common::Point &line2Start, const Common::Point &line2End, Common::Point &result)
+bool Actor_v0::intersectLineSegments(const Common::Point &line1Start, const Common::Point &line1End,
+ const Common::Point &line2Start, const Common::Point &line2End, Common::Point &result)
{
const Common::Point v1 = line1End - line1Start; // line1(n1) = line1Start + n1 * v1
const Common::Point v2 = line2End - line2Start; // line2(n2) = line2Start + n2 * v2
-
+
double det = v2.x * v1.y - v1.x * v2.y;
if (det == 0)
return false;
- double n1 = ((double)v2.x * (line2Start.y - line1Start.y) -
+ double n1 = ((double)v2.x * (line2Start.y - line1Start.y) -
(double)v2.y * (line2Start.x - line1Start.x)) / det;
- double n2 = ((double)v1.x * (line2Start.y - line1Start.y) -
+ double n2 = ((double)v1.x * (line2Start.y - line1Start.y) -
(double)v1.y * (line2Start.x - line1Start.x)) / det;
// both coefficients have to be in [0, 1], otherwise the intersection is
@@ -599,16 +599,16 @@ bool Actor_v0::intersectLineSegments(const Common::Point &line1Start, const Comm
}
/*
- * MM v0 allows the actor to walk in a direct line between boxes to the target
+ * MM v0 allows the actor to walk in a direct line between boxes to the target
* if actor and target share a horizontal or vertical corridor.
- * If such a corridor is found the actor is not forced to go horizontally or
+ * If such a corridor is found the actor is not forced to go horizontally or
* vertically from one box to the next but can also walk diagonally.
*
- * Note: the original v0 interpreter sets the target destination for diagonal
+ * Note: the original v0 interpreter sets the target destination for diagonal
* walking only once and then rechecks whenever the actor reaches a new box if the
- * walk destination is still suitable for the current box.
- * ScummVM does not perform such a check, so it is possible to leave the walkboxes
- * in some cases, for example L-shaped rooms like the swimming pool (actor walks over water)
+ * walk destination is still suitable for the current box.
+ * ScummVM does not perform such a check, so it is possible to leave the walkboxes
+ * in some cases, for example L-shaped rooms like the swimming pool (actor walks over water)
* or the medical room (actor walks over examination table).
* To solve this we intersect the new walk destination with the actor's walkbox borders,
* so a recheck is done when the actor leaves his box. This is done by the
@@ -992,7 +992,7 @@ void Actor_v0::setDirection(int direction) {
res = 7; // Face Camera
break;
}
-
+
_animFrameRepeat = -1;
animateActor(res);
if (_moving)
@@ -1408,7 +1408,7 @@ void Actor::showActor() {
if (_vm->_game.version == 0) {
Actor_v0 *a = ((Actor_v0 *)this);
-
+
a->_costCommand = a->_costCommandNew = 0xFF;
for (int i = 0; i < 8; ++i) {
@@ -2056,7 +2056,7 @@ void Actor_v0::animateCostume() {
void Actor_v0::speakCheck() {
if (v0ActorTalkArray[_number] & 0x80)
return;
-
+
int cmd = newDirToOldDir(_facing);
if (_speaking & 0x80)
@@ -2884,7 +2884,7 @@ void Actor_v0::animateActor(int anim) {
_costCommandNew = anim;
_vm->_costumeLoader->costumeDecodeData(this, 0, 0);
-
+
if (dir == -1)
return;
diff --git a/engines/scumm/actor.h b/engines/scumm/actor.h
index 0ed239d005..a733fdb4ed 100644
--- a/engines/scumm/actor.h
+++ b/engines/scumm/actor.h
@@ -377,7 +377,7 @@ public:
virtual void saveLoadWithSerializer(Serializer *ser);
protected:
- bool intersectLineSegments(const Common::Point &line1Start, const Common::Point &line1End,
+ bool intersectLineSegments(const Common::Point &line1Start, const Common::Point &line1End,
const Common::Point &line2Start, const Common::Point &line2End, Common::Point &result);
virtual bool checkWalkboxesHaveDirectPath(Common::Point &foundPath);
};
diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp
index 4064853b6b..9ae75b6683 100644
--- a/engines/scumm/charset.cpp
+++ b/engines/scumm/charset.cpp
@@ -69,7 +69,7 @@ void ScummEngine::loadCJKFont() {
_cjkFont->setDrawingMode(Graphics::FontSJIS::kShadowMode);
_2byteWidth = _2byteHeight = 12;
- _useCJKMode = true;
+ _useCJKMode = true;
#endif
} else if (_game.id == GID_MONKEY && _game.platform == Common::kPlatformSegaCD && _language == Common::JA_JPN) {
int numChar = 1413;
@@ -499,7 +499,7 @@ int CharsetRendererV3::getCharWidth(uint16 chr) {
if (_vm->_useCJKMode && (chr & 0x80))
spacing = _vm->_2byteWidth / 2;
-
+
if (!spacing)
spacing = *(_widthTable + chr);
@@ -644,7 +644,7 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {
drawBits1(*vs, _left + vs->xstart, drawTop, charPtr, drawTop, origWidth, origHeight);
else
drawBits1(_vm->_textSurface, _left * _vm->_textSurfaceMultiplier, _top * _vm->_textSurfaceMultiplier, charPtr, drawTop, origWidth, origHeight);
-
+
if (is2byte) {
origWidth /= _vm->_textSurfaceMultiplier;
height /= _vm->_textSurfaceMultiplier;
@@ -1399,7 +1399,7 @@ void CharsetRendererTownsClassic::drawBitsN(const Graphics::Surface&, byte *dst,
_vm->_cjkFont->drawChar(_vm->_textSurface, _sjisCurChar, _left * _vm->_textSurfaceMultiplier, (_top - _vm->_screenTop) * _vm->_textSurfaceMultiplier, _vm->_townsCharsetColorMap[1], _shadowColor);
return;
}
-
+
bool scale2x = (_vm->_textSurfaceMultiplier == 2);
dst = (byte *)_vm->_textSurface.pixels + (_top - _vm->_screenTop) * _vm->_textSurface.pitch * _vm->_textSurfaceMultiplier + _left * _vm->_textSurfaceMultiplier;
diff --git a/engines/scumm/charset.h b/engines/scumm/charset.h
index b8f1d84045..1c1df51921 100644
--- a/engines/scumm/charset.h
+++ b/engines/scumm/charset.h
@@ -112,7 +112,7 @@ public:
class CharsetRendererClassic : public CharsetRendererCommon {
protected:
virtual void drawBitsN(const Graphics::Surface &s, byte *dst, const byte *src, byte bpp, int drawTop, int width, int height);
- void printCharIntern(bool is2byte, const byte *charPtr, int origWidth, int origHeight, int width, int height, VirtScreen *vs, bool ignoreCharsetMask);
+ void printCharIntern(bool is2byte, const byte *charPtr, int origWidth, int origHeight, int width, int height, VirtScreen *vs, bool ignoreCharsetMask);
virtual bool prepareDraw(uint16 chr);
int _width, _height, _origWidth, _origHeight;
@@ -195,7 +195,7 @@ public:
int getCharWidth(uint16 chr);
int getFontHeight();
-
+
private:
void enableShadow(bool enable);
void drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height);
diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp
index 3f89bc9611..4ebdd00fdc 100644
--- a/engines/scumm/costume.cpp
+++ b/engines/scumm/costume.cpp
@@ -1188,7 +1188,7 @@ byte V0CostumeRenderer::drawLimb(const Actor *a, int limb) {
_draw_top = 200;
_draw_bottom = 0;
}
-
+
// Invalid current position?
if (a->_cost.curpos[limb] == 0xFFFF)
return 0;
@@ -1377,7 +1377,7 @@ byte V0CostumeLoader::increaseAnim(Actor *a, int limb) {
// Reset the comstume command
a0->_costCommandNew = 0xFF;
a0->_costCommand = 0xFF;
-
+
// Set the frame/start to invalid
a0->_cost.frame[limb] = 0xFFFF;
a0->_cost.start[limb] = 0xFFFF;
diff --git a/engines/scumm/cursor.cpp b/engines/scumm/cursor.cpp
index 88681898f5..269ae9e10a 100644
--- a/engines/scumm/cursor.cpp
+++ b/engines/scumm/cursor.cpp
@@ -180,7 +180,7 @@ void ScummEngine_v70he::setDefaultCursor() {
0xff, 0xff, 0xff,
0, 0, 0, };
-
+
memset(_grabbedCursor, 5, sizeof(_grabbedCursor));
_cursor.hotspotX = _cursor.hotspotY = 2;
diff --git a/engines/scumm/debugger.cpp b/engines/scumm/debugger.cpp
index edcf2e6fea..dc5acbdb7d 100644
--- a/engines/scumm/debugger.cpp
+++ b/engines/scumm/debugger.cpp
@@ -382,7 +382,7 @@ bool ScummDebugger::Cmd_Actor(int argc, const char **argv) {
DebugPrintf("Actor[%d].costume = %d\n", actnum, a->_costume);
}
} else if (!strcmp(argv[2], "name")) {
- DebugPrintf("Name of actor %d: %s\n", actnum,
+ DebugPrintf("Name of actor %d: %s\n", actnum,
_vm->getObjOrActorName(_vm->actorToObj(actnum)));
} else if (!strcmp(argv[2], "condmask")) {
if (argc > 3) {
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index 5404c7f8b1..e5c3023380 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -242,6 +242,10 @@ static Common::String generateFilenameForDetection(const char *pattern, Filename
return result;
}
+bool ScummEngine::isMacM68kIMuse() const {
+ return _game.platform == Common::kPlatformMacintosh && (_game.id == GID_MONKEY2 || _game.id == GID_INDY4) && !(_game.features & GF_MAC_CONTAINER);
+}
+
struct DetectorDesc {
Common::FSNode node;
Common::String md5;
@@ -473,6 +477,11 @@ static void computeGameSettingsFromMD5(const Common::FSList &fslist, const GameF
if (dr.language == UNK_LANG) {
dr.language = detectLanguage(fslist, dr.game.id);
}
+
+ // HACK: Detect between 68k and PPC versions
+ if (dr.game.platform == Common::kPlatformMacintosh && dr.game.version >= 5 && dr.game.heversion == 0 && strstr(gfp->pattern, "Data"))
+ dr.game.features |= GF_MAC_CONTAINER;
+
break;
}
}
diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h
index be1b90e356..3120017db6 100644
--- a/engines/scumm/detection_tables.h
+++ b/engines/scumm/detection_tables.h
@@ -236,7 +236,7 @@ static const GameSettings gameVariantsTable[] = {
{"monkey", "VGA", "vga", GID_MONKEY_VGA, 4, 0, MDT_PCSPK | MDT_PCJR | MDT_CMS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO1(GUIO_NOSPEECH)},
{"monkey", "EGA", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_PCJR | MDT_CMS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, GF_16COLOR, Common::kPlatformPC, GUIO1(GUIO_NOSPEECH)},
{"monkey", "No AdLib", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_PCJR, GF_16COLOR, Common::kPlatformAtariST, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)},
- {"monkey", "Demo", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_PCJR | MDT_ADLIB, GF_16COLOR, Common::kPlatformPC, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)},
+ {"monkey", "Demo", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_PCJR | MDT_CMS | MDT_ADLIB, GF_16COLOR, Common::kPlatformPC, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)},
{"monkey", "CD", 0, GID_MONKEY, 5, 0, MDT_ADLIB, GF_AUDIOTRACKS, UNK, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)},
{"monkey", "FM-TOWNS", 0, GID_MONKEY, 5, 0, MDT_TOWNS, GF_AUDIOTRACKS, Common::kPlatformFMTowns, GUIO4(GUIO_NOSPEECH, GUIO_NOMIDI, GUIO_MIDITOWNS, GUIO_NOASPECT)},
{"monkey", "SEGA", 0, GID_MONKEY, 5, 0, MDT_NONE, GF_AUDIOTRACKS, Common::kPlatformSegaCD, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)},
diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp
index 0e531daf73..945c5b6611 100644
--- a/engines/scumm/dialogs.cpp
+++ b/engines/scumm/dialogs.cpp
@@ -180,7 +180,7 @@ static const ResString string_map_table_v345[] = {
// "Moechten Sie wirklich neu starten? (J/N)J"
// Will react to J as 'Yes'
{5, _s("Are you sure you want to restart? (Y/N)")},
- // I18N: you may specify 'Yes' symbol at the end of the line. See previous comment
+ // I18N: you may specify 'Yes' symbol at the end of the line. See previous comment
{6, _s("Are you sure you want to quit? (Y/N)")},
// Added in SCUMM4
diff --git a/engines/scumm/he/logic/soccer.cpp b/engines/scumm/he/logic/soccer.cpp
index 05f377a736..2b29f93173 100644
--- a/engines/scumm/he/logic/soccer.cpp
+++ b/engines/scumm/he/logic/soccer.cpp
@@ -303,7 +303,7 @@ int LogicHEsoccer::op_1008(int outArray, int srcX, int srcY, int srcZ, int vecX,
putInArray(outArray, segmentsSoFar, 5, vecX);
putInArray(outArray, segmentsSoFar, 6, vecY);
putInArray(outArray, segmentsSoFar++, 7, vecZ);
- }
+ }
} else {
srcY = 0;
int thisVecX = vecX;
@@ -628,7 +628,7 @@ int LogicHEsoccer::op_1014(int32 srcX, int32 srcY, int32 srcZ, int32 velX, int32
adjustedVelZ = ((double)srcZ - 3869.0) / 100.0;
break;
}
-
+
int foundCollision = 0;
// work out which collision objects we might collide with (if any)
diff --git a/engines/scumm/he/wiz_he.cpp b/engines/scumm/he/wiz_he.cpp
index 47b4b8ad33..798f703db6 100644
--- a/engines/scumm/he/wiz_he.cpp
+++ b/engines/scumm/he/wiz_he.cpp
@@ -2286,8 +2286,7 @@ void Wiz::fillWizLine(const WizParameters *params) {
lineP.depth = bitDepth;
if (params->processFlags & kWPFParams) {
- assert (params->params2 == 1); // Catch untested usage
- Graphics::drawThickLine(x1, y1, x2, y2, params->params1, color, drawProc, &lineP);
+ Graphics::drawThickLine(x1, y1, x2, y2, params->params1, params->params2, color, drawProc, &lineP);
} else {
Graphics::drawLine(x1, y1, x2, y2, color, drawProc, &lineP);
}
diff --git a/engines/scumm/imuse/imuse.cpp b/engines/scumm/imuse/imuse.cpp
index 27a72c2afe..016ba89e7b 100644
--- a/engines/scumm/imuse/imuse.cpp
+++ b/engines/scumm/imuse/imuse.cpp
@@ -164,7 +164,7 @@ bool IMuseInternal::isMT32(int sound) {
return true;
case MKTAG('M', 'A', 'C', ' '): // Occurs in the Mac version of FOA and MI2
- return true;
+ return false;
case MKTAG('G', 'M', 'D', ' '):
return false;
@@ -226,6 +226,45 @@ bool IMuseInternal::isMIDI(int sound) {
return false;
}
+bool IMuseInternal::supportsPercussion(int sound) {
+ byte *ptr = g_scumm->_res->_types[rtSound][sound]._address;
+ if (ptr == NULL)
+ return false;
+
+ uint32 tag = READ_BE_UINT32(ptr);
+ switch (tag) {
+ case MKTAG('A', 'D', 'L', ' '):
+ case MKTAG('A', 'S', 'F', 'X'): // Special AD class for old AdLib sound effects
+ case MKTAG('S', 'P', 'K', ' '):
+ return false;
+
+ case MKTAG('A', 'M', 'I', ' '):
+ case MKTAG('R', 'O', 'L', ' '):
+ return true;
+
+ case MKTAG('M', 'A', 'C', ' '): // Occurs in the Mac version of FOA and MI2
+ // This is MIDI, i.e. uses MIDI style program changes, but without a
+ // special percussion channel.
+ return false;
+
+ case MKTAG('G', 'M', 'D', ' '):
+ case MKTAG('M', 'I', 'D', 'I'): // Occurs in Sam & Max
+ return true;
+ }
+
+ // Old style 'RO' has equivalent properties to 'ROL'
+ if (ptr[0] == 'R' && ptr[1] == 'O')
+ return true;
+ // Euphony tracks show as 'SO' and have equivalent properties to 'ADL'
+ // FIXME: Right now we're pretending it's GM.
+ if (ptr[4] == 'S' && ptr[5] == 'O')
+ return true;
+
+ error("Unknown music type: '%c%c%c%c'", (char)tag >> 24, (char)tag >> 16, (char)tag >> 8, (char)tag);
+
+ return false;
+}
+
MidiDriver *IMuseInternal::getBestMidiDriver(int sound) {
MidiDriver *driver = NULL;
diff --git a/engines/scumm/imuse/imuse_internal.h b/engines/scumm/imuse/imuse_internal.h
index 3b0d36e119..846e2d7545 100644
--- a/engines/scumm/imuse/imuse_internal.h
+++ b/engines/scumm/imuse/imuse_internal.h
@@ -204,6 +204,7 @@ protected:
bool _isMT32;
bool _isMIDI;
+ bool _supportsPercussion;
protected:
// Player part
@@ -458,6 +459,7 @@ protected:
byte *findStartOfSound(int sound, int ct = (kMThd | kFORM));
bool isMT32(int sound);
bool isMIDI(int sound);
+ bool supportsPercussion(int sound);
int get_queue_sound_status(int sound) const;
void handle_marker(uint id, byte data);
int get_channel_volume(uint a);
diff --git a/engines/scumm/imuse/imuse_part.cpp b/engines/scumm/imuse/imuse_part.cpp
index 73e7704469..89c16a8bb5 100644
--- a/engines/scumm/imuse/imuse_part.cpp
+++ b/engines/scumm/imuse/imuse_part.cpp
@@ -27,6 +27,7 @@
#include "common/util.h"
#include "scumm/imuse/imuse_internal.h"
#include "scumm/saveload.h"
+#include "scumm/scumm.h"
namespace Scumm {
@@ -365,7 +366,17 @@ void Part::set_instrument(uint b) {
_bank = (byte)(b >> 8);
if (_bank)
error("Non-zero instrument bank selection. Please report this");
- _instrument.program((byte)b, _player->isMT32());
+ // HACK: Horrible hack to allow tracing of program change source.
+ // The Mac m68k versions of MI2 and Indy4 use a different program "bank"
+ // when it gets program change events through the iMuse SysEx handler.
+ // We emulate this by introducing a special instrument, which sets
+ // the instrument via sysEx_customInstrument. This seems to be
+ // exclusively used for special sound effects like the "spit" sound.
+ if (g_scumm->isMacM68kIMuse()) {
+ _instrument.macSfx(b);
+ } else {
+ _instrument.program((byte)b, _player->isMT32());
+ }
if (clearToTransmit())
_instrument.send(_mc);
}
diff --git a/engines/scumm/imuse/imuse_player.cpp b/engines/scumm/imuse/imuse_player.cpp
index 53ccfb3734..3a9c42a920 100644
--- a/engines/scumm/imuse/imuse_player.cpp
+++ b/engines/scumm/imuse/imuse_player.cpp
@@ -78,6 +78,7 @@ Player::Player() :
_speed(128),
_isMT32(false),
_isMIDI(false),
+ _supportsPercussion(false),
_se(0),
_vol_chan(0) {
}
@@ -103,6 +104,7 @@ bool Player::startSound(int sound, MidiDriver *midi) {
_isMT32 = _se->isMT32(sound);
_isMIDI = _se->isMIDI(sound);
+ _supportsPercussion = _se->supportsPercussion(sound);
_parts = NULL;
_active = true;
@@ -386,6 +388,8 @@ void Player::sysEx(const byte *p, uint16 len) {
// SysEx manufacturer 0x97 has been spotted in the
// Monkey Island 2 AdLib music, so don't make this a
// fatal error. See bug #1481383.
+ // The Macintosh version of Monkey Island 2 simply
+ // ignores these SysEx events too.
if (a == 0)
warning("Unknown SysEx manufacturer 0x00 0x%02X 0x%02X", p[0], p[1]);
else
@@ -1009,6 +1013,7 @@ void Player::fixAfterLoad() {
_parser->jumpToTick(_music_tick); // start_seq_sound already switched tracks
_isMT32 = _se->isMT32(_id);
_isMIDI = _se->isMIDI(_id);
+ _supportsPercussion = _se->supportsPercussion(_id);
}
}
diff --git a/engines/scumm/imuse/instrument.cpp b/engines/scumm/imuse/instrument.cpp
index 11bb4e7605..61c73b1e2d 100644
--- a/engines/scumm/imuse/instrument.cpp
+++ b/engines/scumm/imuse/instrument.cpp
@@ -278,6 +278,21 @@ private:
byte _instrument[23];
};
+class Instrument_MacSfx : public InstrumentInternal {
+private:
+ byte _program;
+
+public:
+ Instrument_MacSfx(byte program);
+ Instrument_MacSfx(Serializer *s);
+ void saveOrLoad(Serializer *s);
+ void send(MidiChannel *mc);
+ void copy_to(Instrument *dest) { dest->macSfx(_program); }
+ bool is_valid() {
+ return (_program < 128);
+ }
+};
+
////////////////////////////////////////
//
// Instrument class members
@@ -326,6 +341,14 @@ void Instrument::pcspk(const byte *instrument) {
_instrument = new Instrument_PcSpk(instrument);
}
+void Instrument::macSfx(byte prog) {
+ clear();
+ if (prog > 127)
+ return;
+ _type = itMacSfx;
+ _instrument = new Instrument_MacSfx(prog);
+}
+
void Instrument::saveOrLoad(Serializer *s) {
if (s->isSaving()) {
s->saveByte(_type);
@@ -349,6 +372,9 @@ void Instrument::saveOrLoad(Serializer *s) {
case itPcSpk:
_instrument = new Instrument_PcSpk(s);
break;
+ case itMacSfx:
+ _instrument = new Instrument_MacSfx(s);
+ break;
default:
warning("No known instrument classification #%d", (int)_type);
_type = itNone;
@@ -528,4 +554,38 @@ void Instrument_PcSpk::send(MidiChannel *mc) {
mc->sysEx_customInstrument('SPK ', (byte *)&_instrument);
}
+////////////////////////////////////////
+//
+// Instrument_MacSfx class members
+//
+////////////////////////////////////////
+
+Instrument_MacSfx::Instrument_MacSfx(byte program) :
+ _program(program) {
+ if (program > 127) {
+ _program = 255;
+ }
+}
+
+Instrument_MacSfx::Instrument_MacSfx(Serializer *s) {
+ _program = 255;
+ if (!s->isSaving()) {
+ saveOrLoad(s);
+ }
+}
+
+void Instrument_MacSfx::saveOrLoad(Serializer *s) {
+ if (s->isSaving()) {
+ s->saveByte(_program);
+ } else {
+ _program = s->loadByte();
+ }
+}
+
+void Instrument_MacSfx::send(MidiChannel *mc) {
+ if (_program > 127) {
+ return;
+ }
+ mc->sysEx_customInstrument('MAC ', &_program);
+}
} // End of namespace Scumm
diff --git a/engines/scumm/imuse/instrument.h b/engines/scumm/imuse/instrument.h
index a855c64155..7e09e86fa5 100644
--- a/engines/scumm/imuse/instrument.h
+++ b/engines/scumm/imuse/instrument.h
@@ -52,7 +52,8 @@ public:
itProgram = 1,
itAdLib = 2,
itRoland = 3,
- itPcSpk = 4
+ itPcSpk = 4,
+ itMacSfx = 5
};
Instrument() : _type(0), _instrument(0) { }
@@ -72,6 +73,7 @@ public:
void adlib(const byte *instrument);
void roland(const byte *instrument);
void pcspk(const byte *instrument);
+ void macSfx(byte program);
byte getType() { return _type; }
bool isValid() { return (_instrument ? _instrument->is_valid() : false); }
diff --git a/engines/scumm/imuse/mac_m68k.cpp b/engines/scumm/imuse/mac_m68k.cpp
new file mode 100644
index 0000000000..0980ef1fd2
--- /dev/null
+++ b/engines/scumm/imuse/mac_m68k.cpp
@@ -0,0 +1,514 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "scumm/imuse/mac_m68k.h"
+
+#include "common/util.h"
+#include "common/macresman.h"
+#include "common/stream.h"
+
+namespace Scumm {
+
+MacM68kDriver::MacM68kDriver(Audio::Mixer *mixer)
+ : MidiDriver_Emulated(mixer) {
+}
+
+MacM68kDriver::~MacM68kDriver() {
+}
+
+int MacM68kDriver::open() {
+ if (_isOpen) {
+ return MERR_ALREADY_OPEN;
+ }
+
+ const int error = MidiDriver_Emulated::open();
+ if (error) {
+ return error;
+ }
+
+ for (uint i = 0; i < ARRAYSIZE(_channels); ++i) {
+ _channels[i].init(this, i);
+ }
+
+ memset(_voiceChannels, 0, sizeof(_voiceChannels));
+ _lastUsedVoiceChannel = 0;
+
+ loadAllInstruments();
+
+ _pitchTable[116] = 1664510;
+ _pitchTable[117] = 1763487;
+ _pitchTable[118] = 1868350;
+ _pitchTable[119] = 1979447;
+ _pitchTable[120] = 2097152;
+ _pitchTable[121] = 2221855;
+ _pitchTable[122] = 2353973;
+ _pitchTable[123] = 2493948;
+ _pitchTable[124] = 2642246;
+ _pitchTable[125] = 2799362;
+ _pitchTable[126] = 2965820;
+ _pitchTable[127] = 3142177;
+ for (int i = 115; i >= 0; --i) {
+ _pitchTable[i] = _pitchTable[i + 12] / 2;
+ }
+
+ _volumeTable = new byte[8192];
+ for (int i = 0; i < 32; ++i) {
+ for (int j = 0; j < 256; ++j) {
+ _volumeTable[i * 256 + j] = ((-128 + j) * _volumeBaseTable[i]) / 127 - 128;
+ }
+ }
+
+ _mixBuffer = 0;
+ _mixBufferLength = 0;
+
+ // We set the output sound type to music here to allow sound volume
+ // adjustment. The drawback here is that we can not control the music and
+ // sfx separately here. But the AdLib output has the same issue so it
+ // should not be that bad.
+ _mixer->playStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+
+ return 0;
+}
+
+void MacM68kDriver::close() {
+ if (!_isOpen) {
+ return;
+ }
+
+ _mixer->stopHandle(_mixerSoundHandle);
+ _isOpen = false;
+ for (InstrumentMap::iterator i = _instruments.begin(); i != _instruments.end(); ++i) {
+ delete[] i->_value.data;
+ }
+ _instruments.clear();
+ delete[] _volumeTable;
+ _volumeTable = 0;
+ delete[] _mixBuffer;
+ _mixBuffer = 0;
+ _mixBufferLength = 0;
+}
+
+void MacM68kDriver::send(uint32 d) {
+ assert(false);
+}
+
+void MacM68kDriver::sysEx_customInstrument(byte channel, uint32 type, const byte *instr) {
+ assert(false);
+}
+
+MidiChannel *MacM68kDriver::allocateChannel() {
+ for (uint i = 0; i < ARRAYSIZE(_channels); ++i) {
+ if (_channels[i].allocate()) {
+ return &_channels[i];
+ }
+ }
+
+ return 0;
+}
+
+MacM68kDriver::Instrument MacM68kDriver::getInstrument(int idx) const {
+ InstrumentMap::const_iterator i = _instruments.find(idx);
+ if (i != _instruments.end()) {
+ return i->_value;
+ } else {
+ return _defaultInstrument;
+ }
+}
+
+void MacM68kDriver::generateSamples(int16 *buf, int len) {
+ int silentChannels = 0;
+
+ if (_mixBufferLength < len) {
+ delete[] _mixBuffer;
+
+ _mixBufferLength = len;
+ _mixBuffer = new int[_mixBufferLength];
+ assert(_mixBuffer);
+ }
+ memset(_mixBuffer, 0, sizeof(int) * _mixBufferLength);
+
+ for (int i = 0; i < kChannelCount; ++i) {
+ OutputChannel &out = _voiceChannels[i].out;
+ if (out.isFinished) {
+ ++silentChannels;
+ continue;
+ }
+
+ byte *volumeTable = &_volumeTable[(out.volume / 4) * 256];
+ int *buffer = _mixBuffer;
+
+ int samplesLeft = len;
+ while (samplesLeft) {
+ out.subPos += out.pitchModifier;
+ while (out.subPos >= 0x10000) {
+ out.subPos -= 0x10000;
+ out.instrument++;
+ }
+
+ if (out.instrument >= out.end) {
+ if (!out.start) {
+ break;
+ }
+
+ out.instrument = out.start;
+ out.subPos = 0;
+ }
+
+ *buffer++ += volumeTable[*out.instrument];
+ --samplesLeft;
+ }
+
+ if (samplesLeft) {
+ out.isFinished = true;
+ while (samplesLeft--) {
+ *buffer++ += 0x80;
+ }
+ }
+ }
+
+ const int *buffer = _mixBuffer;
+ const int silenceAdd = silentChannels << 7;
+ while (len--) {
+ *buf++ = (((*buffer++ + silenceAdd) >> 3) << 8) ^ 0x8000;
+ }
+}
+
+void MacM68kDriver::loadAllInstruments() {
+ Common::MacResManager resource;
+ if (resource.open("iMUSE Setups")) {
+ if (!resource.hasResFork()) {
+ error("MacM68kDriver::loadAllInstruments: \"iMUSE Setups\" loaded, but no resource fork present");
+ }
+
+ for (int i = 0x3E7; i < 0x468; ++i) {
+ Common::SeekableReadStream *stream = resource.getResource(MKTAG('s', 'n', 'd', ' '), i);
+ if (stream) {
+ addInstrument(i, stream);
+ delete stream;
+ }
+ }
+
+ for (int i = 0x7D0; i < 0x8D0; ++i) {
+ Common::SeekableReadStream *stream = resource.getResource(MKTAG('s', 'n', 'd', ' '), i);
+ if (stream) {
+ addInstrument(i, stream);
+ delete stream;
+ }
+ }
+
+ InstrumentMap::iterator inst = _instruments.find(kDefaultInstrument);
+ if (inst != _instruments.end()) {
+ _defaultInstrument = inst->_value;
+ } else {
+ error("MacM68kDriver::loadAllInstruments: Could not load default instrument");
+ }
+ } else {
+ error("MacM68kDriver::loadAllInstruments: Could not load \"iMUSE Setups\"");
+ }
+}
+
+void MacM68kDriver::addInstrument(int idx, Common::SeekableReadStream *data) {
+ // We parse the "SND" files manually here, since we need special data
+ // from their header and need to work on them raw while mixing.
+ data->skip(2);
+ int count = data->readUint16BE();
+ data->skip(2 * (3 * count));
+ count = data->readUint16BE();
+ data->skip(2 * (4 * count));
+
+ Instrument inst;
+ // Skip (optional) pointer to data
+ data->skip(4);
+ inst.length = data->readUint32BE();
+ inst.sampleRate = data->readUint32BE();
+ inst.loopStart = data->readUint32BE();
+ inst.loopEnd = data->readUint32BE();
+ // Skip encoding
+ data->skip(1);
+ inst.baseFrequency = data->readByte();
+
+ inst.data = new byte[inst.length];
+ assert(inst.data);
+ data->read(inst.data, inst.length);
+ _instruments[idx] = inst;
+}
+
+void MacM68kDriver::setPitch(OutputChannel *out, int frequency) {
+ out->frequency = frequency;
+ out->isFinished = false;
+
+ const int pitchIdx = (frequency >> 7) + 60 - out->baseFrequency;
+ assert(pitchIdx >= 0);
+
+ const int low7Bits = frequency & 0x7F;
+ if (low7Bits) {
+ out->pitchModifier = _pitchTable[pitchIdx] + (((_pitchTable[pitchIdx + 1] - _pitchTable[pitchIdx]) * low7Bits) >> 7);
+ } else {
+ out->pitchModifier = _pitchTable[pitchIdx];
+ }
+}
+
+void MacM68kDriver::VoiceChannel::off() {
+ if (out.start) {
+ out.isFinished = true;
+ }
+
+ part->removeVoice(this);
+ part = 0;
+}
+
+void MacM68kDriver::MidiChannel_MacM68k::release() {
+ _allocated = false;
+ while (_voice) {
+ _voice->off();
+ }
+}
+
+void MacM68kDriver::MidiChannel_MacM68k::send(uint32 b) {
+ uint8 type = b & 0xF0;
+ uint8 p1 = (b >> 8) & 0xFF;
+ uint8 p2 = (b >> 16) & 0xFF;
+
+ switch (type) {
+ case 0x80:
+ noteOff(p1);
+ break;
+
+ case 0x90:
+ if (p2) {
+ noteOn(p1, p2);
+ } else {
+ noteOff(p1);
+ }
+ break;
+
+ case 0xB0:
+ controlChange(p1, p2);
+ break;
+
+ case 0xE0:
+ pitchBend((p1 | (p2 << 7)) - 0x2000);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void MacM68kDriver::MidiChannel_MacM68k::noteOff(byte note) {
+ for (VoiceChannel *i = _voice; i; i = i->next) {
+ if (i->note == note) {
+ if (_sustain) {
+ i->sustainNoteOff = true;
+ } else {
+ i->off();
+ }
+ }
+ }
+}
+
+void MacM68kDriver::MidiChannel_MacM68k::noteOn(byte note, byte velocity) {
+ // Do not start a not unless there is an instrument set up
+ if (!_instrument.data) {
+ return;
+ }
+
+ // Allocate a voice channel
+ VoiceChannel *voice = _owner->allocateVoice(_priority);
+ if (!voice) {
+ return;
+ }
+ addVoice(voice);
+
+ voice->note = note;
+ // This completly ignores the note's volume, but is in accordance
+ // to the original.
+ voice->out.volume = _volume;
+
+ // Set up the instrument data
+ voice->out.baseFrequency = _instrument.baseFrequency;
+ voice->out.soundStart = _instrument.data;
+ voice->out.soundEnd = _instrument.data + _instrument.length;
+ if (_instrument.loopEnd && _instrument.loopEnd - 12 > _instrument.loopStart) {
+ voice->out.loopStart = _instrument.data + _instrument.loopStart;
+ voice->out.loopEnd = _instrument.data + _instrument.loopEnd;
+ } else {
+ voice->out.loopStart = 0;
+ voice->out.loopEnd = voice->out.soundEnd;
+ }
+
+ voice->out.start = voice->out.loopStart;
+ voice->out.end = voice->out.loopEnd;
+
+ // Set up the pitch
+ _owner->setPitch(&voice->out, (note << 7) + _pitchBend);
+
+ // Set up the sample position
+ voice->out.instrument = voice->out.soundStart;
+ voice->out.subPos = 0;
+}
+
+void MacM68kDriver::MidiChannel_MacM68k::programChange(byte program) {
+ _instrument = _owner->getInstrument(program + kProgramChangeBase);
+}
+
+void MacM68kDriver::MidiChannel_MacM68k::pitchBend(int16 bend) {
+ _pitchBend = (bend * _pitchBendFactor) >> 6;
+ for (VoiceChannel *i = _voice; i; i = i->next) {
+ _owner->setPitch(&i->out, (i->note << 7) + _pitchBend);
+ }
+}
+
+void MacM68kDriver::MidiChannel_MacM68k::controlChange(byte control, byte value) {
+ switch (control) {
+ // volume change
+ case 7:
+ _volume = value;
+ for (VoiceChannel *i = _voice; i; i = i->next) {
+ i->out.volume = value;
+ i->out.isFinished = false;
+ }
+ break;
+
+ // sustain
+ case 64:
+ _sustain = value;
+ if (!_sustain) {
+ for (VoiceChannel *i = _voice; i; i = i->next) {
+ if (i->sustainNoteOff) {
+ i->off();
+ }
+ }
+ }
+ break;
+
+ // all notes off
+ case 123:
+ for (VoiceChannel *i = _voice; i; i = i->next) {
+ i->off();
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void MacM68kDriver::MidiChannel_MacM68k::pitchBendFactor(byte value) {
+ _pitchBendFactor = value;
+}
+
+void MacM68kDriver::MidiChannel_MacM68k::priority(byte value) {
+ _priority = value;
+}
+
+void MacM68kDriver::MidiChannel_MacM68k::sysEx_customInstrument(uint32 type, const byte *instr) {
+ assert(instr);
+ if (type == 'MAC ') {
+ _instrument = _owner->getInstrument(*instr + kSysExBase);
+ }
+}
+
+void MacM68kDriver::MidiChannel_MacM68k::init(MacM68kDriver *owner, byte channel) {
+ _owner = owner;
+ _number = channel;
+ _allocated = false;
+}
+
+bool MacM68kDriver::MidiChannel_MacM68k::allocate() {
+ if (_allocated) {
+ return false;
+ }
+
+ _allocated = true;
+ _voice = 0;
+ _priority = 0;
+ memset(&_instrument, 0, sizeof(_instrument));
+ _pitchBend = 0;
+ _pitchBendFactor = 0;
+ _volume = 0;
+ return true;
+}
+
+void MacM68kDriver::MidiChannel_MacM68k::addVoice(VoiceChannel *voice) {
+ voice->next = _voice;
+ voice->prev = 0;
+ voice->part = this;
+ if (_voice) {
+ _voice->prev = voice;
+ }
+ _voice = voice;
+}
+
+void MacM68kDriver::MidiChannel_MacM68k::removeVoice(VoiceChannel *voice) {
+ VoiceChannel *i = _voice;
+ while (i && i != voice) {
+ i = i->next;
+ }
+
+ if (i) {
+ if (i->next) {
+ i->next->prev = i->prev;
+ }
+
+ if (i->prev) {
+ i->prev->next = i->next;
+ } else {
+ _voice = i->next;
+ }
+ }
+}
+
+MacM68kDriver::VoiceChannel *MacM68kDriver::allocateVoice(int priority) {
+ VoiceChannel *channel = 0;
+ for (int i = 0; i < kChannelCount; ++i) {
+ if (++_lastUsedVoiceChannel == kChannelCount) {
+ _lastUsedVoiceChannel = 0;
+ }
+
+ VoiceChannel *cur = &_voiceChannels[_lastUsedVoiceChannel];
+ if (!cur->part) {
+ memset(cur, 0, sizeof(*cur));
+ return cur;
+ } else if (!cur->next) {
+ if (cur->part->_priority <= priority) {
+ priority = cur->part->_priority;
+ channel = cur;
+ }
+ }
+ }
+
+ if (channel) {
+ channel->off();
+ memset(channel, 0, sizeof(*channel));
+ }
+
+ return channel;
+}
+
+const int MacM68kDriver::_volumeBaseTable[32] = {
+ 0, 0, 1, 1, 2, 3, 5, 6,
+ 8, 11, 13, 16, 19, 22, 26, 30,
+ 34, 38, 43, 48, 53, 58, 64, 70,
+ 76, 83, 89, 96, 104, 111, 119, 127
+};
+
+} // End of namespace Scumm
diff --git a/engines/scumm/imuse/mac_m68k.h b/engines/scumm/imuse/mac_m68k.h
new file mode 100644
index 0000000000..59e2f68b9b
--- /dev/null
+++ b/engines/scumm/imuse/mac_m68k.h
@@ -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.
+ */
+
+#ifndef SCUMM_IMUSE_MAC_M68K_H
+#define SCUMM_IMUSE_MAC_M68K_H
+
+#include "audio/softsynth/emumidi.h"
+
+#include "common/hashmap.h"
+
+namespace Common {
+class SeekableReadStream;
+}
+
+namespace Scumm {
+
+class MacM68kDriver : public MidiDriver_Emulated {
+ friend class MidiChannel_MacM68k;
+public:
+ MacM68kDriver(Audio::Mixer *mixer);
+ ~MacM68kDriver();
+
+ virtual int open();
+ virtual void close();
+
+ virtual void send(uint32 d);
+ virtual void sysEx_customInstrument(byte channel, uint32 type, const byte *instr);
+
+ virtual MidiChannel *allocateChannel();
+ virtual MidiChannel *getPercussionChannel() { return 0; }
+
+ virtual bool isStereo() const { return false; }
+ virtual int getRate() const {
+ // The original is using a frequency of approx. 22254.54546 here.
+ // To be precise it uses the 16.16 fixed point value 0x56EE8BA3.
+ return 22254;
+ }
+
+protected:
+ virtual void generateSamples(int16 *buf, int len);
+ virtual void onTimer() {}
+
+private:
+ int *_mixBuffer;
+ int _mixBufferLength;
+
+ struct Instrument {
+ uint length;
+ uint sampleRate;
+ uint loopStart;
+ uint loopEnd;
+ int baseFrequency;
+
+ byte *data;
+ };
+
+ enum {
+ kDefaultInstrument = 0x3E7,
+ kProgramChangeBase = 0x3E8,
+ kSysExBase = 0x7D0
+ };
+
+ Instrument getInstrument(int idx) const;
+ typedef Common::HashMap<int, Instrument> InstrumentMap;
+ InstrumentMap _instruments;
+ Instrument _defaultInstrument;
+ void loadAllInstruments();
+ void addInstrument(int idx, Common::SeekableReadStream *data);
+
+ struct OutputChannel {
+ int pitchModifier;
+
+ const byte *instrument;
+ uint subPos;
+
+ const byte *start;
+ const byte *end;
+
+ const byte *soundStart;
+ const byte *soundEnd;
+ const byte *loopStart;
+ const byte *loopEnd;
+
+ int frequency;
+ int volume;
+
+ bool isFinished;
+
+ int baseFrequency;
+ };
+
+ void setPitch(OutputChannel *out, int frequency);
+ int _pitchTable[128];
+
+ byte *_volumeTable;
+ static const int _volumeBaseTable[32];
+
+ class MidiChannel_MacM68k;
+
+ struct VoiceChannel {
+ MidiChannel_MacM68k *part;
+ VoiceChannel *prev, *next;
+ int channel;
+ int note;
+ bool sustainNoteOff;
+ OutputChannel out;
+
+ void off();
+ };
+
+ class MidiChannel_MacM68k : public MidiChannel {
+ friend class MacM68kDriver;
+ public:
+ virtual MidiDriver *device() { return _owner; }
+ virtual byte getNumber() { return _number; }
+ virtual void release();
+
+ virtual void send(uint32 b);
+ virtual void noteOff(byte note);
+ virtual void noteOn(byte note, byte velocity);
+ virtual void programChange(byte program);
+ virtual void pitchBend(int16 bend);
+ virtual void controlChange(byte control, byte value);
+ virtual void pitchBendFactor(byte value);
+ virtual void priority(byte value);
+ virtual void sysEx_customInstrument(uint32 type, const byte *instr);
+
+ void init(MacM68kDriver *owner, byte channel);
+ bool allocate();
+
+ void addVoice(VoiceChannel *voice);
+ void removeVoice(VoiceChannel *voice);
+ private:
+ MacM68kDriver *_owner;
+ bool _allocated;
+ int _number;
+
+ VoiceChannel *_voice;
+ int _priority;
+ int _sustain;
+ Instrument _instrument;
+ int _pitchBend;
+ int _pitchBendFactor;
+ int _volume;
+ };
+
+ MidiChannel_MacM68k _channels[32];
+
+ enum {
+ kChannelCount = 8
+ };
+ VoiceChannel _voiceChannels[kChannelCount];
+ int _lastUsedVoiceChannel;
+ VoiceChannel *allocateVoice(int priority);
+};
+
+} // End of namespace Scumm
+
+#endif
diff --git a/engines/scumm/imuse/sysex_scumm.cpp b/engines/scumm/imuse/sysex_scumm.cpp
index 85ffc86f47..8f230ebac3 100644
--- a/engines/scumm/imuse/sysex_scumm.cpp
+++ b/engines/scumm/imuse/sysex_scumm.cpp
@@ -71,7 +71,7 @@ void sysexHandler_Scumm(Player *player, const byte *msg, uint16 len) {
part->set_pri(buf[2]);
part->volume(buf[3]);
part->set_pan(buf[4]);
- part->_percussion = player->_isMIDI ? ((buf[5] & 0x80) > 0) : false;
+ part->_percussion = player->_supportsPercussion ? ((buf[5] & 0x80) > 0) : false;
part->set_transpose(buf[5]);
part->set_detune(buf[6]);
part->pitchBendFactor(buf[7]);
diff --git a/engines/scumm/midiparser_ro.cpp b/engines/scumm/midiparser_ro.cpp
index 1a31d1ca82..8549a9262d 100644
--- a/engines/scumm/midiparser_ro.cpp
+++ b/engines/scumm/midiparser_ro.cpp
@@ -62,13 +62,13 @@ void MidiParser_RO::parseNextEvent (EventInfo &info) {
info.delta = 0;
do {
- info.start = _position._play_pos;
- info.event = *(_position._play_pos++);
+ info.start = _position._playPos;
+ info.event = *(_position._playPos++);
if (info.command() == 0xA) {
++_lastMarkerCount;
info.event = 0xF0;
} else if (info.event == 0xF0 || info.event == 0xF1) {
- byte delay = *(_position._play_pos++);
+ byte delay = *(_position._playPos++);
info.delta += delay;
if (info.event == 0xF1) {
// This event is, as far as we have been able
@@ -95,16 +95,16 @@ void MidiParser_RO::parseNextEvent (EventInfo &info) {
if (info.event < 0x80)
return;
- _position._running_status = info.event;
+ _position._runningStatus = info.event;
switch (info.command()) {
case 0xC:
- info.basic.param1 = *(_position._play_pos++);
+ info.basic.param1 = *(_position._playPos++);
info.basic.param2 = 0;
break;
case 0x8: case 0x9: case 0xB:
- info.basic.param1 = *(_position._play_pos++);
- info.basic.param2 = *(_position._play_pos++);
+ 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;
@@ -133,7 +133,7 @@ bool MidiParser_RO::loadMusic (byte *data, uint32 size) {
return false;
}
- _num_tracks = 1;
+ _numTracks = 1;
_ppqn = 120;
_tracks[0] = pos + 2;
_markerCount = _lastMarkerCount = 0;
diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk
index 1f219f5187..8499c9bad3 100644
--- a/engines/scumm/module.mk
+++ b/engines/scumm/module.mk
@@ -27,6 +27,7 @@ MODULE_OBJS := \
imuse/imuse_part.o \
imuse/imuse_player.o \
imuse/instrument.o \
+ imuse/mac_m68k.o \
imuse/pcspk.o \
imuse/sysex_samnmax.o \
imuse/sysex_scumm.o \
diff --git a/engines/scumm/object.cpp b/engines/scumm/object.cpp
index 399cd91324..77c75c4ad6 100644
--- a/engines/scumm/object.cpp
+++ b/engines/scumm/object.cpp
@@ -335,7 +335,7 @@ int ScummEngine::whereIsObject(int object) const {
return WIO_NOT_FOUND;
if ((_game.version != 0 || OBJECT_V0_TYPE(object) == 0) &&
- _objectOwnerTable[object] != OF_OWNER_ROOM)
+ _objectOwnerTable[object] != OF_OWNER_ROOM)
{
for (i = 0; i < _numInventory; i++)
if (_inventory[i] == object)
@@ -1225,7 +1225,7 @@ byte *ScummEngine::getOBCDFromObject(int obj, bool v0CheckInventory) {
byte *ptr;
if ((_game.version != 0 || OBJECT_V0_TYPE(obj) == 0) &&
- _objectOwnerTable[obj] != OF_OWNER_ROOM)
+ _objectOwnerTable[obj] != OF_OWNER_ROOM)
{
if (_game.version == 0 && !v0CheckInventory)
return 0;
diff --git a/engines/scumm/player_apple2.cpp b/engines/scumm/player_apple2.cpp
index a8e150caa9..58e4f78a94 100644
--- a/engines/scumm/player_apple2.cpp
+++ b/engines/scumm/player_apple2.cpp
@@ -61,8 +61,8 @@ public:
private:
void _update(int interval /*a*/, int count /*y*/) { // D076
- assert(interval > 0); // 0 == 256?
- assert(count > 0); // 0 == 256?
+ assert(interval > 0); // 0 == 256?
+ assert(count > 0); // 0 == 256?
for (; count >= 0; --count) {
_player->speakerToggle();
@@ -99,7 +99,7 @@ public:
++_pos;
return false;
- }
+ }
return true;
}
@@ -112,7 +112,7 @@ private:
assert(interval > 0); // 0 == 256?
int a = (interval >> 3) + count;
- for (int y = a; y > 0; --y) {
+ for (int y = a; y > 0; --y) {
_player->generateSamples(1292 - 5*interval);
_player->speakerToggle();
@@ -206,7 +206,7 @@ private:
_bitmask1 = 0x3;
_bitmask2 = 0x3;
-
+
_updateInterval2 = param0;
if (_updateInterval2 == 0)
_bitmask2 = 0x0;
@@ -234,9 +234,9 @@ private:
if (_updateRemain2 == 0) {
_updateRemain2 = _updateInterval2;
- // use only first voice's data (bitmask1) if both voices are triggered
+ // use only first voice's data (bitmask1) if both voices are triggered
if (_updateRemain1 != 0) {
- _speakerShiftReg ^= _bitmask2;
+ _speakerShiftReg ^= _bitmask2;
}
}
@@ -256,7 +256,7 @@ private:
protected:
const byte *_params;
-
+
byte _updateRemain1;
byte _updateRemain2;
@@ -309,7 +309,7 @@ private:
for (int i = count; i > 0; --i) {
_player->generateSamples(10 + 5*interval);
_player->speakerToggle();
-
+
_player->generateSamples(5 + 5*interval);
_player->speakerToggle();
}
@@ -332,20 +332,20 @@ private:
// LD000[loc] ^ LD00A[loc]
const byte AppleII_SoundFunction5_Noise::_noiseTable[256] = {
- 0x65, 0x1b, 0xda, 0x11, 0x61, 0xe5, 0x77, 0x57, 0x92, 0xc8, 0x51, 0x1c, 0xd4, 0x91, 0x62, 0x63,
- 0x00, 0x38, 0x57, 0xd5, 0x18, 0xd8, 0xdc, 0x40, 0x03, 0x86, 0xd3, 0x2f, 0x10, 0x11, 0xd8, 0x3c,
- 0xbe, 0x00, 0x19, 0xc5, 0xd2, 0xc3, 0xca, 0x34, 0x00, 0x28, 0xbf, 0xb9, 0x18, 0x20, 0x01, 0xcc,
- 0xda, 0x08, 0xbc, 0x75, 0x7c, 0xb0, 0x8d, 0xe0, 0x09, 0x18, 0xbf, 0x5d, 0xe9, 0x8c, 0x75, 0x64,
+ 0x65, 0x1b, 0xda, 0x11, 0x61, 0xe5, 0x77, 0x57, 0x92, 0xc8, 0x51, 0x1c, 0xd4, 0x91, 0x62, 0x63,
+ 0x00, 0x38, 0x57, 0xd5, 0x18, 0xd8, 0xdc, 0x40, 0x03, 0x86, 0xd3, 0x2f, 0x10, 0x11, 0xd8, 0x3c,
+ 0xbe, 0x00, 0x19, 0xc5, 0xd2, 0xc3, 0xca, 0x34, 0x00, 0x28, 0xbf, 0xb9, 0x18, 0x20, 0x01, 0xcc,
+ 0xda, 0x08, 0xbc, 0x75, 0x7c, 0xb0, 0x8d, 0xe0, 0x09, 0x18, 0xbf, 0x5d, 0xe9, 0x8c, 0x75, 0x64,
0xe5, 0xb5, 0x5d, 0xe0, 0xb7, 0x7d, 0xe9, 0x8c, 0x55, 0x65, 0xc5, 0xb5, 0x5d, 0xd8, 0x09, 0x0d,
- 0x64, 0xf0, 0xf0, 0x08, 0x63, 0x03, 0x00, 0x55, 0x35, 0xc0, 0x00, 0x20, 0x74, 0xa5, 0x1e, 0xe3,
- 0x00, 0x06, 0x3c, 0x52, 0xd1, 0x70, 0xd0, 0x57, 0x02, 0xf0, 0x00, 0xb6, 0xfc, 0x02, 0x11, 0x9a,
- 0x3b, 0xc8, 0x38, 0xdf, 0x1a, 0xb0, 0xd1, 0xb8, 0xd0, 0x18, 0x8a, 0x4a, 0xea, 0x1b, 0x12, 0x5d,
- 0x29, 0x58, 0xd8, 0x43, 0xb8, 0x2d, 0xd2, 0x61, 0x10, 0x3c, 0x0c, 0x5d, 0x1b, 0x61, 0x10, 0x3c,
+ 0x64, 0xf0, 0xf0, 0x08, 0x63, 0x03, 0x00, 0x55, 0x35, 0xc0, 0x00, 0x20, 0x74, 0xa5, 0x1e, 0xe3,
+ 0x00, 0x06, 0x3c, 0x52, 0xd1, 0x70, 0xd0, 0x57, 0x02, 0xf0, 0x00, 0xb6, 0xfc, 0x02, 0x11, 0x9a,
+ 0x3b, 0xc8, 0x38, 0xdf, 0x1a, 0xb0, 0xd1, 0xb8, 0xd0, 0x18, 0x8a, 0x4a, 0xea, 0x1b, 0x12, 0x5d,
+ 0x29, 0x58, 0xd8, 0x43, 0xb8, 0x2d, 0xd2, 0x61, 0x10, 0x3c, 0x0c, 0x5d, 0x1b, 0x61, 0x10, 0x3c,
0x0a, 0x5d, 0x1d, 0x61, 0x10, 0x3c, 0x0b, 0x19, 0x88, 0x21, 0xc0, 0x21, 0x07, 0x00, 0x65, 0x62,
- 0x08, 0xe9, 0x36, 0x40, 0x20, 0x41, 0x06, 0x00, 0x20, 0x00, 0x00, 0xed, 0xa3, 0x00, 0x88, 0x06,
- 0x98, 0x01, 0x5d, 0x7f, 0x02, 0x1d, 0x78, 0x03, 0x60, 0xcb, 0x3a, 0x01, 0xbd, 0x78, 0x02, 0x5d,
- 0x7e, 0x03, 0x1d, 0xf5, 0xa6, 0x40, 0x81, 0xb4, 0xd0, 0x8d, 0xd3, 0xd0, 0x6d, 0xd5, 0x61, 0x48,
- 0x61, 0x4d, 0xd1, 0xc8, 0xb1, 0xd8, 0x69, 0xff, 0x61, 0xd9, 0xed, 0xa0, 0xfe, 0x19, 0x91, 0x37,
+ 0x08, 0xe9, 0x36, 0x40, 0x20, 0x41, 0x06, 0x00, 0x20, 0x00, 0x00, 0xed, 0xa3, 0x00, 0x88, 0x06,
+ 0x98, 0x01, 0x5d, 0x7f, 0x02, 0x1d, 0x78, 0x03, 0x60, 0xcb, 0x3a, 0x01, 0xbd, 0x78, 0x02, 0x5d,
+ 0x7e, 0x03, 0x1d, 0xf5, 0xa6, 0x40, 0x81, 0xb4, 0xd0, 0x8d, 0xd3, 0xd0, 0x6d, 0xd5, 0x61, 0x48,
+ 0x61, 0x4d, 0xd1, 0xc8, 0xb1, 0xd8, 0x69, 0xff, 0x61, 0xd9, 0xed, 0xa0, 0xfe, 0x19, 0x91, 0x37,
0x19, 0x37, 0x00, 0xf1, 0x00, 0x01, 0x1f, 0x00, 0xad, 0xc1, 0x01, 0x01, 0x2e, 0x00, 0x40, 0xc6,
0x7a, 0x9b, 0x95, 0x43, 0xfc, 0x18, 0xd2, 0x9e, 0x2a, 0x5a, 0x4b, 0x2a, 0xb6, 0x87, 0x30, 0x6c
};
@@ -394,20 +394,20 @@ void Player_AppleII::startSound(int nr) {
case 0: // empty (nothing to play)
resetState();
return;
- case 1:
- _soundFunc = new AppleII_SoundFunction1_FreqUpDown();
+ case 1:
+ _soundFunc = new AppleII_SoundFunction1_FreqUpDown();
break;
- case 2:
- _soundFunc = new AppleII_SoundFunction2_SymmetricWave();
+ case 2:
+ _soundFunc = new AppleII_SoundFunction2_SymmetricWave();
break;
- case 3:
- _soundFunc = new AppleII_SoundFunction3_AsymmetricWave();
+ case 3:
+ _soundFunc = new AppleII_SoundFunction3_AsymmetricWave();
break;
- case 4:
- _soundFunc = new AppleII_SoundFunction4_Polyphone();
+ case 4:
+ _soundFunc = new AppleII_SoundFunction4_Polyphone();
break;
- case 5:
- _soundFunc = new AppleII_SoundFunction5_Noise();
+ case 5:
+ _soundFunc = new AppleII_SoundFunction5_Noise();
break;
}
_soundFunc->init(this, _params);
@@ -484,7 +484,7 @@ int Player_AppleII::readBuffer(int16 *buffer, const int numSamples) {
// toggle speaker on/off
void Player_AppleII::speakerToggle() {
- _speakerState ^= 0x1;
+ _speakerState ^= 0x1;
}
void Player_AppleII::generateSamples(int cycles) {
@@ -492,8 +492,8 @@ void Player_AppleII::generateSamples(int cycles) {
}
void Player_AppleII::wait(int interval, int count /*y*/) {
- assert(count > 0); // 0 == 256?
- assert(interval > 0); // 0 == 256?
+ assert(count > 0); // 0 == 256?
+ assert(interval > 0); // 0 == 256?
generateSamples(11 + count*(8 + 5 * interval));
}
diff --git a/engines/scumm/player_apple2.h b/engines/scumm/player_apple2.h
index b4a7d409fb..e1ec9d8946 100644
--- a/engines/scumm/player_apple2.h
+++ b/engines/scumm/player_apple2.h
@@ -36,7 +36,7 @@ namespace Scumm {
class ScummEngine;
/*
- * Optimized for use with periodical read/write phases when the buffer
+ * Optimized for use with periodical read/write phases when the buffer
* is filled in a write phase and completely read in a read phase.
* The growing strategy is optimized for repeated small (e.g. 2 bytes)
* single writes resulting in large buffers
@@ -133,7 +133,7 @@ static const double APPLEII_CPU_CLOCK = 1020484.5; // ~ 1.02 MHz
/*
* Converts the 1-bit speaker state values into audio samples.
- * This is done by aggregation of the speaker states at each
+ * This is done by aggregation of the speaker states at each
* CPU cycle in a sampling period into an audio sample.
*/
class SampleConverter {
@@ -144,7 +144,7 @@ private:
}
public:
- SampleConverter() :
+ SampleConverter() :
_cyclesPerSampleFP(0),
_missingCyclesFP(0),
_sampleCyclesSumFP(0),
@@ -156,7 +156,7 @@ public:
void reset() {
_missingCyclesFP = 0;
_sampleCyclesSumFP = 0;
- _buffer.clear();
+ _buffer.clear();
}
uint32 availableSize() const {
@@ -245,7 +245,7 @@ public:
virtual void setMusicVolume(int vol) { _sampleConverter.setMusicVolume(vol); }
void setSampleRate(int rate) {
_sampleRate = rate;
- _sampleConverter.setSampleRate(rate);
+ _sampleConverter.setSampleRate(rate);
}
virtual void startSound(int sound);
virtual void stopSound(int sound);
diff --git a/engines/scumm/player_towns.cpp b/engines/scumm/player_towns.cpp
index 2588026e59..33e3e40e39 100644
--- a/engines/scumm/player_towns.cpp
+++ b/engines/scumm/player_towns.cpp
@@ -87,7 +87,7 @@ void Player_Towns::restoreAfterLoad() {
if (!_v2)
restoredSounds.push_back(_pcmCurrentSound[i].index);
-
+
uint8 *ptr = _vm->getResourceAddress(rtSound, _pcmCurrentSound[i].index);
if (!ptr)
continue;
diff --git a/engines/scumm/player_v2cms.cpp b/engines/scumm/player_v2cms.cpp
index d4b21774ed..c1242e0645 100644
--- a/engines/scumm/player_v2cms.cpp
+++ b/engines/scumm/player_v2cms.cpp
@@ -718,38 +718,38 @@ void Player_V2CMS::playMusicChips(const MusicChip *table) {
}
const Player_V2CMS::MidiNote Player_V2CMS::_midiNotes[132] = {
- { 3, 0 }, { 31, 0 }, { 58, 0 }, { 83, 0 },
- { 107, 0 }, { 130, 0 }, { 151, 0 }, { 172, 0 },
- { 191, 0 }, { 209, 0 }, { 226, 0 }, { 242, 0 },
- { 3, 1 }, { 31, 1 }, { 58, 1 }, { 83, 1 },
- { 107, 1 }, { 130, 1 }, { 151, 1 }, { 172, 1 },
- { 191, 1 }, { 209, 1 }, { 226, 1 }, { 242, 1 },
- { 3, 2 }, { 31, 2 }, { 58, 2 }, { 83, 2 },
- { 107, 2 }, { 130, 2 }, { 151, 2 }, { 172, 2 },
- { 191, 2 }, { 209, 2 }, { 226, 2 }, { 242, 2 },
- { 3, 3 }, { 31, 3 }, { 58, 3 }, { 83, 3 },
- { 107, 3 }, { 130, 3 }, { 151, 3 }, { 172, 3 },
- { 191, 3 }, { 209, 3 }, { 226, 3 }, { 242, 3 },
- { 3, 4 }, { 31, 4 }, { 58, 4 }, { 83, 4 },
- { 107, 4 }, { 130, 4 }, { 151, 4 }, { 172, 4 },
- { 191, 4 }, { 209, 4 }, { 226, 4 }, { 242, 4 },
- { 3, 5 }, { 31, 5 }, { 58, 5 }, { 83, 5 },
- { 107, 5 }, { 130, 5 }, { 151, 5 }, { 172, 5 },
- { 191, 5 }, { 209, 5 }, { 226, 5 }, { 242, 5 },
- { 3, 6 }, { 31, 6 }, { 58, 6 }, { 83, 6 },
- { 107, 6 }, { 130, 6 }, { 151, 6 }, { 172, 6 },
- { 191, 6 }, { 209, 6 }, { 226, 6 }, { 242, 6 },
- { 3, 7 }, { 31, 7 }, { 58, 7 }, { 83, 7 },
- { 107, 7 }, { 130, 7 }, { 151, 7 }, { 172, 7 },
- { 191, 7 }, { 209, 7 }, { 226, 7 }, { 242, 7 },
- { 3, 8 }, { 31, 8 }, { 58, 8 }, { 83, 8 },
- { 107, 8 }, { 130, 8 }, { 151, 8 }, { 172, 8 },
- { 191, 8 }, { 209, 8 }, { 226, 8 }, { 242, 8 },
- { 3, 9 }, { 31, 9 }, { 58, 9 }, { 83, 9 },
- { 107, 9 }, { 130, 9 }, { 151, 9 }, { 172, 9 },
- { 191, 9 }, { 209, 9 }, { 226, 9 }, { 242, 9 },
- { 3, 10 }, { 31, 10 }, { 58, 10 }, { 83, 10 },
- { 107, 10 }, { 130, 10 }, { 151, 10 }, { 172, 10 },
+ { 3, 0 }, { 31, 0 }, { 58, 0 }, { 83, 0 },
+ { 107, 0 }, { 130, 0 }, { 151, 0 }, { 172, 0 },
+ { 191, 0 }, { 209, 0 }, { 226, 0 }, { 242, 0 },
+ { 3, 1 }, { 31, 1 }, { 58, 1 }, { 83, 1 },
+ { 107, 1 }, { 130, 1 }, { 151, 1 }, { 172, 1 },
+ { 191, 1 }, { 209, 1 }, { 226, 1 }, { 242, 1 },
+ { 3, 2 }, { 31, 2 }, { 58, 2 }, { 83, 2 },
+ { 107, 2 }, { 130, 2 }, { 151, 2 }, { 172, 2 },
+ { 191, 2 }, { 209, 2 }, { 226, 2 }, { 242, 2 },
+ { 3, 3 }, { 31, 3 }, { 58, 3 }, { 83, 3 },
+ { 107, 3 }, { 130, 3 }, { 151, 3 }, { 172, 3 },
+ { 191, 3 }, { 209, 3 }, { 226, 3 }, { 242, 3 },
+ { 3, 4 }, { 31, 4 }, { 58, 4 }, { 83, 4 },
+ { 107, 4 }, { 130, 4 }, { 151, 4 }, { 172, 4 },
+ { 191, 4 }, { 209, 4 }, { 226, 4 }, { 242, 4 },
+ { 3, 5 }, { 31, 5 }, { 58, 5 }, { 83, 5 },
+ { 107, 5 }, { 130, 5 }, { 151, 5 }, { 172, 5 },
+ { 191, 5 }, { 209, 5 }, { 226, 5 }, { 242, 5 },
+ { 3, 6 }, { 31, 6 }, { 58, 6 }, { 83, 6 },
+ { 107, 6 }, { 130, 6 }, { 151, 6 }, { 172, 6 },
+ { 191, 6 }, { 209, 6 }, { 226, 6 }, { 242, 6 },
+ { 3, 7 }, { 31, 7 }, { 58, 7 }, { 83, 7 },
+ { 107, 7 }, { 130, 7 }, { 151, 7 }, { 172, 7 },
+ { 191, 7 }, { 209, 7 }, { 226, 7 }, { 242, 7 },
+ { 3, 8 }, { 31, 8 }, { 58, 8 }, { 83, 8 },
+ { 107, 8 }, { 130, 8 }, { 151, 8 }, { 172, 8 },
+ { 191, 8 }, { 209, 8 }, { 226, 8 }, { 242, 8 },
+ { 3, 9 }, { 31, 9 }, { 58, 9 }, { 83, 9 },
+ { 107, 9 }, { 130, 9 }, { 151, 9 }, { 172, 9 },
+ { 191, 9 }, { 209, 9 }, { 226, 9 }, { 242, 9 },
+ { 3, 10 }, { 31, 10 }, { 58, 10 }, { 83, 10 },
+ { 107, 10 }, { 130, 10 }, { 151, 10 }, { 172, 10 },
{ 191, 10 }, { 209, 10 }, { 226, 10 }, { 242, 10 }
};
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index beac077fd1..72896e097a 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -1298,7 +1298,7 @@ void ScummEngine::saveOrLoad(Serializer *s) {
s->saveLoadArrayOf(_16BitPalette, 512, sizeof(_16BitPalette[0]), sleUint16);
}
-
+
// FM-Towns specific (extra palette data, color cycle data, etc.)
// In earlier save game versions (below 87) the FM-Towns specific data would get saved (and loaded) even in non FM-Towns games.
// This would cause an unnecessary save file incompatibility between DS (which uses the DISABLE_TOWNS_DUAL_LAYER_MODE setting)
diff --git a/engines/scumm/saveload.h b/engines/scumm/saveload.h
index d5f7ea526e..a640bc1e17 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 92
+#define CURRENT_VER 93
/**
* An auxillary macro, used to specify savegame versions. We use this instead
diff --git a/engines/scumm/script_v0.cpp b/engines/scumm/script_v0.cpp
index 44b77f1d18..361287d29f 100644
--- a/engines/scumm/script_v0.cpp
+++ b/engines/scumm/script_v0.cpp
@@ -602,7 +602,7 @@ void ScummEngine_v0::o_loadRoomWithEgo() {
x = r.x;
y = r.y;
a->putActor(x, y, _currentRoom);
-
+
camera._dest.x = camera._cur.x = a->getPos().x;
setCameraAt(a->getPos().x, a->getPos().y);
setCameraFollows(a);
@@ -635,18 +635,18 @@ void ScummEngine_v0::setMode(byte mode) {
case kModeCutscene:
_redrawSentenceLine = false;
// Note: do not change freeze state here
- state = USERSTATE_SET_IFACE |
+ state = USERSTATE_SET_IFACE |
USERSTATE_SET_CURSOR;
break;
case kModeKeypad:
_redrawSentenceLine = false;
- state = USERSTATE_SET_IFACE |
+ state = USERSTATE_SET_IFACE |
USERSTATE_SET_CURSOR | USERSTATE_CURSOR_ON |
USERSTATE_SET_FREEZE | USERSTATE_FREEZE_ON;
break;
case kModeNormal:
case kModeNoNewKid:
- state = USERSTATE_SET_IFACE | USERSTATE_IFACE_ALL |
+ state = USERSTATE_SET_IFACE | USERSTATE_IFACE_ALL |
USERSTATE_SET_CURSOR | USERSTATE_CURSOR_ON |
USERSTATE_SET_FREEZE;
break;
@@ -688,7 +688,7 @@ void ScummEngine_v0::o_animateActor() {
Actor_v0 *a = (Actor_v0*) derefActor(act, "o_animateActor");
a->_animFrameRepeat = repeat;
-
+
switch (anim) {
case 0xFE:
@@ -700,7 +700,7 @@ void ScummEngine_v0::o_animateActor() {
// 0x69A3
a->_speaking = 0x00;
return;
-
+
case 0xFF:
a->stopActorMoving();
return;
diff --git a/engines/scumm/script_v2.cpp b/engines/scumm/script_v2.cpp
index ce162b4a6a..96d422d5bb 100644
--- a/engines/scumm/script_v2.cpp
+++ b/engines/scumm/script_v2.cpp
@@ -993,7 +993,7 @@ void ScummEngine_v2::o2_drawSentence() {
const byte *temp;
int slot = getVerbSlot(VAR(VAR_SENTENCE_VERB), 0);
- if (!((_userState & USERSTATE_IFACE_SENTENCE) ||
+ if (!((_userState & USERSTATE_IFACE_SENTENCE) ||
(_game.platform == Common::kPlatformNES && (_userState & USERSTATE_IFACE_ALL))))
return;
@@ -1486,8 +1486,8 @@ void ScummEngine_v2::o2_cutscene() {
VAR(VAR_CURSORSTATE) = 200;
// Hide inventory, freeze scripts, hide cursor
- setUserState(USERSTATE_SET_IFACE |
- USERSTATE_SET_CURSOR |
+ setUserState(USERSTATE_SET_IFACE |
+ USERSTATE_SET_CURSOR |
USERSTATE_SET_FREEZE | USERSTATE_FREEZE_ON);
_sentenceNum = 0;
diff --git a/engines/scumm/script_v5.cpp b/engines/scumm/script_v5.cpp
index a5591b701f..0bf51a2816 100644
--- a/engines/scumm/script_v5.cpp
+++ b/engines/scumm/script_v5.cpp
@@ -1097,7 +1097,7 @@ void ScummEngine_v5::o5_getDist() {
int r;
getResultPos();
-
+
o1 = getVarOrDirectWord(PARAM_1);
o2 = getVarOrDirectWord(PARAM_2);
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index d0f46f3e56..2c79fb8de0 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -73,6 +73,7 @@
#include "scumm/util.h"
#include "scumm/verbs.h"
#include "scumm/imuse/pcspk.h"
+#include "scumm/imuse/mac_m68k.h"
#include "backends/audiocd/audiocd.h"
@@ -1835,17 +1836,31 @@ void ScummEngine::setupMusic(int midi) {
} else if (_game.version >= 3 && _game.heversion <= 62) {
MidiDriver *nativeMidiDriver = 0;
MidiDriver *adlibMidiDriver = 0;
-
- if (_sound->_musicType != MDT_ADLIB && _sound->_musicType != MDT_TOWNS && _sound->_musicType != MDT_PCSPK)
+ bool multi_midi = ConfMan.getBool("multi_midi") && _sound->_musicType != MDT_NONE && _sound->_musicType != MDT_PCSPK && (midi & MDT_ADLIB);
+ bool useOnlyNative = false;
+
+ if (isMacM68kIMuse()) {
+ // We setup this driver as native MIDI driver to avoid playback
+ // of the Mac music via a selected MIDI device.
+ nativeMidiDriver = new MacM68kDriver(_mixer);
+ // The Mac driver is never MT-32.
+ _native_mt32 = false;
+ // Ignore non-native drivers. This also ignores the multi MIDI setting.
+ useOnlyNative = true;
+ } else if (_sound->_musicType != MDT_ADLIB && _sound->_musicType != MDT_TOWNS && _sound->_musicType != MDT_PCSPK) {
nativeMidiDriver = MidiDriver::createMidi(dev);
+ }
+
if (nativeMidiDriver != NULL && _native_mt32)
nativeMidiDriver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
- bool multi_midi = ConfMan.getBool("multi_midi") && _sound->_musicType != MDT_NONE && _sound->_musicType != MDT_PCSPK && (midi & MDT_ADLIB);
- if (_sound->_musicType == MDT_ADLIB || _sound->_musicType == MDT_TOWNS || multi_midi) {
- adlibMidiDriver = MidiDriver::createMidi(MidiDriver::detectDevice(_sound->_musicType == MDT_TOWNS ? MDT_TOWNS : MDT_ADLIB));
- adlibMidiDriver->property(MidiDriver::PROP_OLD_ADLIB, (_game.features & GF_SMALL_HEADER) ? 1 : 0);
- } else if (_sound->_musicType == MDT_PCSPK) {
- adlibMidiDriver = new PcSpkDriver(_mixer);
+
+ if (!useOnlyNative) {
+ if (_sound->_musicType == MDT_ADLIB || _sound->_musicType == MDT_TOWNS || multi_midi) {
+ adlibMidiDriver = MidiDriver::createMidi(MidiDriver::detectDevice(_sound->_musicType == MDT_TOWNS ? MDT_TOWNS : MDT_ADLIB));
+ adlibMidiDriver->property(MidiDriver::PROP_OLD_ADLIB, (_game.features & GF_SMALL_HEADER) ? 1 : 0);
+ } else if (_sound->_musicType == MDT_PCSPK) {
+ adlibMidiDriver = new PcSpkDriver(_mixer);
+ }
}
_imuse = IMuse::create(_system, nativeMidiDriver, adlibMidiDriver);
@@ -1971,11 +1986,11 @@ Common::Error ScummEngine::go() {
if (delta < 1) // Ensure we don't get into an endless loop
delta = 1; // by not decreasing sleepers.
- // WORKAROUND: walking speed in the original v0/v1 interpreter
+ // WORKAROUND: walking speed in the original v0/v1 interpreter
// is sometimes slower (e.g. during scrolling) than in ScummVM.
// This is important for the door-closing action in the dungeon,
- // otherwise (delta < 6) a single kid is able to escape.
- if ((_game.version == 0 && isScriptRunning(132)) ||
+ // otherwise (delta < 6) a single kid is able to escape.
+ if ((_game.version == 0 && isScriptRunning(132)) ||
(_game.version == 1 && isScriptRunning(137)))
delta = 6;
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index c8cf096a19..a77c1c0141 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -150,7 +150,13 @@ enum GameFeatures {
GF_HE_985 = 1 << 14,
/** HE games with 16 bit color */
- GF_16BIT_COLOR = 1 << 15
+ GF_16BIT_COLOR = 1 << 15,
+
+ /**
+ * SCUMM v5-v7 Mac games stored in a container file
+ * Used to differentiate between m68k and PPC versions of Indy4
+ */
+ GF_MAC_CONTAINER = 1 << 16
};
/* SCUMM Debug Channels */
@@ -713,6 +719,9 @@ public:
bool openFile(BaseScummFile &file, const Common::String &filename, bool resourceFile = false);
+ /** Is this game a Mac m68k v5 game with iMuse? */
+ bool isMacM68kIMuse() const;
+
protected:
int _resourceHeaderSize;
byte _resourceMapper[128];
@@ -1363,7 +1372,7 @@ public:
public:
bool towns_isRectInStringBox(int x1, int y1, int x2, int y2);
byte _townsPaletteFlags;
- byte _townsCharsetColorMap[16];
+ byte _townsCharsetColorMap[16];
protected:
void towns_drawStripToScreen(VirtScreen *vs, int dstX, int dstY, int srcX, int srcY, int w, int h);
diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp
index 1dc026ad52..a1cecfa0b3 100644
--- a/engines/scumm/sound.cpp
+++ b/engines/scumm/sound.cpp
@@ -248,7 +248,10 @@ void Sound::playSound(int soundID) {
_mixer->playStream(Audio::Mixer::kSFXSoundType, NULL, stream, soundID);
}
// Support for sampled sound effects in Monkey Island 1 and 2
- else if (_vm->_game.platform != Common::kPlatformFMTowns && READ_BE_UINT32(ptr) == MKTAG('S','B','L',' ')) {
+ else if (_vm->_game.platform != Common::kPlatformFMTowns
+ // The Macintosh m68k versions of MI2/Indy4 just ignore SBL effects.
+ && !_vm->isMacM68kIMuse()
+ && READ_BE_UINT32(ptr) == MKTAG('S','B','L',' ')) {
debugC(DEBUG_SOUND, "Using SBL sound effect");
// SBL resources essentially contain VOC sound data.
@@ -954,7 +957,7 @@ void Sound::setupSfxFile() {
if (file.open(tmp))
_sfxFilename = tmp;
-
+
if (_vm->_game.heversion <= 74)
_sfxFileEncByte = 0x69;
@@ -1179,7 +1182,7 @@ int ScummEngine::readSoundResource(ResId idx) {
// its sound resources, and Amiga games, which feature only ROL
// resources, since we are a doing Midi -> AdLib conversion for
// these.
- if ((_sound->_musicType == MDT_ADLIB || _sound->_musicType == MDT_TOWNS) && pri != 16
+ if ((_sound->_musicType == MDT_ADLIB || _sound->_musicType == MDT_TOWNS) && pri != 16
&& pri != 15 && pri != 10 && pri != 2 && _game.platform != Common::kPlatformAmiga)
pri = -1;
diff --git a/engines/scumm/verbs.cpp b/engines/scumm/verbs.cpp
index 567ca31485..0d0f6cdb95 100644
--- a/engines/scumm/verbs.cpp
+++ b/engines/scumm/verbs.cpp
@@ -84,7 +84,7 @@ int ScummEngine_v0::verbPrepIdType(int verbid) {
switch (verbid) {
case kVerbUse: // depends on object1
return kVerbPrepObject;
- case kVerbGive:
+ case kVerbGive:
return kVerbPrepTo;
case kVerbUnlock: case kVerbFix:
return kVerbPrepWith;
@@ -693,7 +693,7 @@ void ScummEngine_v0::verbExec() {
if (_activeVerb == kVerbWhatIs)
return;
-
+
if (!(_activeVerb == kVerbWalkTo && _activeObject == 0)) {
doSentence(_activeVerb, _activeObject, _activeObject2);
if (_activeVerb != kVerbWalkTo) {
diff --git a/engines/sky/detection.cpp b/engines/sky/detection.cpp
index dfa3ded50b..8f6c2bb6a2 100644
--- a/engines/sky/detection.cpp
+++ b/engines/sky/detection.cpp
@@ -119,12 +119,12 @@ GameList SkyMetaEngine::getSupportedGames() const {
const ExtraGuiOptions SkyMetaEngine::getExtraGuiOptions(const Common::String &target) const {
Common::String guiOptions;
ExtraGuiOptions options;
-
+
if (target.empty()) {
options.push_back(skyExtraGuiOption);
return options;
}
-
+
if (ConfMan.hasKey("guioptions", target)) {
guiOptions = ConfMan.get("guioptions", target);
guiOptions = parseGameGUIOptions(guiOptions);
diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp
index f7add4eed2..ff3c897dba 100644
--- a/engines/sword1/animation.cpp
+++ b/engines/sword1/animation.cpp
@@ -69,7 +69,7 @@ static const char *const sequenceList[20] = {
};
// This is the list of the names of the PlayStation videos
-// TODO: fight.str, flashy.str,
+// TODO: fight.str, flashy.str,
static const char *const sequenceListPSX[20] = {
"e_ferr1",
"ladder1",
@@ -152,14 +152,14 @@ bool MoviePlayer::load(uint32 id) {
warning("%s:%d startFrame (%d) <= lastEnd (%d)", filename.c_str(), lineNo, startFrame, lastEnd);
continue;
}
-
+
int color = 0;
if (*ptr == '@') {
++ptr;
color = strtoul(ptr, const_cast<char **>(&ptr), 10);
while (*ptr && Common::isSpace(*ptr))
ptr++;
- }
+ }
_movieTexts.push_back(MovieText(startFrame, endFrame, ptr, color));
lastEnd = endFrame;
diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp
index 6e395116f9..7cd85dff54 100644
--- a/engines/sword1/control.cpp
+++ b/engines/sword1/control.cpp
@@ -541,7 +541,9 @@ void Control::setupMainPanel() {
if (SwordEngine::_systemVars.controlPanelMode == CP_DEATHSCREEN)
panelId = SR_DEATHPANEL;
else {
- if (SwordEngine::_systemVars.language <= BS1_SPANISH)
+ if (SwordEngine::_systemVars.realLanguage == Common::EN_USA)
+ panelId = SR_PANEL_AMERICAN;
+ else if (SwordEngine::_systemVars.language <= BS1_SPANISH)
panelId = SR_PANEL_ENGLISH + SwordEngine::_systemVars.language;
else
panelId = SR_PANEL_ENGLISH;
diff --git a/engines/sword1/objectman.cpp b/engines/sword1/objectman.cpp
index 5d1864d58d..3e70a95699 100644
--- a/engines/sword1/objectman.cpp
+++ b/engines/sword1/objectman.cpp
@@ -107,7 +107,7 @@ char *ObjectMan::lockText(uint32 textId) {
warning("Missing translation for textId %u (\"%s\")", textId, text);
unlockText(textId, BS1_ENGLISH);
}
-
+
return _missingSubTitleStr;
}
return text;
@@ -164,7 +164,7 @@ char *ObjectMan::lockText(uint32 textId, uint8 lang) {
// We use the hardcoded text in this case.
if (textId == 2950145)
return const_cast<char *>(_translationId2950145[lang]);
-
+
warning("ObjectMan::lockText(%d): text number has no text lines", textId);
return NULL;
}
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 75e8f72d9d..fa593b8df4 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -116,8 +116,9 @@ Common::Error SwordEngine::init() {
_systemVars.controlPanelMode = CP_NEWGAME;
_systemVars.forceRestart = false;
_systemVars.wantFade = true;
+ _systemVars.realLanguage = Common::parseLanguage(ConfMan.get("language"));
- switch (Common::parseLanguage(ConfMan.get("language"))) {
+ switch (_systemVars.realLanguage) {
case Common::DE_DEU:
_systemVars.language = BS1_GERMAN;
break;
@@ -138,6 +139,7 @@ Common::Error SwordEngine::init() {
break;
default:
_systemVars.language = BS1_ENGLISH;
+ break;
}
_systemVars.showText = ConfMan.getBool("subtitles");
diff --git a/engines/sword1/sword1.h b/engines/sword1/sword1.h
index ccdc2d3a59..ec6555b4b3 100644
--- a/engines/sword1/sword1.h
+++ b/engines/sword1/sword1.h
@@ -75,6 +75,7 @@ struct SystemVars {
uint8 language;
bool isDemo;
Common::Platform platform;
+ Common::Language realLanguage;
};
class SwordEngine : public Engine {
diff --git a/engines/sword2/sprite.cpp b/engines/sword2/sprite.cpp
index cb0923cc2f..91a5e2e86b 100644
--- a/engines/sword2/sprite.cpp
+++ b/engines/sword2/sprite.cpp
@@ -772,7 +772,7 @@ int32 Screen::drawSprite(SpriteInfo *s) {
src = sprite + rs.top * srcPitch + rs.left;
dst = _buffer + _screenWide * rd.top + rd.left;
- if (s->type & RDSPR_BLEND) {
+ if (s->type & RDSPR_BLEND) {
// The original code had two different blending cases. One for
// s->blend & 0x01 and one for s->blend & 0x02. However, the
// only values that actually appear in the cluster files are
@@ -783,7 +783,7 @@ int32 Screen::drawSprite(SpriteInfo *s) {
// The only correct way to simulate this would be using 16-bit mode.
// As this is not yet available for this engine, fake transparency is used
// as placeholder.
- if (!(_renderCaps & RDBLTFX_SPRITEBLEND) || Sword2Engine::isPsx()) {
+ if (!(_renderCaps & RDBLTFX_SPRITEBLEND) || Sword2Engine::isPsx()) {
for (i = 0; i < rs.height(); i++) {
for (j = 0; j < rs.width(); j++) {
if (src[j] && ((i & 1) == (j & 1)))
diff --git a/engines/sword25/sfx/soundengine.cpp b/engines/sword25/sfx/soundengine.cpp
index 69fae3dc4e..61d53c89a7 100644
--- a/engines/sword25/sfx/soundengine.cpp
+++ b/engines/sword25/sfx/soundengine.cpp
@@ -370,7 +370,7 @@ bool SoundEngine::unpersist(InputPersistenceBlock &reader) {
int loopStart;
int loopEnd;
uint layer;
-
+
reader.readString(fileName);
reader.read(sndType);
reader.read(volume);
diff --git a/engines/teenagent/actor.cpp b/engines/teenagent/actor.cpp
index cb8c798fb6..d65a367309 100644
--- a/engines/teenagent/actor.cpp
+++ b/engines/teenagent/actor.cpp
@@ -22,47 +22,46 @@
#include "teenagent/actor.h"
#include "teenagent/objects.h"
#include "teenagent/resources.h"
+#include "teenagent/teenagent.h"
#include "common/random.h"
#include "common/textconsole.h"
namespace TeenAgent {
-Actor::Actor() : head_index(0), idle_type(0) {}
+Actor::Actor(TeenAgentEngine *vm) : _vm(vm), headIndex(0), idleType(0) {}
-//idle animation lists at dseg: 0x6540
-Common::Rect Actor::renderIdle(Graphics::Surface *surface, const Common::Point &position, uint8 orientation, int delta_frame, uint zoom, Common::RandomSource &rnd) {
+Common::Rect Actor::renderIdle(Graphics::Surface *surface, const Common::Point &position, uint8 orientation, int deltaFrame, uint zoom, Common::RandomSource &rnd) {
if (index == 0) {
- idle_type = rnd.getRandomNumber(2);
- debug(0, "switched to idle animation %u", idle_type);
+ idleType = rnd.getRandomNumber(2);
+ debugC(kDebugActor, "switched to idle animation %u", idleType);
}
- Resources *res = Resources::instance();
- byte *frames_idle;
+ byte *framesIdle;
do {
- frames_idle = res->dseg.ptr(res->dseg.get_word(0x6540 + idle_type * 2)) + index;
- index += delta_frame;
- if (*frames_idle == 0) {
- idle_type = rnd.getRandomNumber(2);
- debug(0, "switched to idle animation %u[loop]", idle_type);
+ framesIdle = _vm->res->dseg.ptr(_vm->res->dseg.get_word(dsAddr_idleAnimationListPtr + idleType * 2)) + index;
+ index += deltaFrame;
+ if (*framesIdle == 0) {
+ idleType = rnd.getRandomNumber(2);
+ debugC(kDebugActor, "switched to idle animation %u[loop]", idleType);
index = 3; //put 4th frame (base 1) if idle animation loops
}
- } while (*frames_idle == 0);
+ } while (*framesIdle == 0);
bool mirror = orientation == kActorLeft;
- Surface *s = frames + *frames_idle - 1;
+ Surface *s = frames + *framesIdle - 1;
- ///\todo remove copy-paste here and below
+ //TODO: remove copy-paste here and below
int xp = position.x - s->w * zoom / 512 - s->x, yp = position.y - 62 * zoom / 256 - s->y; //hardcoded in original game
return s->render(surface, xp, yp, mirror, Common::Rect(), zoom);
}
-Common::Rect Actor::render(Graphics::Surface *surface, const Common::Point &position, uint8 orientation, int delta_frame, bool render_head, uint zoom) {
- const uint8 frames_left_right[] = {0, 1, 2, 3, 4, 5, /* step */ 6, 7, 8, 9};
- const uint8 frames_up[] = {18, 19, 20, 21, 22, 23, 24, 25, };
- const uint8 frames_down[] = {10, 11, 12, 13, 14, 15, 16, 17, };
+Common::Rect Actor::render(Graphics::Surface *surface, const Common::Point &position, uint8 orientation, int deltaFrame, bool renderHead, uint zoom) {
+ const uint8 framesLeftRight[] = {0, 1, 2, 3, 4, 5, /* step */ 6, 7, 8, 9};
+ const uint8 framesUp[] = {18, 19, 20, 21, 22, 23, 24, 25, };
+ const uint8 framesDown[] = {10, 11, 12, 13, 14, 15, 16, 17, };
- const uint8 frames_head_left_right[] = {
+ const uint8 framesHeadLeftRight[] = {
0x27, 0x1a, 0x1b,
0x27, 0x1c, 0x1d,
0x27, 0x1a,
@@ -73,14 +72,14 @@ Common::Rect Actor::render(Graphics::Surface *surface, const Common::Point &posi
0x27, 0x1a,
};
- const uint8 frames_head_up[] = {
+ const uint8 framesHeadUp[] = {
0x29, 0x25, 0x29, 0x29,
0x26, 0x29, 0x26, 0x29,
0x29, 0x25, 0x29, 0x25,
0x29, 0x29, 0x29, 0x25,
0x25, 0x29, 0x29, 0x26
};
- const uint8 frames_head_down[] = {
+ const uint8 framesHeadDown[] = {
0x20, 0x21, 0x22, 0x23,
0x28, 0x24, 0x28, 0x28,
0x24, 0x28, 0x20, 0x21,
@@ -91,45 +90,45 @@ Common::Rect Actor::render(Graphics::Surface *surface, const Common::Point &posi
Surface *s = NULL, *head = NULL;
bool mirror = orientation == kActorLeft;
- index += delta_frame;
+ index += deltaFrame;
switch (orientation) {
case kActorLeft:
case kActorRight:
- if (render_head) {
- if (head_index >= ARRAYSIZE(frames_head_left_right))
- head_index = 0;
- head = frames + frames_head_left_right[head_index];
- ++head_index;
+ if (renderHead) {
+ if (headIndex >= ARRAYSIZE(framesHeadLeftRight))
+ headIndex = 0;
+ head = frames + framesHeadLeftRight[headIndex];
+ ++headIndex;
}
- if (index >= ARRAYSIZE(frames_left_right))
+ if (index >= ARRAYSIZE(framesLeftRight))
index = 1;
- s = frames + frames_left_right[index];
+ s = frames + framesLeftRight[index];
break;
case kActorUp:
- if (render_head) {
- if (head_index >= ARRAYSIZE(frames_head_up))
- head_index = 0;
- head = frames + frames_head_up[head_index];
- ++head_index;
+ if (renderHead) {
+ if (headIndex >= ARRAYSIZE(framesHeadUp))
+ headIndex = 0;
+ head = frames + framesHeadUp[headIndex];
+ ++headIndex;
}
- if (index >= ARRAYSIZE(frames_up))
+ if (index >= ARRAYSIZE(framesUp))
index = 1;
- s = frames + frames_up[index];
+ s = frames + framesUp[index];
break;
case kActorDown:
- if (render_head) {
- if (head_index >= ARRAYSIZE(frames_head_down))
- head_index = 0;
- head = frames + frames_head_down[head_index];
- ++head_index;
+ if (renderHead) {
+ if (headIndex >= ARRAYSIZE(framesHeadDown))
+ headIndex = 0;
+ head = frames + framesHeadDown[headIndex];
+ ++headIndex;
}
- if (index >= ARRAYSIZE(frames_down))
+ if (index >= ARRAYSIZE(framesDown))
index = 1;
- s = frames + frames_down[index];
+ s = frames + framesDown[index];
break;
default:
return Common::Rect();
diff --git a/engines/teenagent/actor.h b/engines/teenagent/actor.h
index 9a7d395547..942397c636 100644
--- a/engines/teenagent/actor.h
+++ b/engines/teenagent/actor.h
@@ -28,13 +28,20 @@ class RandomSource;
namespace TeenAgent {
+class TeenAgentEngine;
+
class Actor : public Animation {
- uint head_index;
- uint idle_type;
+private:
+ TeenAgentEngine *_vm;
+
+ uint headIndex;
+ uint idleType;
+
public:
- Actor();
- Common::Rect render(Graphics::Surface *surface, const Common::Point &position, uint8 orientation, int delta_frame, bool head, uint zoom);
- Common::Rect renderIdle(Graphics::Surface *surface, const Common::Point &position, uint8 orientation, int delta_frame, uint zoom, Common::RandomSource &rnd);
+ Actor(TeenAgentEngine *vm);
+
+ Common::Rect render(Graphics::Surface *surface, const Common::Point &position, uint8 orientation, int deltaFrame, bool renderHead, uint zoom);
+ Common::Rect renderIdle(Graphics::Surface *surface, const Common::Point &position, uint8 orientation, int deltaFrame, uint zoom, Common::RandomSource &rnd);
};
} // End of namespace TeenAgent
diff --git a/engines/teenagent/animation.cpp b/engines/teenagent/animation.cpp
index 56107b67ca..effafcaac6 100644
--- a/engines/teenagent/animation.cpp
+++ b/engines/teenagent/animation.cpp
@@ -19,24 +19,30 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include "teenagent/teenagent.h"
#include "teenagent/animation.h"
+
#include "common/endian.h"
#include "common/textconsole.h"
namespace TeenAgent {
-Animation::Animation() : id(0), x(0), y(0), loop(true), paused(false), ignore(false), data(0), data_size(0), frames_count(0), frames(0), index(0) {
+Animation::Animation() : id(0), x(0), y(0), loop(true), paused(false), ignore(false), data(0), dataSize(0), framesCount(0), frames(0), index(0) {
+}
+
+Animation::~Animation() {
+ free();
}
Surface *Animation::firstFrame() {
- if (frames == NULL || frames_count == 0)
+ if (frames == NULL || framesCount == 0)
return NULL;
Surface *r = frames;
uint16 pos = READ_LE_UINT16(data + 1);
if (pos != 0) {
- r->x = pos % 320;
- r->y = pos / 320;
+ r->x = pos % kScreenWidth;
+ r->y = pos / kScreenWidth;
}
return r;
}
@@ -45,38 +51,38 @@ Surface *Animation::currentFrame(int dt) {
if (paused)
return firstFrame();
- if (frames == NULL || frames_count == 0)
+ if (frames == NULL || framesCount == 0)
return NULL;
Surface *r;
if (data != NULL) {
uint32 frame = 3 * index;
- //debug(0, "%u/%u", index, data_size / 3);
+ debugC(2, kDebugAnimation, "%u/%u", index, dataSize / 3);
index += dt;
- if (!loop && index >= data_size / 3) {
+ if (!loop && index >= dataSize / 3) {
return NULL;
}
- if (data[frame] - 1 >= frames_count) {
- warning("invalid frame %u(0x%x) (max %u) index %u, mod %u", frame, frame, frames_count, index - 1, data_size / 3);
+ if (data[frame] - 1 >= framesCount) {
+ warning("invalid frame %u(0x%x) (max %u) index %u, mod %u", frame, frame, framesCount, index - 1, dataSize / 3);
return NULL;
}
r = frames + data[frame] - 1;
uint16 pos = READ_LE_UINT16(data + frame + 1);
- index %= (data_size / 3);
+ index %= (dataSize / 3);
if (pos != 0) {
- x = r->x = pos % 320;
- y = r->y = pos / 320;
+ x = r->x = pos % kScreenWidth;
+ y = r->y = pos / kScreenWidth;
}
} else {
- //debug(0, "index %u", index);
+ debugC(2, kDebugAnimation, "index %u", index);
r = frames + index;
index += dt;
- index %= frames_count;
+ index %= framesCount;
}
return r;
@@ -97,9 +103,9 @@ void Animation::free() {
delete[] data;
data = NULL;
- data_size = 0;
+ dataSize = 0;
- frames_count = 0;
+ framesCount = 0;
delete[] frames;
frames = NULL;
@@ -107,44 +113,42 @@ void Animation::free() {
}
void Animation::load(Common::SeekableReadStream &s, Type type) {
- //fixme: do not reload the same animation each time
+ //FIXME: do not reload the same animation each time
free();
if (s.size() <= 1) {
- debug(1, "empty animation");
+ debugC(1, kDebugAnimation, "empty animation");
return;
}
- //uint16 pos = 0;
+ uint16 pos = 0;
int off = 0;
switch (type) {
case kTypeLan:
- data_size = s.readUint16LE();
+ dataSize = s.readUint16LE();
if (s.eos()) {
- debug(1, "empty animation");
+ debugC(1, kDebugAnimation, "empty animation");
return;
}
- data_size -= 2;
- data = new byte[data_size];
- data_size = s.read(data, data_size);
- /* for (int i = 0; i < data_size; ++i) {
- debug(0, "%02x ", data[i]);
- }
- debug(0, ", %u frames", data_size / 3);
- */
- frames_count = s.readByte();
- debug(1, "%u physical frames", frames_count);
- if (frames_count == 0)
+ dataSize -= 2;
+ data = new byte[dataSize];
+ dataSize = s.read(data, dataSize);
+ for (int i = 0; i < dataSize; ++i)
+ debugC(2, kDebugAnimation, "%02x ", data[i]);
+ debugC(2, kDebugAnimation, ", %u frames", dataSize / 3);
+ framesCount = s.readByte();
+ debugC(1, kDebugAnimation, "%u physical frames", framesCount);
+ if (framesCount == 0)
return;
- frames = new Surface[frames_count];
+ frames = new Surface[framesCount];
- s.skip(frames_count * 2 - 2); //sizes
- /*pos = */s.readUint16LE();
- //debug(0, "pos?: %04x", pos);
+ s.skip(framesCount * 2 - 2); //sizes
+ pos = s.readUint16LE();
+ debugC(3, kDebugAnimation, "pos?: 0x%04x", pos);
- for (uint16 i = 0; i < frames_count; ++i) {
+ for (uint16 i = 0; i < framesCount; ++i) {
frames[i].load(s, Surface::kTypeLan);
frames[i].x = 0;
frames[i].y = 0;
@@ -152,43 +156,43 @@ void Animation::load(Common::SeekableReadStream &s, Type type) {
break;
case kTypeInventory: {
- data_size = 3 * s.readByte();
- data = new byte[data_size];
+ dataSize = 3 * s.readByte();
+ data = new byte[dataSize];
- frames_count = 0;
- for (byte i = 0; i < data_size / 3; ++i) {
+ framesCount = 0;
+ for (byte i = 0; i < dataSize / 3; ++i) {
int idx = i * 3;
- /* byte unk = */
- s.readByte();
+ byte unk = s.readByte();
+ debugC(3, kDebugAnimation, "unk?: 0x%02x", unk);
data[idx] = s.readByte();
if (data[idx] == 0)
data[idx] = 1; //fixme: investigate
- if (data[idx] > frames_count)
- frames_count = data[idx];
+ if (data[idx] > framesCount)
+ framesCount = data[idx];
data[idx + 1] = 0;
data[idx + 2] = 0;
- //debug(0, "frame #%u", data[idx]);
+ debugC(2, kDebugAnimation, "frame #%u", data[idx]);
}
- frames = new Surface[frames_count];
+ frames = new Surface[framesCount];
- for (uint16 i = 0; i < frames_count; ++i) {
+ for (uint16 i = 0; i < framesCount; ++i) {
frames[i].load(s, Surface::kTypeOns);
}
}
break;
case kTypeVaria:
- frames_count = s.readByte();
- debug(1, "loading varia resource, %u physical frames", frames_count);
+ framesCount = s.readByte();
+ debugC(1, kDebugAnimation, "loading varia resource, %u physical frames", framesCount);
uint16 offset[255];
- for (byte i = 0; i < frames_count; ++i) {
+ for (byte i = 0; i < framesCount; ++i) {
offset[i] = s.readUint16LE();
- //debug(0, "%u: %04x", i, offset[i]);
+ debugC(0, kDebugAnimation, "%u: %04x", i, offset[i]);
}
- frames = new Surface[frames_count];
- for (uint16 i = 0; i < frames_count; ++i) {
- //debug(0, "%04x", offset[i]);
+ frames = new Surface[framesCount];
+ for (uint16 i = 0; i < framesCount; ++i) {
+ debugC(0, kDebugAnimation, "%04x", offset[i]);
s.seek(offset[i] + off);
frames[i].load(s, Surface::kTypeOns);
}
@@ -196,11 +200,7 @@ void Animation::load(Common::SeekableReadStream &s, Type type) {
break;
}
- debug(0, "%u frames", data_size / 3);
-}
-
-Animation::~Animation() {
- free();
+ debugC(2, kDebugAnimation, "%u frames", dataSize / 3);
}
} // End of namespace TeenAgent
diff --git a/engines/teenagent/animation.h b/engines/teenagent/animation.h
index 6942cc74eb..9be21a4c3d 100644
--- a/engines/teenagent/animation.h
+++ b/engines/teenagent/animation.h
@@ -35,6 +35,8 @@ public:
enum Type {kTypeLan, kTypeVaria, kTypeInventory};
Animation();
+ ~Animation();
+
void load(Common::SeekableReadStream &, Type type = kTypeLan);
void free();
@@ -43,8 +45,6 @@ public:
uint16 currentIndex() const { return index; }
void resetIndex() { index = 0; }
- ~Animation();
-
bool empty() const { return frames == NULL; }
void restart();
@@ -53,9 +53,9 @@ public:
protected:
byte *data;
- uint16 data_size;
+ uint16 dataSize;
- uint16 frames_count;
+ uint16 framesCount;
Surface *frames;
uint16 index;
};
diff --git a/engines/teenagent/callbacks.cpp b/engines/teenagent/callbacks.cpp
index 934727a478..2de81abb37 100644
--- a/engines/teenagent/callbacks.cpp
+++ b/engines/teenagent/callbacks.cpp
@@ -19,8 +19,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#include "teenagent/scene.h"
#include "teenagent/teenagent.h"
+#include "teenagent/scene.h"
+#include "teenagent/inventory.h"
#include "teenagent/resources.h"
#include "teenagent/dialog.h"
@@ -33,159 +34,536 @@ namespace TeenAgent {
#define GET_FLAG(addr) (res->dseg.get_byte(addr))
#define INC_FLAG(addr) (++*res->dseg.ptr(addr))
-void TeenAgentEngine::rejectMessage() {
- Resources *res = Resources::instance();
- //random reject message:
- uint i = _rnd.getRandomNumber(3);
- //debug(0, "reject message: %s", (const char *)res->dseg.ptr(res->dseg.get_word(0x339e + 2 * i)));
- displayMessage(res->dseg.get_word(0x339e + 2 * i));
+void TeenAgentEngine::fnIntro() {
+ hideActor();
+
+ loadScene(41, 139, 156, 3);
+ playSound(41, 12);
+ playAnimation(912, 1);
+ setOns(0, 108);
+ playSound(62, 8);
+ playSound(58, 40);
+ playAnimation(913, 1);
+ setOns(1, 109);
+ setLan(2, 1);
+ dialog->show(192, scene, 914, 915, textColorGoldDriver, textColorBankGuard, 2, 1);
+ displayCredits(dsAddr_introCredits1);
+
+ loadScene(42, 139, 156, 3);
+ playSound(15, 20);
+ playAnimation(916, 1);
+ playSound(40, 18);
+ playSound(40, 22);
+ for (byte i = 27; i < 37; i += 2)
+ playSound(40, i);
+ playSound(29, 44);
+ playAnimation(918, 0, true);
+ playAnimation(917, 1, true);
+ waitAnimation();
+ displayCredits(dsAddr_introCredits2);
+
+ loadScene(40, 139, 156, 3);
+ playMusic(3);
+ dialog->show(193, scene, 920, 924, textColorRGBBoss, textColorFortuneTeller, 1, 2);
+ playSound(26, 50);
+ playAnimation(925, 0, true);
+ playAnimation(926, 1, true);
+ waitAnimation();
+ dialog->show(194, scene, 927, 920, textColorFortuneTeller, textColorRGBBoss, 2, 1);
+ displayCredits(dsAddr_introCredits3);
+
+ loadScene(39, 139, 156, 3);
+ playMusic(11);
+ playSound(81, 2);
+ playSound(81, 8);
+ playSound(81, 11);
+ playSound(81, 14);
+ playSound(81, 16);
+ playSound(81, 18);
+ playSound(81, 20);
+ playSound(81, 21);
+ playAnimation(928, 1);
+ setOns(0, 112);
+ dialog->showMono(195, scene, 929, textColorMark, 1);
+ showActor();
+ moveTo(319, 150, 1, true);
+ moveTo(63, 150, 1);
+ displayAsyncMessage(dsAddr_HeyWtmQMsg, 4, 62, 18, 36); // hey, what's the matter?
+ playAnimation(851, 0, true);
+ playActorAnimation(930, true);
+ waitAnimation();
+ playSound(24, 11);
+ playActorAnimation(931);
+
+ displayCredits(dsAddr_introCredits4);
+
+ playMusic(3);
+ loadScene(40, 50, 186, 1);
+ setOns(0, 113);
+ dialog->show(196, scene, 919, 0, textColorRGBBoss, textColorMark, 1, 0);
+ moveTo(196, 186, 1);
+ dialog->show(197, scene, 0, 920, textColorMark, textColorRGBBoss, 0, 1);
+ playActorAnimation(932);
+ dialog->show(198, scene, 0, 920, textColorMark, textColorRGBBoss, 0, 1);
+ playActorAnimation(932);
+ dialog->show(199, scene, 0, 920, textColorMark, textColorRGBBoss, 0, 1);
+ playActorAnimation(932);
+ dialog->show(200, scene, 0, 922, textColorMark, textColorRGBBoss, 0, 1);
+ playActorAnimation(933);
+ dialog->show(201, scene, 0, 920, textColorMark, textColorRGBBoss, 0, 1);
+ moveTo(174, 186, 1);
+ playAnimation(851, 0, true);
+ playActorAnimation(934, true);
+ waitAnimation();
+ loadScene(10, 136, 153, 3);
}
+void TeenAgentEngine::fnPoleClimbFail() {
+ moveTo(86, 195, 1, true);
+ playActorAnimation(868);
+}
-bool TeenAgentEngine::processCallback(uint16 addr) {
- if (addr == 0)
- return false;
+void TeenAgentEngine::fnGotAnchor() {
+ SET_FLAG(dsAddr_timedCallbackState, 0);
+ setTimerCallback(0, 0);
+ scene->getActorAnimation()->free();
+ playSound(64, 7);
+ playActorAnimation(618);
+ disableObject(5);
+ setOns(0, 0);
+ playSound(31, 1);
+ playActorAnimation(619);
+ fnGetOutOfLake();
+ inventory->add(kInvItemAnchor);
+ displayMessage(dsAddr_hookedAnchorMsg); // "I was really hooked on this anchor!"
+}
- Resources *res = Resources::instance();
- debug(0, "processCallback(%04x)", addr);
- byte *code = res->cseg.ptr(addr);
-
- //try trivial callbacks first
- if (code[0] == 0xbb && code[3] == 0xe8 && code[6] == 0xc3) {
- //call display_message, r
- uint16 msg = READ_LE_UINT16(code + 1);
- uint16 func = 6 + addr + READ_LE_UINT16(code + 4);
- debug(0, "call %04x", func);
- //debug(0, "trivial callback, showing message %s", (const char *)res->dseg.ptr(addr));
- switch (func) {
- case 0xa055:
- displayMessage(msg);
- return true;
- }
+void TeenAgentEngine::fnGetOutOfLake() {
+ loadScene(15, 156, 180, 3);
+ playSound(5, 5);
+ playSound(38, 14);
+ playSound(38, 20);
+ playSound(5, 25);
+ playActorAnimation(616);
+}
+
+void TeenAgentEngine::fnGuardDrinking() {
+ SET_FLAG(dsAddr_timedCallbackState, 0);
+ setTimerCallback(0, 0);
+ scene->getAnimation(0)->free();
+ SET_FLAG(dsAddr_scaredGuardAlreadyFlag, 1);
+
+ displayAsyncMessage(dsAddr_BooMsg, 300, 130, 1, 5); // "Booo!"
+ setOns(0, 16);
+ enableObject(2);
+
+ playSound(17, 5);
+ playAnimation(545, 0);
+
+ dialog->show(5, scene, 0, 546, textColorMark, textColorMansionGuard, 0, 1);
+ SET_FLAG(dsAddr_spokenWithMansionGuardFlag, 1);
+ SET_FLAG(dsAddr_haveNotSpokenWithMansionGuardFlag, 0);
+}
+
+void TeenAgentEngine::fnEgoDefaultPosition() {
+ if (scene->getPosition().y <= 149)
+ moveTo(94, 115, 4);
+ else
+ moveTo(51, 149, 4);
+}
+
+void TeenAgentEngine::fnEnterCave() {
+ loadScene(24, 230, 170, 1);
+ playSound(52, 3);
+ playSound(52, 7);
+ playSound(52, 11);
+ playSound(52, 14);
+ playSound(52, 18);
+ playSound(52, 21);
+ playSound(52, 25);
+ playActorAnimation(601);
+ moveTo(230, 179, 3);
+ if (!CHECK_FLAG(dsAddr_lightOnFlag, 1))
+ displayMessage(dsAddr_kindaDarkMsg); // "It's kinda dark here"
+}
+
+void TeenAgentEngine::fnEgoScaredBySpider() {
+ if (CHECK_FLAG(dsAddr_egoAlreadyScaredBySpiderFlag, 1)) {
+ fnMoveToLadderAndLeaveCellar();
+ dialog->showMark(75, scene);
+ } else {
+ dialog->showMark(73, scene);
+ fnMoveToLadderAndLeaveCellar();
+ wait(100);
+ dialog->showMark(74, scene);
+ SET_FLAG(dsAddr_egoAlreadyScaredBySpiderFlag, 1);
}
+}
- if (code[0] == 0xe8 && code[3] == 0xc3) {
- uint func = 3 + addr + READ_LE_UINT16(code + 1);
- debug(0, "call %04x and return", func);
- if (func == 0xa4d6) {
- rejectMessage();
+void TeenAgentEngine::fnMoveToLadderAndLeaveCellar() {
+ Object *objTemp = scene->getObject(3);
+ moveTo(objTemp);
+ fnLeaveCellar();
+ moveTo(48, 190, 3);
+}
+
+void TeenAgentEngine::fnLeaveCellar() {
+ playSound(52, 10);
+ playSound(52, 14);
+ playSound(52, 18);
+ playSound(52, 21);
+ playSound(52, 25);
+ playSound(52, 28);
+ playSound(52, 32);
+ playActorAnimation(600);
+ loadScene(21, 297, 178, 3);
+}
+
+void TeenAgentEngine::fnPutRockInHole() {
+ if (CHECK_FLAG(dsAddr_timedCallbackState, 0)) {
+ playSound(5, 2);
+ playSound(15, 12);
+ playActorAnimation(638);
+ inventory->remove(kInvItemMouse);
+ setTimerCallback(csAddr_mouseOutOfHoleTimeout, 100);
+ SET_FLAG(dsAddr_timedCallbackState, 1);
+ } else if (CHECK_FLAG(dsAddr_timedCallbackState, 1)) {
+ playSound(5, 2);
+ playSound(52, 13);
+ playActorAnimation(648);
+ setOns(1, 46);
+ inventory->remove(kInvItemRock);
+ setTimerCallback(csAddr_mouseOutOfHoleTimeout, 100);
+ SET_FLAG(dsAddr_timedCallbackState, 2);
+ } else if (CHECK_FLAG(dsAddr_timedCallbackState, 2)) {
+ playActorAnimation(649);
+ setOns(1, 47);
+ wait(300);
+ for (byte i = 1; i <= 37; i += 4)
+ playSound(68, i);
+ playAnimation(639, 2);
+ setOns(0, 42);
+ enableObject(6);
+ disableObject(5);
+ SET_FLAG(dsAddr_mouseGotGoldNuggetFlag, 1);
+ SET_FLAG(dsAddr_timedCallbackState, 0);
+ setTimerCallback(0, 0);
+ }
+}
+
+void TeenAgentEngine::fnEgoBottomRightTurn() {
+ Common::Point p = scene->getPosition();
+ if (p.x == 208 && p.y == 151)
+ moveRel(0, 0, 2);
+ else
+ moveTo(208, 151, 1);
+}
+
+bool TeenAgentEngine::fnCheckingDrawers() {
+ uint16 v = GET_FLAG(dsAddr_drawerPuzzleBookValue) - 1;
+ if (GET_FLAG(dsAddr_blueDrawerOpenFlag + v) != 1)
+ return false;
+ else {
+ uint16 sum = 0;
+ for (uint i = 0; i < 6; ++i)
+ sum += GET_FLAG(dsAddr_blueDrawerOpenFlag + i);
+ if (sum != 1)
+ return false;
+ else
return true;
- }
}
+}
- if (code[0] == 0xc7 && code[1] == 0x06 && code[2] == 0xf3 && code[3] == 0xb4 &&
- code[6] == 0xb8 && code[9] == 0xbb && code[12] == 0xbf &&
- code[22] == 0xe8 && code[25] == 0xc3) {
- loadScene(code[4], Common::Point(
- (READ_LE_UINT16(code + 7) + READ_LE_UINT16(code + 13) + 1) / 2 ,
- READ_LE_UINT16(code + 10)));
- scene->setOrientation(code[21]);
+void TeenAgentEngine::fnDrawerOpenMessage() {
+ if (CHECK_FLAG(dsAddr_drawerPuzzleHintGivenFlag, 1))
+ displayMessage(dsAddr_drawerOpenMsg); // "I cannot open the drawer if the next one is open!"
+ else {
+ displayMessage(dsAddr_strangeDrawerMsg); // "Strange, but the drawer is stuck if the next drawer is open"
+ displayMessage(dsAddr_notOrdinaryDrawersMsg); // "Maybe these are not just ordinary drawers!"
+ SET_FLAG(dsAddr_drawerPuzzleHintGivenFlag, 1);
+ }
+}
+
+bool TeenAgentEngine::fnRobotSafeAlreadyUnlockedCheck() {
+ if (CHECK_FLAG(dsAddr_MansionRobotSafeUnlockedFlag, 1)) {
return true;
+ } else {
+ displayMessage(dsAddr_noReasonMsg); // "There's no reason to do it"
+ return false;
}
+}
- switch (addr) {
+void TeenAgentEngine::fnRobotSafeUnlockCheck() {
+ if (CHECK_FLAG(dsAddr_MansionRobotSafeVoiceTestPassedFlag, 1) &&
+ CHECK_FLAG(dsAddr_MansionRobotSafeScentTestPassedFlag, 1) &&
+ CHECK_FLAG(dsAddr_MansionRobotSafeViewTestPassedFlag, 1)) {
+ waitLanAnimationFrame(1, 1);
+ playSound(89, 2);
+ playActorAnimation(731);
+ setOns(0, 70);
+ setLan(1, 0);
+ disableObject(1);
+ enableObject(2);
+ enableObject(3);
+ }
+}
- case 0x024c: //intro
- hideActor();
+bool TeenAgentEngine::fnMansionIntrusionAttempt() {
+ wait(50);
+ byte attempts = res->dseg.get_byte(dsAddr_mansionEntryCount) + 1;
+ res->dseg.set_byte(dsAddr_mansionEntryCount, attempts);
+ debugC(0, kDebugCallbacks, "mansion intrusion attempt #%u", attempts);
+ if (attempts >= 7)
+ return false;
+ else {
+ byte id = scene->getId();
- loadScene(41, 139, 156, 3);
- playSound(41, 12);
- playAnimation(912, 1);
- setOns(0, 108);
- playSound(62, 8);
- playSound(58, 40);
- playAnimation(913, 1);
- setOns(1, 109);
- setLan(2, 1);
- Dialog::show(scene, 0x748e, 914, 915, 0xe7, 0xd7, 2, 1);
- displayCredits(0xe3c2);
-
- loadScene(42, 139, 156, 3);
- playSound(15, 20);
- playAnimation(916, 1);
- playSound(40, 18);
- playSound(40, 22);
- for (byte i = 27; i < 37; i += 2)
- playSound(40, i);
- playSound(29, 44);
- playAnimation(918, 0, true);
- playAnimation(917, 1, true);
- waitAnimation();
- displayCredits(0xe3e6);
+ playMusic(11);
+ displayCutsceneMessage(dsAddr_cutsceneMsg2, 84, 95); // "Meanwhile in the mansion"
+ switch (attempts) {
+ case 2:
+ fnSecondMansionIntrusion();
+ break;
+ case 3:
+ fnThirdMansionIntrusion();
+ break;
+ case 4:
+ fnFourthMansionIntrusion();
+ break;
+ case 5:
+ fnFifthMansionIntrusion();
+ break;
+ case 6:
+ fnSixthMansionIntrusion();
+ break;
+ default:
+ error("mansion intrusion attempts out of range!");
+ break;
+ }
+ playMusic(6);
+ if (getFlag(dsAddr_johnNotyOutsideMansionDoorFlag) != 1 || attempts != 6)
+ loadScene(id, scene->getPosition());
+ return true;
+ }
+}
- loadScene(40, 139, 156, 3);
- playMusic(3);
- Dialog::show(scene, 0x750d, 920, 924, 0xe7, 0xeb, 1, 2); //as i told you, our organization...
- playSound(26, 50);
- playAnimation(925, 0, true);
- playAnimation(926, 1, true);
- waitAnimation();
- Dialog::show(scene, 0x78a6, 927, 920, 0xeb, 0xe7, 2, 1);
- displayCredits(0xe3ff);
+void TeenAgentEngine::fnSecondMansionIntrusion() {
+ hideActor();
+ loadScene(34, scene->getPosition());
+ playAnimation(986, 0, true);
+ playAnimation(987, 1, true);
+ waitAnimation();
+ dialog->show(178, scene, 988, 989, textColorMansionGuard, textColorJohnNoty, 1, 2);
+ playAnimation(990, 0, true);
+ playAnimation(991, 1, true);
+ waitAnimation();
+ showActor();
+}
- loadScene(39, 139, 156, 3);
- playMusic(11);
- playSound(81, 2);
- playSound(81, 8);
- playSound(81, 11);
- playSound(81, 14);
- playSound(81, 16);
- playSound(81, 18);
- playSound(81, 20);
- playSound(81, 21);
- playAnimation(928, 1);
- setOns(0, 112);
- Dialog::showMono(scene, 0x78e1, 929, 0xd1, 1); //he's coming
- showActor();
- moveTo(319, 150, 1, true);
- moveTo(63, 150, 1);
- displayAsyncMessage(0x5da8, 19844, 18, 36); //hey, what's the matter?
- playAnimation(851, 0, true);
- playActorAnimation(930, true);
- waitAnimation();
- playSound(24, 11);
- playActorAnimation(931);
+void TeenAgentEngine::fnThirdMansionIntrusion() {
+ hideActor();
+ loadScene(30, scene->getPosition());
+ playAnimation(887, 1);
+ playAnimation(888, 2, true, true, true);
+ //waitAnimation();
+ dialog->showMono(179, scene, 889, textColorMansionGuard, 2);
+ playSound(26, 3);
+ playAnimation(891, 1, true, true, true);
+ playAnimation(892, 2);
+ waitAnimation();
+ dialog->show(180, scene, 890, 889, textColorJohnNoty, textColorMansionGuard, 3, 2);
+ showActor();
+}
- displayCredits(0xe42f);
+void TeenAgentEngine::fnFourthMansionIntrusion() {
+ hideActor();
+ loadScene(32, scene->getPosition());
+ playAnimation(894, 1, true, true, true);
+ playAnimation(893, 2, true);
+ waitAnimation();
+ dialog->showMono(181, scene, 895, textColorMansionGuard, 3);
+ playSound(75, 9);
+ playAnimation(898, 1, true);
+ playAnimation(897, 2, true);
+ dialog->show(182, scene, 896, 895, textColorJohnNoty, textColorMansionGuard, 2, 3);
+ showActor();
+}
- playMusic(3);
- loadScene(40, 50, 186, 1);
- setOns(0, 113);
- Dialog::show(scene, 0x78f1, 919, 0, 0xe7, 0xd1, 1, 0);
- moveTo(196, 186, 1);
- Dialog::show(scene, 0x7958, 0, 920, 0xd1, 0xe7, 0, 1);
- playActorAnimation(932);
- Dialog::show(scene, 0x7e07, 0, 920, 0xd1, 0xe7, 0, 1);
- playActorAnimation(932);
- Dialog::show(scene, 0x7e1a, 0, 920, 0xd1, 0xe7, 0, 1);
- playActorAnimation(932);
- Dialog::show(scene, 0x7e2c, 0, 922, 0xd1, 0xe7, 0, 1);
- playActorAnimation(933);
- Dialog::show(scene, 0x7e70, 0, 920, 0xd1, 0xe7, 0, 1);
- moveTo(174, 186, 1);
- playAnimation(851, 0, true);
- playActorAnimation(934, true);
- waitAnimation();
- loadScene(10, 136, 153, 3);
+void TeenAgentEngine::fnFifthMansionIntrusion() {
+ hideActor();
+ loadScene(29, scene->getPosition());
+ playActorAnimation(901, true);
+ playAnimation(900, 1, true);
+ waitAnimation();
+ dialog->show(183, scene, 903, 902, textColorJohnNoty, textColorMansionGuard, 2, 3);
+ for (byte i = 3; i <= 9; i += 2)
+ playSound(56, i);
+
+ playActorAnimation(905, true);
+ playAnimation(904, 1, true);
+ dialog->show(184, scene, 903, 902, textColorJohnNoty, textColorMansionGuard, 2, 3);
+ showActor();
+}
+
+void TeenAgentEngine::fnSixthMansionIntrusion() {
+ hideActor();
+ loadScene(35, scene->getPosition());
+ playAnimation(907, 2, true);
+ playAnimation(906, 3, true);
+ waitAnimation();
+ dialog->show(185, scene, 908, 909, textColorMansionGuard, textColorJohnNoty, 2, 3);
+ dialog->show(186, scene, 910, 908, textColorJohnNoty, textColorMansionGuard, 3, 2);
+ loadScene(11, scene->getPosition());
+ showActor();
+ setOns(3, 51);
+ playAnimation(911, 1);
+ playAnimation(899, 1);
+ setFlag(dsAddr_johnNotyOutsideMansionDoorFlag, 1);
+ reloadLan();
+ wait(200);
+ enableObject(8);
+ setLan(2, 8);
+}
+void TeenAgentEngine::fnTooDark() {
+ displayMessage(dsAddr_TooDarkMsg); // "It's too dark to see clearly"
+}
+
+bool TeenAgentEngine::fnIsCookGone() {
+ if (CHECK_FLAG(dsAddr_MansionCookGoneFlag, 1)) {
return true;
+ } else {
+ displayMessage(dsAddr_cookAroundMsg); // "I can't do anything with this cook around"
+ return false;
+ }
+}
+
+void TeenAgentEngine::fnEgoSuspiciousPosition() {
+ Common::Point p = scene->getPosition();
+ if (p.x != 203 && p.y != 171)
+ moveTo(203, 169, 2);
+ else
+ moveTo(203, 169, 1);
+}
+
+void TeenAgentEngine::fnGivingFlowerToOldLady() {
+ playSound(5, 2);
+ dialog->show(37, scene, 0, 523, textColorMark, textColorOldLady, 0, 1);
+ playActorAnimation(537, true);
+ playAnimation(538, 0, true);
+ waitAnimation();
+ wait(100);
+ dialog->show(38, scene, 0, 523, textColorMark, textColorOldLady, 0, 1);
+}
+
+void TeenAgentEngine::fnGiveAnotherFlowerToOldLady() {
+ dialog->pop(scene, dsAddr_dialogStackOldLady, 0, 523, textColorMark, textColorOldLady, 0, 1);
+}
+
+void TeenAgentEngine::fnGivingFlowerToAnne() {
+ dialog->show(53, scene, 0, 524, textColorMark, textColorAnne, 0, 2);
+ playSound(5, 10);
+ playActorAnimation(540, true);
+ playAnimation(539, 1, true);
+ waitAnimation();
+ wait(100);
+ dialog->show(54, scene, 0, 524, textColorMark, textColorAnne, 0, 2);
+ wait(50);
+ dialog->show(55, scene, 0, 524, textColorMark, textColorAnne, 0, 2);
+ dialog->show(56, scene, 0, 524, textColorMark, textColorAnne, 0, 2);
+ wait(50);
+ moveRel(0, 1, 0);
+ dialog->show(57, scene, 0, 524, textColorMark, textColorAnne, 0, 2);
+ moveRel(0, -1, 0);
+ wait(50);
+}
+
+void TeenAgentEngine::fnGiveAnotherFlowerToAnne() {
+ dialog->pop(scene, dsAddr_dialogStackAnotherFlowerToAnne, 0, 524, textColorMark, textColorAnne, 0, 2);
+}
+
+void TeenAgentEngine::rejectMessage() {
+ uint i = _rnd.getRandomNumber(3);
+ switch (i) {
+ case 0:
+ displayMessage(dsAddr_rejectMsg0); // "I have no idea what to do with it"
+ break;
+ case 1:
+ displayMessage(dsAddr_rejectMsg1); // "I can't imagine what I could do with this"
+ break;
+ case 2:
+ displayMessage(dsAddr_rejectMsg2); // "I can't figure out what I should do with this"
+ break;
+ case 3:
+ displayMessage(dsAddr_rejectMsg3); // "I can't find any reason to mess with it"
+ break;
+ default:
+ error("rejectMessage() index out of range");
+ break;
+ }
+}
+
+bool TeenAgentEngine::processCallback(uint16 addr) {
+ if (addr == 0)
+ return false;
+
+ debugC(0, kDebugCallbacks, "processCallback(%04x)", addr);
+
+ bool retVal = true;
+ switch (addr) {
+ case csAddr_intro: // intro
+ fnIntro();
+ break;
+
+ case 0x3fed:
+ loadScene(3, Common::Point(305, 104));
+ scene->setOrientation(4);
+ break;
+
+ case 0x4007:
+ loadScene(5, Common::Point(300, 131));
+ scene->setOrientation(3);
+ break;
case 0x4021:
- //pulling out mysterious object
- if (CHECK_FLAG(0xdbe1, 1)) {
+ // pulling out mysterious object
+ if (CHECK_FLAG(dsAddr_cutFenceFlag, 1)) {
playActorAnimation(844);
playActorAnimation(846);
playActorAnimation(845);
- displayMessage(0x5696);
+ displayMessage(dsAddr_pullObjMsg1); // "I can't pull it out"
} else {
- displayMessage(0x570f);
+ displayMessage(dsAddr_pullObjMsg2); // "I can't reach it"
}
- return true;
-
- case 0x4094: //climbing to the pole near mudpool
- if (CHECK_FLAG(0xDBE4, 1)) {
- displayMessage(0x57b2);
- return true;
+ break;
+
+ case 0x4048:
+ displayMessage(dsAddr_dontWantToTouchMsg); // "I don't want to touch it - I might get hurt"
+ break;
+
+ case 0x404f:
+ displayMessage(dsAddr_notWantToSleepMsg); // "I don't want to sleep"
+ break;
+
+ case 0x4056:
+ // 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;
+
+ case 0x4060:
+ loadScene(2, Common::Point(28, 180));
+ scene->setOrientation(2);
+ break;
+
+ case 0x407a:
+ loadScene(4, Common::Point(297, 128));
+ scene->setOrientation(4);
+ break;
+
+ case 0x4094: // climbing to the pole near mudpool
+ if (CHECK_FLAG(dsAddr_gotMugOfMudFlag, 1)) {
+ displayMessage(dsAddr_poleClimbDoneMsg); // "Never Again!"
} else {
for (byte i = 11; i <= 27; i += 4)
playSound(76, i);
@@ -196,39 +574,49 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playAnimation(865, 1);
playActorAnimation(866);
//InventoryObject *obj = inventory->selectedObject();
- //if (obj != NULL && obj->id == 0x55) {
+ //if (obj != NULL && obj->id == kInvItemMug) {
- //implement pause and using real object:
- if (inventory->has(0x55)) {
+ // FIXME: implement pause in mudpool and using of Mug object, as per original interpreter
+ if (inventory->has(kInvItemMug)) {
playSound(5, 4);
playSound(5, 19);
playSound(64, 11);
playActorAnimation(867);
- inventory->remove(0x55);
- inventory->add(0x56);
+ inventory->remove(kInvItemMug);
+ inventory->add(kInvItemMugOfMud);
moveTo(86, 195, 1, true);
playActorAnimation(868);
- SET_FLAG(0xDBE4, 1);
+ SET_FLAG(dsAddr_gotMugOfMudFlag, 1);
} else {
- processCallback(0x4173);
- Dialog::pop(scene, 0xDB72, 0, 0, 0xd1, 0xd1, 0, 0);
+ fnPoleClimbFail();
+ dialog->popMark(scene, dsAddr_dialogStackFallIntoMudpool);
}
- return true;
}
- case 0x4173:
- //fail!
- moveTo(86, 195, 1, true);
- playActorAnimation(868);
- return true;
+ break;
+
+ case csAddr_poleClimbFail:
+ fnPoleClimbFail();
+ break;
- case 0x419c: //getting the bird
+ case 0x4195:
+ displayMessage(dsAddr_preferWaterMsg); // "I prefer water"
+ break;
+
+ case 0x419c: // getting the bird
setOns(0, 0);
playSound(56, 10);
playActorAnimation(875);
disableObject(6);
- inventory->add(0x5c);
- return true;
+ inventory->add(kInvItemBird);
+ break;
+ case 0x41c3:
+ displayMessage(dsAddr_pullObjMsg2); // "I can't reach it"
+ break;
+
+ case 0x41ca:
+ rejectMessage();
+ break;
case 0x41ce:
moveTo(197, 159, 4);
@@ -236,9 +624,23 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playSound(71, 8);
playActorAnimation(833);
moveTo(225, 159, 4);
- inventory->add(0x4e);
+ inventory->add(kInvItemDelicatePlant);
disableObject(3);
- return true;
+ break;
+
+ case 0x422c:
+ displayMessage(dsAddr_tooWeakToClimbMsg); // "I'm too weak to climb it"
+ break;
+
+ case 0x4233:
+ loadScene(3, Common::Point(216, 199));
+ scene->setOrientation(1);
+ break;
+
+ case 0x424d:
+ loadScene(5, Common::Point(18, 174));
+ scene->setOrientation(2);
+ break;
case 0x4267:
hideActor();
@@ -252,92 +654,111 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playSound(5, 26);
playActorAnimation(842);
wait(100);
- //shown in different positions
- displayMessage(0x5656, 0xd1, 0x5510);
+ // shown in different positions
+ displayMessage(dsAddr_fnMsg2, textColorMark, 16, 68); // "And how am I supposed to get back?"
wait(50);
- displayMessage(0x567a, 0xd1, 0x555c);
+ displayMessage(dsAddr_fnMsg3, textColorMark, 92, 68); // "Great"
wait(50);
- displayMessage(0x5682, 0xd1, 0x553e);
+ displayMessage(dsAddr_fnMsg4, textColorMark, 62, 68); // "Oh, yeah, right"
wait(50);
playActorAnimation(843);
showActor();
moveTo(223, 149, 0, true);
disableObject(7);
disableObject(1);
- inventory->add(0x51);
- displayMessage(0x5646);
- return true;
+ inventory->add(kInvItemShovelAct1);
+ displayMessage(dsAddr_fnMsg1); // "Piece of cake"
+ break;
+
+ case 0x433a:
+ loadScene(10, Common::Point(294, 183));
+ scene->setOrientation(4);
+ break;
+
+ case 0x4354:
+ loadScene(4, Common::Point(300, 185));
+ scene->setOrientation(4);
+ break;
+
+ case 0x436e:
+ loadScene(2, Common::Point(219, 199));
+ scene->setOrientation(1);
+ break;
case 0x4388:
playSound(80, 4);
playActorAnimation(961);
loadScene(8, 155, 199, 1);
- return true;
+ break;
- case 0x43b5: //HQ, first trial - prison
+ case 0x43b5: // HQ, first trial - prison
playSound(70, 6);
playActorAnimation(962);
loadScene(7, 30, 184, 2);
- if (res->dseg.get_byte(0xDBDF) < 2) {
+ if (res->dseg.get_byte(dsAddr_FirstActTrialState) < 2) {
wait(150);
moveTo(134, 167, 2);
- displayMessage(0x54f7);
+ displayMessage(dsAddr_firstTrialMsg); // "Sir, I'm Mark. A rookie"
setLan(1, 0);
playAnimation(812, 0, true);
playActorAnimation(811);
- Dialog::show(scene, 0x6117, 0, 813, 0xd1, 0xec, 0, 1);
+ dialog->show(148, scene, 0, 813, textColorMark, textColorCaptain, 0, 1);
loadScene(6, 230, 184);
playMusic(5);
- Dialog::show(scene, 0x626a, 0, 814, 0xd1, 0xec, 0, 1);
+ dialog->show(149, scene, 0, 814, textColorMark, textColorCaptain, 0, 1);
playSound(4, 14);
playAnimation(815, 0);
setOns(1, 0);
- Dialog::showMono(scene, 0x62dc, 0, 0xd1, 0);
+ dialog->showMono(150, scene, 0, textColorMark, 0);
- SET_FLAG(0xDBDF, 1);
+ SET_FLAG(dsAddr_FirstActTrialState, 1);
}
- return true;
+ break;
case 0x4482:
- if (CHECK_FLAG(0xDBDF, 0)) {
+ if (CHECK_FLAG(dsAddr_FirstActTrialState, 0)) {
playActorAnimation(968);
- displayMessage(0x5511);
+ displayMessage(dsAddr_lockedMsg); // "It's Locked!"
} else {
playSound(80, 3);
playSound(79, 4);
playActorAnimation(968);
loadScene(6, 280, 186, 4);
}
- return true;
+ break;
- case 0x44fc: //pull out spring from bed
+ case 0x44fc: // pull out spring from bed
playSound(53, 25);
playSound(24, 27);
playSound(5, 36);
playActorAnimation(839);
moveTo(278, scene->getPosition().y, 0, true);
- inventory->add(0x50);
+ inventory->add(kInvItemSpring);
disableObject(1);
- return true;
+ break;
case 0x44cb:
- if (CHECK_FLAG(0xDBE5, 1)) {
- displayMessage(0x57c0);
+ if (CHECK_FLAG(dsAddr_gotRopeAct1Flag, 1)) {
+ displayMessage(dsAddr_vacMsg); // "What am I? A vacuum cleaner?!"
} else {
playSound(49, 14);
playSound(5, 21);
playActorAnimation(869);
- inventory->add(0x58);
- SET_FLAG(0xDBE5, 1);
+ inventory->add(kInvItemRopeAct1);
+ SET_FLAG(dsAddr_gotRopeAct1Flag, 1);
}
- return true;
+ break;
+
+ case 0x4532:
+ displayMessage(dsAddr_springPrickMsg); // "The springs would prick my back"
+ break;
- case 0x4539: //prison cell: use crates
- if (CHECK_FLAG(0xdbdd, 2)) {
- //finished the meal - trap
- displayMessage(0x55c0);
+ case 0x4539: // prison cell: use crates
+ if (CHECK_FLAG(dsAddr_JailCableAndBowlState, 2)) {
+ // finished the meal - trap
+ displayMessage(dsAddr_mealFinishedMsg); // "Hey! I finished my meal."
moveTo(306, 196, 2);
wait(50);
//playAnimation(825, 1); //very long empty animation. what for?
@@ -354,66 +775,65 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
loadScene(6, scene->getPosition());
setOns(3, 0x5b);
wait(50);
- displayMessage(0x55db);
- SET_FLAG(0xdbdd, 3);
+ displayMessage(dsAddr_bowlWeldedMsg); // "Wow. He got welded to the bowl"
+ SET_FLAG(dsAddr_JailCableAndBowlState, 3);
scene->getObject(4)->setName("body");
} else {
- if (Dialog::pop(scene, 0xdb5c, 0, 0, 0xd1, 0xd1, 0, 0) != 0x636b) //not 'im getting hungry'
- return true;
-
- wait(100);
- playSound(52, 8);
- playSound(52, 13);
- playAnimation(820, 1);
- setOns(3, 0x59);
- wait(50);
- moveTo(scene->getPosition().x, scene->getPosition().y + 1, 3);
- wait(150);
- moveTo(scene->getPosition().x, scene->getPosition().y - 1, 2);
- wait(100);
- displayMessage(0x551f);
- enableObject(4);
- SET_FLAG(0xdbdc, 1);
+ if (dialog->pop(scene, dsAddr_dialogStackJailDoorGrates, 0, 0, textColorMark, textColorMark, 0, 0) == 0x636b) { // 'im getting hungry'
+ wait(100);
+ playSound(52, 8);
+ playSound(52, 13);
+ playAnimation(820, 1);
+ setOns(3, 0x59);
+ wait(50);
+ moveTo(scene->getPosition().x, scene->getPosition().y + 1, 3);
+ wait(150);
+ moveTo(scene->getPosition().x, scene->getPosition().y - 1, 2);
+ wait(100);
+ displayMessage(dsAddr_ThanksMsg); // "Thanks."
+ enableObject(4);
+ SET_FLAG(dsAddr_GotFoodBowlInJailFlag, 1);
+ }
}
- return true;
+ break;
case 0x4662:
- if (CHECK_FLAG(0xDBDD, 3)) {
- if (CHECK_FLAG(0xDBDE, 1)) {
- displayMessage(0x5608);
+ if (CHECK_FLAG(dsAddr_JailCableAndBowlState, 3)) {
+ if (CHECK_FLAG(dsAddr_GotJailKeyFlag, 1)) {
+ displayMessage(dsAddr_noPocketMsg); // "I don't want to touch his pockets again."
} else {
moveTo(280, 179, 2);
playSound(49, 7);
playSound(5, 17);
playActorAnimation(827);
- inventory->add(0x4d);
- SET_FLAG(0xDBDE, 1);
+ inventory->add(kInvItemJailKey);
+ SET_FLAG(dsAddr_GotJailKeyFlag, 1);
}
} else
- displayMessage(0x5905);
- return true;
+ displayMessage(dsAddr_foodAliveMsg); // "No, thanks. This food seems still alive"
+ break;
- case 0x46af: //prison cell: use live cable
- if (CHECK_FLAG(0xdbdc, 1)) {
- displayMessage(0x555d);
+ case 0x46af: // prison cell: use live cable
+ if (CHECK_FLAG(dsAddr_GotFoodBowlInJailFlag, 1)) {
+ displayMessage(dsAddr_ideaMsg); // "That gives me an idea"
setOns(2, 0);
playActorAnimation(821);
setOns(2, 0x5a);
setOns(3, 0);
playSound(22, 2);
playActorAnimation(822);
- displayMessage(0x5577);
+ displayMessage(dsAddr_checkWorksMsg); // "Now I got to check if it works"
disableObject(5);
- SET_FLAG(0xdbdd, 1);
+ SET_FLAG(dsAddr_JailCableAndBowlState, 1);
} else
- displayMessage(0x5528);
- return true;
+ displayMessage(dsAddr_unkUsageMsg); // "I don't have any idea what to do with it right now"
+ break;
- case 0x4705: //prison: getting lamp bulb
+ case 0x4705: // prison: getting lamp bulb
wait(50);
moveTo(144, 185, 4);
playSound(56, 15);
- setOns(0, 86); //hiding lamp
+ setOns(0, 86); // hiding lamp
playActorAnimation(816, true);
playAnimation(817, 0, true);
waitAnimation();
@@ -430,69 +850,102 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
disableObject(6);
enableObject(5);
- inventory->add(0x4c);
- return true;
+ inventory->add(kInvItemBulb);
+ break;
- case 0x4794: //prison cell door
- if (res->dseg.get_byte(0xDBDF) >= 2) {
+ case 0x4794: // prison cell door
+ if (res->dseg.get_byte(dsAddr_FirstActTrialState) >= 2) {
loadScene(5, 287, 143);
} else {
- displayMessage(0x592f);
+ displayMessage(dsAddr_doorClosedMsg); // "The door is closed. What a surprise."
}
- return true;
+ break;
- case 0x47bc: //prison: examining trash can
+ case 0x47bc: // prison: examining trash can
playSound(79, 5);
playSound(1, 14);
playActorAnimation(966);
- displayMessage(0x5955);
- return true;
+ displayMessage(dsAddr_emptyMsg); // "It's Empty"
+ break;
- case 0x47db: //prison: use switch
- if (CHECK_FLAG(0xDBDF, 1)) {
+ case 0x47db: // prison: use switch
+ if (CHECK_FLAG(dsAddr_FirstActTrialState, 1)) {
playSound(71, 4);
playActorAnimation(823);
- if (CHECK_FLAG(0xDBDD, 0)) {
- displayMessage(0x4d80);
+ if (CHECK_FLAG(dsAddr_JailCableAndBowlState, 0)) {
+ displayMessage(dsAddr_NotHappenMsg); // "Nothing happened"
} else {
playSound(74, 1);
playAnimation(824, 1);
- if (CHECK_FLAG(0xDBDD, 1)) {
+ if (CHECK_FLAG(dsAddr_JailCableAndBowlState, 1)) {
wait(100);
- displayMessage(0x559a);
- SET_FLAG(0xDBDD, 2);
+ displayMessage(dsAddr_timeToCallMsg); // "I think it is time to call captain"
+ SET_FLAG(dsAddr_JailCableAndBowlState, 2);
}
}
} else {
- displayMessage(0x52f6);
+ displayMessage(dsAddr_nahMsg); // "Nah"
}
- return true;
+ break;
+
+ case 0x4836:
+ rejectMessage();
+ break;
case 0x4871:
playActorAnimation(965);
- displayMessage(0x5511);
- return true;
+ displayMessage(dsAddr_lockedMsg); // "It's Locked!"
+ break;
+
+ case 0x487e:
+ displayMessage(dsAddr_geographyClassMsg); // "I should have paid more attention in geography classes."
+ break;
+
+ case 0x4885:
+ displayMessage(dsAddr_dontNeedMessMsg); // "I don't need this mess"
+ break;
+
+ case 0x488c:
+ displayMessage(dsAddr_seenSofterRocksMsg); // "Thanks, but I've seen softer rocks"
+ break;
- case 0x4893: //taking pills
- if (CHECK_FLAG(0xDBE6, 1)) {
- SET_FLAG(0xDBE6, 2);
+ case 0x4893: // taking pills
+ if (CHECK_FLAG(dsAddr_captainDrawerState, 1)) {
+ SET_FLAG(dsAddr_captainDrawerState, 2);
setOns(1, 0x67);
playSound(5, 9);
playActorAnimation(872);
- inventory->add(0x5a);
+ inventory->add(kInvItemMedicine);
disableObject(7);
} else {
playActorAnimation(964);
- displayMessage(0x5511);
+ displayMessage(dsAddr_lockedMsg); // "It's Locked!"
}
- return true;
+ break;
+
+ case 0x48d4:
+ displayMessage(dsAddr_tooBluntMsg); // "They are too blunt to be of any use"
+ break;
+
+ case 0x48db:
+ displayMessage(dsAddr_uselessModelsMsg); // "What's the use of the models?"
+ break;
+
+ case 0x48e2:
+ case 0x48e6:
+ rejectMessage();
+ break;
+
+ case 0x4911:
+ displayMessage(dsAddr_barmanWillNoticeMsg); // "The barman will surely notice its disappearing"
+ break;
- case 0x4918: //talking with barmen
- if (CHECK_FLAG(0xDBE7, 1)) {
+ case 0x4918: // talking with barmen
+ if (CHECK_FLAG(dsAddr_birdOnBarRadioAntennaFlag, 1)) {
moveTo(140, 152, 1);
- if (CHECK_FLAG(0xDBE8, 1)) {
- Dialog::showMono(scene, 0x6f20, 0, 0xd1, 0); //aren't you thirsty?
- displayMessage(0x5883, 0xef, 21472);
+ if (CHECK_FLAG(dsAddr_swappedBarmanMugFlag, 1)) {
+ dialog->showMono(177, scene, 0, textColorMark, 0);
+ displayMessage(dsAddr_yeahRightMsg, textColorBarman, 32, 67); // "Yeah right!"
//reloadLan();
setLan(1, 0);
playAnimation(882, 0);
@@ -504,86 +957,145 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
shakeScreen();
disableObject(1);
disableObject(2);
- SET_FLAG(0xDBE9, 1);
+ SET_FLAG(dsAddr_barmanPassedOutFlag, 1);
} else
- displayMessage(0x5855);
+ displayMessage(dsAddr_talkNotNowMsg); // "I've got no reason to talk to him right now."
} else {
- if (CHECK_FLAG(0xDBDF, 3)) {
- if (CHECK_FLAG(0xDBE3, 1)) {
- Dialog::show(scene, 0x6BD6, 0, 857, 0xd1, 0xef, 0, 1);
+ if (CHECK_FLAG(dsAddr_FirstActTrialState, 3)) {
+ if (CHECK_FLAG(dsAddr_spokeToBarmanAboutThirdTrialFlag, 1)) {
+ dialog->show(168, scene, 0, 857, textColorMark, textColorBarman, 0, 1);
} else {
- Dialog::show(scene, 0x69B5, 0, 857, 0xd1, 0xef, 0, 1); //taking mug
+ dialog->show(166, scene, 0, 857, textColorMark, textColorBarman, 0, 1); // taking mug
playActorAnimation(859, true);
playAnimation(858, 0, true);
waitAnimation();
playSound(75, 6);
playActorAnimation(860);
- Dialog::show(scene, 0x69C2, 0, 857, 0xd1, 0xef, 0, 1);
- inventory->add(0x55);
- SET_FLAG(0xDBE3, 1);
- SET_FLAG(0xDBF0, 0);
+ dialog->show(167, scene, 0, 857, textColorMark, textColorBarman, 0, 1);
+ inventory->add(kInvItemMug);
+ SET_FLAG(dsAddr_spokeToBarmanAboutThirdTrialFlag, 1);
+ SET_FLAG(dsAddr_gotPasswordNeedSpeakBarmanFlag, 0);
}
} else {
- Dialog::pop(scene, 0xDB68, 0, 857, 0xd1, 0xef, 0, 1);
+ dialog->pop(scene, dsAddr_dialogStackBarman, 0, 857, textColorMark, textColorBarman, 0, 1);
}
}
- return true;
+ break;
- case 0x4f14: //use the hollow
- displayMessage(CHECK_FLAG(0xDBA1, 1) ? 0x370f : 0x36c2);
- return true;
+ case 0x4d7d:
+ case 0x4d81:
+ rejectMessage();
+ break;
+
+ case 0x4d89:
+ displayMessage(dsAddr_getRidOfGuardFirstMsg); // "If I want to get inside I must get rid of this guard first..."
+ break;
+
+ case 0x4d90:
+ rejectMessage();
+ break;
+
+ case 0x4e47:
+ loadScene(13, Common::Point(9, 172));
+ scene->setOrientation(2);
+ break;
+
+ case 0x4e85:
+ loadScene(15, Common::Point(291, 162));
+ scene->setOrientation(4);
+ break;
+
+ case 0x4e9f:
+ loadScene(12, Common::Point(310, 152));
+ scene->setOrientation(4);
+ break;
+
+ case 0x4f14: // use the hollow
+ if (CHECK_FLAG(dsAddr_mansionTreeHollowEmptyFlag, 1))
+ displayMessage(dsAddr_totalEmptyMsg); // "I can see it's totally empty"
+ else
+ displayMessage(dsAddr_noHandsMsg); // "I'd better not put my hands in there..."
+ break;
case 0x4a64:
- if (CHECK_FLAG(0xDBF0, 1)) {
- displayMessage(0x5e25);
- } else {
+ if (CHECK_FLAG(dsAddr_gotPasswordNeedSpeakBarmanFlag, 1))
+ displayMessage(dsAddr_firstBusinessMsg); // "First I've got some business to take care of"
+ else
loadScene(5, 35, 162);
- }
- return true;
+ break;
case 0x4bf5:
playActorAnimation(959);
loadScene(8, 40, 152, 3);
- return true;
+ break;
+
+ case 0x4c18:
+ rejectMessage();
+ break;
+
+ case 0x4c29:
+ displayMessage(dsAddr_tooManyToSearchMsg); // "There are too many of them to search"
+ break;
+
+ case 0x4c30:
+ case 0x4c37:
+ displayMessage(dsAddr_captainWouldNotFitMsg); // "Captain surely wouldn't fit them. I must look elsewhere"
+ break;
case 0x483a:
- Dialog::pop(scene, 0xdb82, 0, 0, 0xd1, 0xd1, 0, 0);
- return true;
+ dialog->popMark(scene, dsAddr_dialogStackInterrogateCaptain);
+ break;
case 0x4844:
playSound(80, 4);
playActorAnimation(963);
loadScene(5, 166, 158);
- return true;
+ break;
case 0x48ea:
setOns(0, 0);
playSound(5, 9);
playActorAnimation(836);
- inventory->add(0x4f);
+ inventory->add(kInvItemSwissArmyKnife);
disableObject(12);
- return true;
+ break;
case 0x4a8c:
- if (CHECK_FLAG(0xDBE9, 1)) {
+ if (CHECK_FLAG(dsAddr_barmanPassedOutFlag, 1)) {
playSound(89, 5);
playActorAnimation(958);
loadScene(9, 240, 182, 4);
- } else if (CHECK_FLAG(0xDBE7, 1)) {
- displayMessage(0x5894);
+ } else if (CHECK_FLAG(dsAddr_birdOnBarRadioAntennaFlag, 1)) {
+ displayMessage(dsAddr_barmanTooCloseMsg); // "The barman is too close"
} else {
- Dialog::pop(scene, 0xDB8A, 0, 857, 0xd1, 0xef, 0, 1);
+ dialog->pop(scene, dsAddr_dialogStackBarCellarDoor, 0, 857, textColorMark, textColorBarman, 0, 1);
}
- return true;
+ break;
- case 0x4af4: //taking the crumbs
+ case 0x4aed:
+ displayMessage(dsAddr_tooBigMsg); // "It's too big and I doubt if I'll ever need it"
+ break;
+
+ case 0x4af4: // taking the crumbs
setOns(0, 0);
playSound(49, 6);
playSound(5, 13);
playActorAnimation(861);
- inventory->add(0x57);
+ inventory->add(kInvItemCrumbs);
disableObject(6);
- return true;
+ break;
+
+ case 0x4b23:
+ rejectMessage();
+ break;
+
+ case 0x4b27:
+ displayMessage(dsAddr_tooMuchToDrinkMsg); // "It'd take too much time to drink it..."
+ break;
+
+ case 0x4b2e:
+ displayMessage(dsAddr_notThiefMsg); // "I'm not a thief. And it's empty, by the way."
+ break;
case 0x4b35:
playSound(15, 7);
@@ -591,140 +1103,149 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playSound(55, 1);
playSound(24, 12);
playAnimation(885, 0);
- Dialog::show(scene, 0x67e5, 886, 0, 0xd0, 0xd1, 1, 0);
+ dialog->show(164, scene, 886, 0, textColorJohnNoty, textColorMark, 1, 0);
playMusic(3);
loadScene(40, 198, 186, 1);
- Dialog::show(scene, 0x7f20, 0, 920, 0xd1, 0xe7, 0, 1);
+ dialog->show(202, scene, 0, 920, textColorMark, textColorRGBBoss, 0, 1);
inventory->clear();
- inventory->add(0x1d);
- displayCredits(0xe45c);
+ inventory->add(kInvItemSuperGlue);
+ displayCredits(dsAddr_credits5);
loadScene(1, 198, 186);
hideActor();
playActorAnimation(956);
- Dialog::showMono(scene, 0x8bc4, 957, 0xd1, 1);
+ dialog->showMono(212, scene, 957, textColorMark, 1);
waitAnimation();
loadScene(15, 157, 199, 1);
playMusic(6);
- return true;
+ break;
- case 0x4c3e: //get the grenade
+ case 0x4c3e: // get the grenade
playSound(32, 24);
playActorAnimation(862);
reloadLan();
playAnimation(863, 1);
- inventory->add(0x54);
+ inventory->add(kInvItemGrenade);
disableObject(1);
- SET_FLAG(0xDBE2, 2);
- return true;
+ SET_FLAG(dsAddr_act1GuardState, 2);
+ break;
case 0x4c70:
- if (CHECK_FLAG(0xDBE2, 0)) {
- if (CHECK_FLAG(0xDBDA, 1)) { //papers are shown
- Dialog::pop(scene, 0xDB4C, 0, 809, 0xd1, 0xd0, 0, 1);
+ if (CHECK_FLAG(dsAddr_act1GuardState, 0)) {
+ if (CHECK_FLAG(dsAddr_ShownPassToGuardFlag, 1)) { // papers are shown
+ dialog->pop(scene, dsAddr_dialogStackCampGuardReadingNews, 0, 809, textColorMark, textColorCampGuard, 0, 1);
} else {
- Dialog::pop(scene, 0xDB40, 0, 809, 0xd1, 0xd0, 0, 1);
+ dialog->pop(scene, dsAddr_dialogStackCampGuardWantsDocuments, 0, 809, textColorMark, textColorCampGuard, 0, 1);
}
} else {
- displayMessage(0x5722);
+ displayMessage(dsAddr_helloQMsg); // "Hello?"
wait(100);
- displayMessage(0x572a);
+ displayMessage(dsAddr_totallyAddictedMsg); // "He's totally addicted"
}
- return true;
+ break;
case 0x4c1c:
playActorAnimation(960);
- displayMessage(0x5511);
- return true;
+ displayMessage(dsAddr_lockedMsg); // "It's Locked!"
+ break;
+
+ case 0x4ca5:
+ displayMessage(dsAddr_chickenNeverMsg); // "Chickening? Me? Never!"
+ break;
case 0x4cac:
- if (CHECK_FLAG(0xdbda, 1)) { //papers are shown
+ if (CHECK_FLAG(dsAddr_ShownPassToGuardFlag, 1)) { // papers are shown
loadScene(5, 124, 199);
} else {
- Dialog::show(scene, 0x5FE9, 0, 809, 0xd1, 0xd0, 0, 1);
+ dialog->show(144, scene, 0, 809, textColorMark, textColorCampGuard, 0, 1);
moveTo(269, 175, 4);
- Dialog::pop(scene, 0xDB56, 0, 809, 0xd1, 0xd0, 0, 1);
+ dialog->pop(scene, dsAddr_dialogStackCampGuardShowPass, 0, 809, textColorMark, textColorCampGuard, 0, 1);
}
- return true;
-
- case 0x4cf1: { //talking with mansion guard
- SET_FLAG(0xda96, 1);
- if (Dialog::pop(scene, 0xdaa6, 0, 529, 0xd1, 0xd9, 0, 1) != 0x1b4)
- return true;
+ break;
- Common::Point p = scene->getPosition();
- moveTo(189, 159, 0);
- //waitLanAnimationFrame(1, 1);
+ case 0x4cf1: // talking with mansion guard
+ SET_FLAG(dsAddr_spokenWithMansionGuardFlag, 1);
+ if (dialog->pop(scene, dsAddr_dialogStackPleadingToMansionGuard, 0, 529, textColorMark, textColorMansionGuard, 0, 1) == 0x01b4) { // 2nd try
+ Common::Point p = scene->getPosition();
+ moveTo(189, 159, 0);
+ //waitLanAnimationFrame(1, 1);
- playSound(5, 2);
- playSound(5, 19);
- playActorAnimation(550, true);
- playAnimation(551, 0, true);
- waitAnimation();
+ playSound(5, 2);
+ playSound(5, 19);
+ playActorAnimation(550, true);
+ playAnimation(551, 0, true);
+ waitAnimation();
- moveTo(p, 2);
- inventory->add(0x13);
- Dialog::pop(scene, 0xdaa6, 0, 529, 0xd1, 0xd9, 0, 1);
- }
- return true;
+ moveTo(p, 2);
+ inventory->add(kInvItemChocCandy);
+ dialog->pop(scene, dsAddr_dialogStackPleadingToMansionGuard, 0, 529, textColorMark, textColorMansionGuard, 0, 1);
+ }
+ break;
- case 0x4d94: //talking with fatso
- Dialog::show(scene, 0x33bd, 0, 666, 0xd1, 0xd0, 0, 2);
- displayAsyncMessage(0x49ae, /*25060*/ 35000, 1, 10, 0xd0);
+ case 0x4d94: // talking with fatso
+ dialog->show(87, scene, 0, 666, textColorMark, textColorJohnNoty, 0, 2);
+ displayAsyncMessage(dsAddr_BribeMsg, 120, 109, 1, 10, textColorJohnNoty); // FIXME: Original (x,y) was (100, 78), rather than (120, 109)?
playSound(5, 3);
playAnimation(667, 1);
playAnimation(668, 1);
setOns(2, 50);
- Dialog::show(scene, 0x36c7, 0, 666, 0xd1, 0xd0, 0, 2);
+ dialog->show(88, scene, 0, 666, textColorMark, textColorJohnNoty, 0, 2);
setOns(3, 0);
- setFlag(0xDBEC, 0);
+ setFlag(dsAddr_johnNotyOutsideMansionDoorFlag, 0);
reloadLan();
playSound(82, 19);
playAnimation(669, 1);
- Dialog::showMark(scene, 0x3779);
+ dialog->showMark(89, scene);
enableObject(15);
disableObject(8);
- return true;
+ break;
case 0x4e61:
loadScene(14, 280, 198);
- return true;
+ break;
case 0x4ee5:
setOns(2, 0);
playSound(5, 12);
playActorAnimation(676);
- displayMessage(0x4ab0);
+ displayMessage(dsAddr_WimpMsg); // "I'm a pathetic little wimp"
disableObject(15);
- inventory->add(51);
- return true;
+ inventory->add(kInvItemBanknote);
+ break;
case 0x4d56:
- inventory->add(16);
+ inventory->add(kInvItemWhisky);
disableObject(2);
setOns(0, 0);
playSound(5, 12);
playActorAnimation(547);
- return true;
+ break;
+ case 0x4d85:
+ rejectMessage();
+ break;
- case 0x4eb9://Pick up wrapper
+ case 0x4eb9: // Pick up wrapper
playSound(5, 12);
playSound(5, 18);
- inventory->add(0x12);
+ inventory->add(kInvItemWrapper);
setOns(1, 0);
playActorAnimation(549);
disableObject(13);
- return true;
+ break;
+
+ case 0x4ee1:
+ rejectMessage();
+ break;
case 0x4f25:
playActorAnimation(967);
- displayMessage(0x3542);
- return true;
+ displayMessage(dsAddr_tooHardWoodMsg); // "This wood is too hard to break"
+ break;
- case 0x4f32: //use tree near the mansion
- if (CHECK_FLAG(0xDBA1, 1)) {
- if (CHECK_FLAG(0xDBA2, 1)) {
- displayMessage(0x3766);
+ case 0x4f32: // use tree near the mansion
+ if (CHECK_FLAG(dsAddr_mansionTreeHollowEmptyFlag, 1)) {
+ if (CHECK_FLAG(dsAddr_climbedMansionTreeAlreadyFlag, 1)) {
+ displayMessage(dsAddr_noChanceMsg); // "I won't take my chances a second time"
} else {
playSound(26, 13);
playSound(26, 15);
@@ -739,95 +1260,126 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playSound(60, 16);
playActorAnimation(591);
wait(50);
- displayMessage(0x372e);
- SET_FLAG(0xDBA2, 1);
- processCallback(0x9d45);
+ displayMessage(dsAddr_oneSmallStepMsg); // "One small step for man, one big pain in the head"
+ SET_FLAG(dsAddr_climbedMansionTreeAlreadyFlag, 1);
+ fnMansionIntrusionAttempt();
}
} else {
playActorAnimation(49);
playSound(56, 8);
playSound(56, 12);
playSound(49, 10);
- displayAsyncMessage(0x4652, 31579, 16, 24);
+ displayAsyncMessage(dsAddr_laughterMsg, 219, 98, 16, 24); // "(laughter)"
playActorAnimation(587);
moveRel(0, 0, 2);
wait(100);
- displayMessage(0x3668);
+ displayMessage(dsAddr_tickledMsg); // "Something tickled me!"
}
- return true;
+ break;
- case 0x500d: //picking up wild plant
- if (CHECK_FLAG(0xDB9E, 1)) {
- displayMessage(0x35E8); //there are no more
+ case 0x500d: // picking up wild plant
+ if (CHECK_FLAG(dsAddr_gotPotatoAlreadyFlag, 1)) {
+ displayMessage(dsAddr_noPotatoMsg); // "There are no more potatoes"
} else {
- SET_FLAG(0xDB9E, 1);
+ SET_FLAG(dsAddr_gotPotatoAlreadyFlag, 1);
setOns(2, 0);
playSound(21, 9);
playSound(34, 21);
playSound(26, 30);
playActorAnimation(552);
setOns(2, 0x12);
- inventory->add(0x14);
+ inventory->add(kInvItemPotato);
}
- return true;
+ break;
+
+ case 0x505f:
+ displayMessage(dsAddr_wallTooSmoothMsg); // "The wall surface is too smooth to climb"
+ break;
+
+ case 0x5066:
+ loadScene(11, Common::Point(183, 109));
+ scene->setOrientation(3);
+ break;
+
+ case 0x5080:
+ loadScene(13, Common::Point(290, 181));
+ scene->setOrientation(4);
+ break;
+
+ case 0x50f6:
+ displayMessage(dsAddr_tooMuchResinToClimbMsg); // "I could climb it if there wasn't so much resin"
+ break;
+
+ case 0x50fd:
+ displayMessage(dsAddr_onlyGreenRectMsg); // "The only green stuff that I like is that rectangular piece of paper with..."
+ break;
case 0x5104:
loadScene(11, 319, 198, 4);
- if (CHECK_FLAG(0xDB9C, 1))
- return true;
-
- //guard's drinking
- SET_FLAG(0, 3);
- setTimerCallback(0x516d, 40);
- playAnimation(544, 0, true, true); //ignore busy flag for this animation
- return true;
+ if (!CHECK_FLAG(dsAddr_scaredGuardAlreadyFlag, 1)) {
+ // guard is drinking
+ SET_FLAG(dsAddr_timedCallbackState, 3);
+ setTimerCallback(csAddr_guardScareTimeout, 40);
+ playAnimation(544, 0, true, true); // ignore busy flag for this animation
+ }
+ break;
- case 0x516d: //too late to scare guard, resetting
- SET_FLAG(0, 0);
- return true;
+ case csAddr_guardScareTimeout: // too late to scare guard, resetting
+ SET_FLAG(dsAddr_timedCallbackState, 0);
+ break;
- case 0x5189: //guard's drinking, boo!
- SET_FLAG(0, 0);
- setTimerCallback(0, 0);
- scene->getAnimation(0)->free();
- SET_FLAG(0xDB9C, 1);
+ case csAddr_guardDrinking:
+ fnGuardDrinking();
+ break;
- displayAsyncMessage(0x3563, 320 * 130 + 300, 1, 5);
- setOns(0, 16);
- enableObject(2);
+ case 0x51c8:
+ displayMessage(dsAddr_wallTooSmoothMsg); // "The wall surface is too smooth to climb"
+ break;
- playSound(17, 5);
- playAnimation(545, 0);
+ case 0x51cf:
+ loadScene(12, Common::Point(15, 189));
+ scene->setOrientation(2);
+ break;
- Dialog::show(scene, 0x0917, 0, 546, 0xd1, 0xd9, 0, 1);
- SET_FLAG(0xDA96, 1);
- SET_FLAG(0xDA97, 0);
- return true;
+ case 0x51e9:
+ displayMessage(dsAddr_dontWannaTouchHedgehogMsg); // "I don't wanna touch it. Its spines could hurt my delicate hands"
+ break;
case 0x51f0:
setOns(0, 0);
playSound(5, 11);
playActorAnimation(637);
disableObject(7);
- inventory->add(49);
- return true;
+ inventory->add(kInvItemRock);
+ break;
case 0x5217:
- displayMessage(CHECK_FLAG(0xDB9F, 1) ? 0x402e : 0x34e1);
- return true;
+ if (CHECK_FLAG(dsAddr_beesGoneFlag, 1))
+ displayMessage(dsAddr_notHungryMsg); // "Thanks, I'm not hungry"
+ else
+ displayMessage(dsAddr_avoidBeesMsg); // "I'm going to stay at least five meters away from these bees!"
+ break;
+
+ case 0x522c:
+ displayMessage(dsAddr_avoidBeesMsg); // "I'm going to stay at least five meters away from these bees!"
+ break;
+
+ case 0x5233:
+ rejectMessage();
+ break;
case 0x5237:
- if (!CHECK_FLAG(0xDB9F, 1)) {
- displayMessage(0x34e1);
- } else if (CHECK_FLAG(0xDBA0, 1))
- displayMessage(0x3E31);
+ if (!CHECK_FLAG(dsAddr_beesGoneFlag, 1)) {
+ displayMessage(dsAddr_avoidBeesMsg); // "I'm going to stay at least five meters away from these bees!"
+ } else if (CHECK_FLAG(dsAddr_mansionTunnelDoneFlag, 1))
+ displayMessage(dsAddr_roadNowhereMsg); // "Nah. It's a road to nowhere"
else {
moveTo(173, 138, 2);
playSound(28, 5);
playActorAnimation(583);
playActorAnimation(584);
- loadScene(0, 0, 0, 0); //clear background
+ loadScene(0, 0, 0, 0); // clear background
playSound(72, 18);
playSound(73, 39);
@@ -837,82 +1389,257 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playSound(28, 2);
playActorAnimation(586);
moveTo(138, 163, 3);
- displayMessage(0x3650);
- SET_FLAG(0xDBA0, 1);
- processCallback(0x9d45); //another mansion try
+ displayMessage(dsAddr_lifeBrutalMsg); // "Life is really brutal"
+ SET_FLAG(dsAddr_mansionTunnelDoneFlag, 1);
+ fnMansionIntrusionAttempt();
}
- return true;
-
- case 0x55a8: {
- uint16 d = Dialog::pop(scene, 0xdb08, 0, 0, 0xd1, 0xd1, 0, 0);
- if (d == 0x2c5d) {
- waitLanAnimationFrame(1, 0x23);
- setOns(0, 0);
- playSound(52, 9);
- playSound(52, 11);
- playSound(52, 13);
- playSound(53, 32);
- playAnimation(570, 0);
- wait(50);
- displayMessage(0x551f);
- disableObject(5);
- SET_FLAG(0xDBB0, 1);
- } else if (d != 0x2c9b) {
- waitLanAnimationFrame(1, 0x23);
- playSound(52, 9);
- playSound(52, 11);
- playSound(52, 13);
- playAnimation(569, 0);
+ break;
+
+ case 0x5320:
+ loadScene(11, Common::Point(30, 124));
+ scene->setOrientation(2);
+ break;
+
+ case 0x533a:
+ displayMessage(dsAddr_noLongHandsMsg); // "I really don't have such long hands"
+ break;
+
+ case 0x5341:
+ displayMessage(dsAddr_tooFarToSwimMsg); // "It's too far to swim there"
+ break;
+
+ case 0x5403:
+ displayMessage(dsAddr_noBucketMsg); // "It's not a barrel-organ. And there's no bucket."
+ break;
+
+ case 0x540a:
+ loadScene(20, Common::Point(10, 185));
+ scene->setOrientation(2);
+ break;
+
+ case 0x5424:
+ loadScene(11, Common::Point(30, 170));
+ scene->setOrientation(2);
+ break;
+
+ case 0x543e:
+ loadScene(18, Common::Point(224, 199));
+ scene->setOrientation(4);
+ break;
+
+ case 0x5547:
+ loadScene(15, Common::Point(15, 172));
+ scene->setOrientation(2);
+ break;
+
+ case 0x55a8:
+ {
+ uint16 d = dialog->popMark(scene, dsAddr_dialogStackSquirrel);
+ if (d == 0x2c5d) { // 4th try - Throw Nut
+ waitLanAnimationFrame(1, 0x23);
+ setOns(0, 0);
+ playSound(52, 9);
+ playSound(52, 11);
+ playSound(52, 13);
+ playSound(53, 32);
+ playAnimation(570, 0);
+ wait(50);
+ displayMessage(dsAddr_ThanksMsg); // "Thanks."
+ disableObject(5);
+ SET_FLAG(dsAddr_squirrelNutState, 1);
+ } else if (d != 0x2c9b) { // 5th (last) try
+ waitLanAnimationFrame(1, 0x23);
+ playSound(52, 9);
+ playSound(52, 11);
+ playSound(52, 13);
+ playAnimation(569, 0);
+ }
}
- }
- return true;
+ break;
case 0x5663:
- displayMessage(CHECK_FLAG(0xDBB0, 1) ? 0x41b1 : 0x417e);
- return true;
+ if (CHECK_FLAG(dsAddr_squirrelNutState, 1))
+ displayMessage(dsAddr_findNutMsg); // "I won't find the nut just like that. The grass is too dense"
+ else
+ displayMessage(dsAddr_hmmGrassMsg); // "Hmmm. Grass..."
+ break;
+
+ case 0x5674:
+ loadScene(18, Common::Point(94, 115));
+ scene->setOrientation(3);
+ break;
+
+ case 0x568e:
+ displayMessage(dsAddr_notHornyMsg); // "I'm not horny"
+ break;
+
+ case 0x5695:
+ displayMessage(dsAddr_dontNeedToOpenMsg); // "I don't need to open it"
+ break;
case 0x569c:
playSound(67, 5);
playActorAnimation(983);
- displayMessage(0x5955);
- return true;
+ displayMessage(dsAddr_emptyMsg); // "It's Empty"
+ break;
+
+ case 0x56b3:
+ rejectMessage();
+ break;
case 0x56b7:
playSound(66, 5);
playSound(67, 11);
playActorAnimation(984);
- displayMessage(0x5955);
- return true;
+ displayMessage(dsAddr_emptyMsg); // "It's Empty"
+ break;
+
+ case 0x56d6:
+ displayMessage(dsAddr_CantJumpMsg); // "No way I can jump so high, cause, err, white men can't jump"
+ break;
+
+ case 0x56dd:
+ displayMessage(dsAddr_dontNeedItMsg); // "I don't need it"
+ break;
+
+ case 0x56e4:
+ displayMessage(dsAddr_notSantaClausMsg); // "I'm not Santa Claus"
+ break;
+
+ case 0x56eb:
+ displayMessage(dsAddr_noPlasticImitationsMsg); // "I don't need plastic imitations"
+ break;
+
+ case 0x56f2:
+ rejectMessage();
+ break;
+
+ case 0x5721:
+ displayMessage(dsAddr_dontNeedItMsg); // "I don't need it"
+ break;
case 0x5728:
- inventory->add(0x0d);
+ inventory->add(kInvItemChainsaw);
disableObject(14);
setOns(0, 0);
playSound(5, 10);
playActorAnimation(566);
- return true;
+ break;
+
+ case 0x574f:
+ displayMessage(dsAddr_tooFragileMsg); // "It's too fragile to carry around"
+ break;
case 0x5793:
- if (!CHECK_FLAG(0xDB94, 1)) {
- displayMessage(0x3e63);
- } else if (CHECK_FLAG(0xDB95, 1)) {
- displayMessage(0x3e75);
+ if (!CHECK_FLAG(dsAddr_alreadyPulledTrunkReleaseLeverFlag, 1)) {
+ displayMessage(dsAddr_shutTightMsg); // "It's shut tight"
+ } else if (CHECK_FLAG(dsAddr_carTrunkEmptyFlag, 1)) {
+ displayMessage(dsAddr_bootEmptyMsg); // "There's nothing else in the boot"
} else {
- SET_FLAG(0xDB95, 1);
+ SET_FLAG(dsAddr_carTrunkEmptyFlag, 1);
moveTo(188, 179, 0);
playSound(7, 16);
playActorAnimation(519);
wait(150);
moveTo(168, 179, 2);
- inventory->add(3);
+ inventory->add(kInvItemToolboxFull);
}
- return true;
+ break;
+
+ case 0x57fa:
+ displayMessage(dsAddr_dontNeedItMsg); // "I don't need it"
+ break;
+
+ case 0x5801:
+ rejectMessage();
+ break;
+
+ case 0x583f:
+ case 0x5846:
+ displayMessage(dsAddr_dontNeedToOpenMsg);
+ break;
+
+ case 0x584d:
+ displayMessage(dsAddr_pullObjMsg2);
+ break;
+
+ case 0x5854:
+ loadScene(15, Common::Point(157, 199));
+ scene->setOrientation(1);
+ break;
+
+ case 0x586e:
+ loadScene(21, Common::Point(24, 187));
+ scene->setOrientation(2);
+ break;
+
+ case 0x5888:
+ loadScene(27, Common::Point(108, 199));
+ scene->setOrientation(2);
+ break;
+
+ case 0x5903:
+ displayMessage(dsAddr_keepItOpenMsg); // "I'd like to keep it open"
+ break;
+
+ case 0x590a:
+ loadScene(20, Common::Point(304, 190));
+ scene->setOrientation(4);
+ break;
+
+ case 0x5924:
+ loadScene(25, Common::Point(298, 146));
+ scene->setOrientation(4);
+ break;
+
+ case 0x5978:
+ displayMessage(dsAddr_notTakingSocksMsg); // "I really don't want to walk around with someone else's socks"
+ break;
+
+ case 0x597f:
+ case 0x5986:
+ case 0x598d:
+ displayMessage(dsAddr_dontNeedToOpenMsg); // "I don't need to open it"
+ break;
+
+ case 0x5b44:
+ // 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.
+ displayMessage(dsAddr_ItsOpenMsg);
+ break;
+
+ case 0x5c72:
+ displayMessage(dsAddr_notTiredMsg); // "Thanks, I'm not tired"
+ break;
+
+ case 0x5c79:
+ displayMessage(dsAddr_dontNeedToOpenMsg); // "I don't need to open it"
+ break;
+
+ case 0x5c80:
+ rejectMessage();
+ break;
+
+ case 0x5cdb:
+ case 0x5ce2:
+ displayMessage(dsAddr_dontNeedItMsg); // "I don't need it"
+ break;
+
+ case 0x5ce9:
+ displayMessage(dsAddr_tooBigMsg); // "It's too big and I doubt if I'll ever need it"
+ break;
+
+ case 0x5d1d:
+ displayMessage(dsAddr_CantJumpMsg); // "No way I can jump so high, cause, err, white men can't jump"
+ break;
case 0x5d88:
- if (CHECK_FLAG(0xDBA5, 1)) { //dry laundry
- SET_FLAG(0xDBA5, 2);
- Dialog::show(scene, 0x1F4F, 0, 523, 0xd1, 0xe5, 0, 1);
- //waitLanAnimationFrame(1, 1); //another long waiting
+ if (CHECK_FLAG(dsAddr_laundryState, 1)) { // dry laundry
+ SET_FLAG(dsAddr_laundryState, 2);
+ dialog->show(46, scene, 0, 523, textColorMark, textColorOldLady, 0, 1);
+ //waitLanAnimationFrame(1, 1); // another long waiting
playAnimation(604, 0);
loadScene(21, scene->getPosition());
@@ -924,184 +1651,393 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
setOns(0, 33);
loadScene(23, scene->getPosition());
playAnimation(605, 0);
- Dialog::show(scene, 0x2002, 0, 523, 0xd1, 0xe5, 0, 1);
+ dialog->show(47, scene, 0, 523, textColorMark, textColorOldLady, 0, 1);
} else {
- uint16 d = Dialog::pop(scene, 0xdada, 0, 523, 0xd1, 0xe5, 0, 1);
- if (d == 0x1913) {
+ uint16 d = dialog->pop(scene, dsAddr_dialogStackAskOldLadyOK, 0, 523, textColorMark, textColorOldLady, 0, 1);
+ if (d == 0x1913) { // 3rd time
wait(100);
moveRel(0, 0, 3);
wait(50);
- displayMessage(0x34d5); //I give up
+ displayMessage(dsAddr_giveUpMsg); // "I give up"
wait(50);
}
}
- return true;
+ break;
+
+ case 0x5f9a:
+ case 0x5fa1:
+ displayMessage(dsAddr_dontNeedToOpenMsg); // "I don't need to open it"
+ break;
- case 0x5ff3: //get duster
- if (CHECK_FLAG(0xDB9A, 0)) {
- Dialog::pop(scene, 0xdaf6, 0, 523, 0xd1, 0xe5, 0, 1);
+ case 0x5fa8:
+ displayMessage(dsAddr_CantJumpMsg); // "No way I can jump so high, cause, err, white men can't jump"
+ break;
+
+ case 0x5faf:
+ displayMessage(dsAddr_noSecretPassageMsg); // "I don't think there's any secret passage inside"
+ break;
+
+ case 0x5fe5:
+ displayMessage(dsAddr_jugMeMsg); // "They can jug me if I steal this"
+ break;
+
+ case 0x5fec:
+ displayMessage(dsAddr_leaveFlowersAloneMsg); // "I'd better leave it. Women are really oversensitive about flowers."
+ break;
+
+ case 0x5ff3: // get duster
+ if (CHECK_FLAG(dsAddr_givenFlowerToOldLadyAlreadyFlag, 0)) {
+ dialog->pop(scene, dsAddr_dialogStackBorrowDusterFromOldLady, 0, 523, textColorMark, textColorOldLady, 0, 1);
} else {
- Dialog::show(scene, 0x1e1e, 0, 523, 0xd1, 0xe5, 0, 1);
+ dialog->show(43, scene, 0, 523, textColorMark, textColorOldLady, 0, 1);
wait(50);
- inventory->add(12);
+ inventory->add(kInvItemFeatherDusterClean);
disableObject(12);
setOns(0, 0);
playSound(5, 6);
playActorAnimation(541);
}
- return true;
+ break;
+
+ case 0x603a:
+ rejectMessage();
+ break;
case 0x603e:
- if (CHECK_FLAG(0xDBB3, 1)) {
- displayMessage(0x44a7);
+ if (CHECK_FLAG(dsAddr_spokenToMirrorFlag, 1)) {
+ displayMessage(dsAddr_busyThinkingMsg); // "I'd better not interrupt it's thought process"
} else {
- displayMessage(0x4412);
+ displayMessage(dsAddr_mirrorMirrorMsg); // "Mirror, Mirror on the wall...."
wait(150);
- displayMessage(0x444f);
+ displayMessage(dsAddr_thinkTooLongMsg); // "Hey, don't think too long"
wait(150);
- displayMessage(0x446b);
+ displayMessage(dsAddr_HintMaleMsg); // "A hint: Someone in this room, a male"
wait(150);
- displayMessage(0x4492);
+ displayMessage(dsAddr_okWaitMsg); // "OK, take your time"
wait(150);
- SET_FLAG(0xDBB3, 1);
+ SET_FLAG(dsAddr_spokenToMirrorFlag, 1);
}
- return true;
+ break;
+
+ case 0x6074:
+ rejectMessage();
+ break;
+
+ case 0x6078:
+ displayMessage(dsAddr_tooBigMsg); // "It's too big and I doubt if I'll ever need it"
+ break;
case 0x6205:
- if (CHECK_FLAG(0xDBA4, 1))
- displayMessage(0x450e);
+ if (CHECK_FLAG(dsAddr_lightOnFlag, 1))
+ displayMessage(dsAddr_tooHeavyMsg); // "It's too heavy. Not that I'm wimp"
else
- processCallback(0x61fe);
- return true;
+ fnTooDark();
+ break;
case 0x6217:
- if (CHECK_FLAG(0xDBA4, 1))
- displayMessage(0x44d6);
+ if (CHECK_FLAG(dsAddr_lightOnFlag, 1))
+ displayMessage(dsAddr_noDentistsMsg); // "I don't want to have anything in common with dentists"
else
- processCallback(0x61fe);
- return true;
+ fnTooDark();
+ break;
case 0x62c1:
- if (CHECK_FLAG(0xDBA4, 1))
- return false;
+ if (CHECK_FLAG(dsAddr_lightOnFlag, 1))
+ retVal = false;
+ else
+ fnTooDark();
+ break;
- processCallback(0x61fe);
- return true;
+ case 0x634a:
+ displayMessage(dsAddr_noHandsSharpThornsMsg); // "I can't remove it with my hands. these thorns look really sharp"
+ break;
+
+ case 0x637f:
+ loadScene(21, Common::Point(201, 199));
+ scene->setOrientation(1);
+ break;
+
+ case 0x6399:
+ displayMessage(dsAddr_rockWalkingGeeMsg); // "Yeah, great idea. Let's take this rock and walk around a bit. Gee..."
+ break;
+
+ case 0x63a0:
+ case 0x63a7:
+ displayMessage(dsAddr_butterflyMsg); // "I'd better leave them alone, they make this place beautiful"
+ break;
+
+ case 0x63ae:
+ displayMessage(dsAddr_notSureIfAliveMsg); // "I'm not sure if it's alive"
+ break;
case 0x63bc:
playMusic(6);
loadScene(25, 151, 156, 2);
- return true;
+ break;
case 0x63dc:
- Dialog::showMono(scene, 0x3375, 0, 0xd1, 0);
- return true;
+ dialog->showMono(86, scene, 0, textColorMark, 0);
+ break;
+
+ case 0x63e3:
+ displayMessage(dsAddr_holeTooNarrowMsg); // "The hole is too narrow to fit my hand"
+ break;
case 0x646e:
case 0x6475:
- Dialog::showMono(scene, 0x32C1, 0, 0xd1, 0);
- return true;
+ dialog->showMono(85, scene, 0, textColorMark, 0);
+ break;
case 0x6479:
- Dialog::showMono(scene, 0x325e, 0, 0xd1, 0);
- return true;
+ dialog->showMono(84, scene, 0, textColorMark, 0);
+ break;
case 0x6507:
- if (CHECK_FLAG(0xDB96, 1)) {
+ if (CHECK_FLAG(dsAddr_birdsGoneFromScarecrowFlag, 1))
rejectMessage();
- } else
- displayMessage(0x47e7);
- return true;
+ else
+ displayMessage(dsAddr_birdAttackMsg); // "Hey You! Wake up! Bird attack!"
+ break;
+
+ case 0x6541:
+ loadScene(20, Common::Point(10, 131));
+ scene->setOrientation(3);
+ break;
+
+ case 0x6635:
+ displayMessage(dsAddr_uninterestingHaystackMsg); // "I don't see anything interesting about this haystack"
+ break;
+
+ case 0x666a:
+ displayMessage(dsAddr_moreComplicatedMsg); // "It's more complicated than that"
+ break;
case 0x65c3:
- if (CHECK_FLAG(0xDBA9, 1)) {
+ if (CHECK_FLAG(dsAddr_mouseHoleState, 1)) {
playActorAnimation(635);
setOns(5, 0);
playSound(63, 11);
playSound(15, 20);
playSound(32, 31);
playActorAnimation(636);
- inventory->add(47);
- inventory->add(48);
+ inventory->add(kInvItemHandkerchief);
+ inventory->add(kInvItemMouse);
moveTo(scene->getPosition().x - 1, 139, 1, true);
- displayMessage(0x3b83);
- SET_FLAG(0xDBA9, 2);
- SET_FLAG(0xDBA8, 0);
+ displayMessage(dsAddr_yikesMsg); // "Yikes!"
+ SET_FLAG(dsAddr_mouseHoleState, 2);
+ SET_FLAG(dsAddr_HankerchiefInMouseholeFlag, 0);
} else
- displayMessage(0x4808);
- return true;
+ displayMessage(dsAddr_noSearchWarrantMsg); // "I don't have a search-warrant"
+ break;
+
+ case 0x6671:
+ displayMessage(dsAddr_cantOpenItMsg); // "I can't open it"
+ break;
+
+ case 0x6678:
+ rejectMessage();
+ break;
+
+ case 0x670f:
+ displayMessage(dsAddr_dontNeedThemMsg); // "I don't need them"
+ break;
+
+ case 0x6716:
+ displayMessage(dsAddr_pullObjMsg2); // "I can't reach it"
+ break;
+
+ case 0x6772:
+ loadScene(31, Common::Point(20, 188));
+ scene->setOrientation(2);
+ break;
+
+ case 0x678c:
+ loadScene(28, Common::Point(189, 153));
+ scene->setOrientation(4);
+ break;
+
+ case 0x67fa:
+ rejectMessage();
+ break;
+
+ case 0x67fe:
+ displayMessage(dsAddr_troubleWithStairsMsg); // "If I put it on I might have trouble walking up the stairs"
+ break;
+
+ case 0x6911:
+ displayMessage(dsAddr_9LivesToReadMsg); // "I'd need 9 lives to read them all"
+ break;
+
+ case 0x6954:
+ displayMessage(dsAddr_thanksNotTiredMsg); // "Thanks, I'm not so tired"
+ break;
+
+ case 0x695b:
+ displayMessage(dsAddr_noNeedToTurnOnMsg); // "There's no need to turn it on"
+ break;
+
+ case 0x6ba6:
+ displayMessage(dsAddr_wontBearWeightMsg); // "It won't bear my weight"
+ break;
+
+ case 0x6bda:
+ displayMessage(dsAddr_peepingTomMsg); // "What am I? A Peeping Tom?"
+ break;
+
+ case 0x6c1c:
+ case 0x6c20:
+ rejectMessage();
+ break;
+
+ case 0x6c24:
+ displayMessage(dsAddr_dontNeedThemMsg); // "I don't need them"
+ break;
+
+ case 0x6c2b:
+ loadScene(29, Common::Point(300, 188));
+ scene->setOrientation(4);
+ break;
+
+ case 0x6c7c:
+ displayMessage(dsAddr_bigPocketsMsg); // "I have big pockets, but there are limits"
+ break;
+
+ case 0x724e:
+ displayMessage(dsAddr_soSharpMsg); // "They're so sharp they'd rip my trousers!"
+ break;
+
+ case 0x72be:
+ rejectMessage();
+ break;
+
+ case 0x7305:
+ rejectMessage();
+ break;
+
+ case 0x7328:
+ displayMessage(dsAddr_noTimeForPleasuresMsg); // "I don't have time for pleasures"
+ break;
+
+ case 0x732f:
+ displayMessage(dsAddr_notSocksWithBareHandsMsg); // "I won't touch these socks with my bare hands!"
+ break;
+
+ case 0x739c:
+ displayMessage(dsAddr_notHalloweenMsg); // "It's not Halloween"
+ break;
+
+ case 0x7401:
+ displayMessage(dsAddr_NotManualMsg); // "It can't be controlled manually! I hate it!"
+ break;
+
+ case 0x746f:
+ displayMessage(dsAddr_nothingToPlayMsg); // "I have nothing to play"
+ break;
+
+ case 0x74b3:
+ loadScene(29, Common::Point(256, 171));
+ scene->setOrientation(3);
+ break;
+
+ case 0x74cd:
+ rejectMessage();
+ break;
+
+ case 0x74f9:
+ loadScene(38, Common::Point(160, 199));
+ scene->setOrientation(1);
+ break;
+
+ case 0x784a:
+ displayMessage(dsAddr_notMineMsg); // "I can't take it. It's not mine."
+ break;
+
+ case 0x7851:
+ displayMessage(dsAddr_lockedMsg); // "It's Locked!"
+ break;
+
+ case 0x7858:
+ displayMessage(dsAddr_lockedMsg); // "It's Locked!"
+ break;
+
+ case 0x785f:
+ displayMessage(dsAddr_pullObjMsg2); // "I can't reach it"
+ break;
case 0x7866:
- if (CHECK_FLAG(0xdbdd, 3)) {
- displayMessage(0x55ff);
- return true;
- } else
- return false;
+ if (CHECK_FLAG(dsAddr_JailCableAndBowlState, 3))
+ displayMessage(dsAddr_gotchaMsg); // "Gotcha"
+ else
+ retVal = false;
+ break;
- case 0x7878: {
- byte v = res->dseg.get_byte(0xDBDB) + 1;
- if (v <= 6)
- SET_FLAG(0xDBDB, v);
+ case 0x7878:
+ {
+ byte v = res->dseg.get_byte(dsAddr_graffitiMsgId) + 1;
+ if (v <= 6)
+ SET_FLAG(dsAddr_graffitiMsgId, v);
- switch (v) {
- case 1:
- displayMessage(0x5411);
- return true;
- case 2:
- displayMessage(0x5463);
- return true;
- case 3:
- displayMessage(0x5475);
- return true;
- case 4:
- displayMessage(0x5484);
- return true;
- case 5:
- displayMessage(0x54c4);
- return true;
- default:
- displayMessage(0x54d5);
- return true;
+ switch (v) {
+ case 1:
+ displayMessage(dsAddr_SavingFineMsg); // "Saving is a very fine thing..."
+ break;
+ case 2:
+ displayMessage(dsAddr_loveCaptainMsg); // "I love captain"
+ break;
+ case 3:
+ displayMessage(dsAddr_soccerRulzMsg); // "Soccer rulz"
+ break;
+ case 4:
+ displayMessage(dsAddr_treeCutMsg); // "Don't cut the trees..."
+ break;
+ case 5:
+ displayMessage(dsAddr_visaAcceptedMsg); // "VISA Accepted"
+ break;
+ default:
+ displayMessage(dsAddr_otherGraffitiMsg); // "The rest of graffiti is obscene"
+ break;
+ }
}
- }
+ break;
case 0x78a9:
- if (CHECK_FLAG(0xDBE6, 1)) {
- displayMessage(0x5827);
- return true;
- } else
- return false;
+ if (CHECK_FLAG(dsAddr_captainDrawerState, 1))
+ displayMessage(dsAddr_nowOpenMsg); // "Now it's open"
+ else
+ retVal = false;
+ break;
case 0x78bb:
- if (CHECK_FLAG(0xDBE8, 1)) {
- displayMessage(0x58b0);
- return true;
- } else
- return false;
+ if (CHECK_FLAG(dsAddr_swappedBarmanMugFlag, 1))
+ displayMessage(dsAddr_yuckMsg); // "Yuck!"
+ else
+ retVal = false;
+ break;
case 0x78ce:
- if (!CHECK_FLAG(0xDBA1, 1)) {
- displayMessage(0x3694);
- return true;
- } else
- return false;
+ if (!CHECK_FLAG(dsAddr_mansionTreeHollowEmptyFlag, 1))
+ displayMessage(dsAddr_monstersMsg); // "Who knows what monsters live in there"
+ else
+ retVal = false;
+ break;
- case 0x792b: //left click on ann
+ case 0x792b: // left click on ann
moveTo(245, 198, 1);
- if (CHECK_FLAG(0xDBAF, 1))
- return false;
-
- Dialog::showMono(scene, 0x2193, 0, 0xd1, 0);
- SET_FLAG(0xDBAF, 1);
- return true;
+ if (!CHECK_FLAG(dsAddr_alreadySaidAnneBeautifulFlag, 1)) {
+ dialog->showMono(50, scene, 0, textColorMark, 0);
+ SET_FLAG(dsAddr_alreadySaidAnneBeautifulFlag, 1);
+ } else
+ retVal = false;
+ break;
case 0x79c3:
- if (CHECK_FLAG(0xDBA4, 1))
- return false;
- processCallback(0x61fe);
- return true;
+ if (CHECK_FLAG(dsAddr_lightOnFlag, 1))
+ retVal = false;
+ else
+ fnTooDark();
+ break;
- case 0x7b26: //cutting the fence
+ case 0x7b26: // cutting the fence
setOns(0, 0);
playSound(5, 2);
playSound(51, 11);
@@ -1114,11 +2050,11 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
setOns(0, 0x60);
moveTo(281, scene->getPosition().y, 0, true);
disableObject(4);
- SET_FLAG(0xDBE1, 1);
- return true;
+ SET_FLAG(dsAddr_cutFenceFlag, 1);
+ break;
- case 0x7b89: //digging mysterious object
- if (CHECK_FLAG(0xDBE1, 1)) {
+ case 0x7b89: // digging mysterious object
+ if (CHECK_FLAG(dsAddr_cutFenceFlag, 1)) {
playActorAnimation(844);
setOns(1, 0);
playSound(5, 5);
@@ -1130,11 +2066,15 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
setOns(1, 0x64);
playActorAnimation(845);
disableObject(3);
- inventory->add(0x52);
- inventory->remove(0x51);
+ inventory->add(kInvItemKaleidoscope);
+ inventory->remove(kInvItemShovelAct1);
} else
- displayMessage(0x56da);
- return true;
+ displayMessage(dsAddr_fenceBlocksMsg); // "The fence blocks the way"
+ break;
+
+ case 0x7bf6:
+ displayMessage(dsAddr_noDiggingKnifeMsg); // "Digging it out with the knife could take a hundred years"
+ break;
case 0x7bfd:
playSound(76, 18);
@@ -1149,7 +2089,7 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playSound(76, 63);
playActorAnimation(873);
moveTo(240, 163, 4);
- displayMessage(0x5837);
+ displayMessage(dsAddr_cmonBabyMsg); // "C'mon baby, it's all yours!"
waitLanAnimationFrame(1, 0x22);
playSound(77, 2);
playSound(77, 12);
@@ -1164,23 +2104,36 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
setLan(1, 0);
playAnimation(874, 1);
setOns(0, 0x68);
- inventory->remove(0x5b);
+ inventory->remove(kInvItemDruggedFood);
enableObject(6);
disableObject(1);
- return true;
+ break;
+
+ case 0x7cc9:
+ case 0x7cd0:
+ displayMessage(dsAddr_throwCrumbsToBirdQMsg); // "Should I throw the crumbs to the bird?"
+ break;
+
+ case 0x7cd7:
+ displayMessage(dsAddr_dontWasteCrumbs); // "I don't want to waste these tasty crumbs"
+ break;
- case 0x7ce5: //put spring on the solid ground
+ case 0x7cde:
+ displayMessage(dsAddr_mightSlipFallInMsg); // "Better not... I might slip and fall in..."
+ break;
+
+ case 0x7ce5: // put spring on the solid ground
playSound(5, 2);
playSound(19, 11);
playActorAnimation(840);
setOns(1, 0x61);
- inventory->remove(0x50);
+ inventory->remove(kInvItemSpring);
disableObject(2);
enableObject(7);
- return true;
+ break;
- case 0x7d1a: //captain's key + door
- if (res->dseg.get_byte(0xDBDF) <= 1) {
+ case 0x7d1a: // captain's key + door
+ if (res->dseg.get_byte(dsAddr_FirstActTrialState) <= 1) {
playSound(5, 2);
playSound(57, 12);
playSound(70, 19);
@@ -1198,24 +2151,23 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
wait(200);
playAnimation(0, 1);
setOns(0, 0);
- Dialog::showMono(scene, 0x63a5, 830, 0xd0, 1);
+ dialog->showMono(156, scene, 830, textColorShockedCaptain, 1);
loadScene(7, 130, 195, 2);
playMusic(4);
setLan(1, 1);
wait(100);
- Dialog::show(scene, 0x6406, 0, 832, 0xd1, 0xec, 0, 1);
+ dialog->show(157, scene, 0, 832, textColorMark, textColorCaptain, 0, 1);
//playAnimation(831, 1);
- SET_FLAG(0xDBDF, 2);
-
+ SET_FLAG(dsAddr_FirstActTrialState, 2);
} else
- displayMessage(0x52f6);
- return true;
+ displayMessage(dsAddr_nahMsg); // "Nah"
+ break;
- case 0x7e02: //tickling the captain
- if (CHECK_FLAG(0xdbe0, 1)) {
- displayMessage(0x5632);
+ case 0x7e02: // tickling the captain
+ if (CHECK_FLAG(dsAddr_AlreadyTickledCaptainFlag, 1)) {
+ displayMessage(dsAddr_doesNotWorkMsg); // "That doesn't work"
} else {
playSound(5, 6);
playSound(27, 49);
@@ -1224,37 +2176,37 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
waitAnimation();
setOns(0, 94);
- Dialog::show(scene, 0x65e9, 0, 832, 0xd1, 0xec, 0, 1);
+ dialog->show(161, scene, 0, 832, textColorMark, textColorCaptain, 0, 1);
enableObject(12);
- SET_FLAG(0xdbe0, 1);
+ SET_FLAG(dsAddr_AlreadyTickledCaptainFlag, 1);
}
- return true;
+ break;
- case 0x7e4f: //giving magazine to captain
- Dialog::show(scene, 0x66c0, 0, 856, 0xd1, 0xec, 0, 1);
+ case 0x7e4f: // giving magazine to captain
+ dialog->show(162, scene, 0, 856, textColorMark, textColorCaptain, 0, 1);
playSound(5, 3);
playActorAnimation(852, true);
playActorAnimation(853, true);
- displayMessage(0x5742);
- displayMessage(0x5757);
- displayMessage(0x5770);
- displayMessage(0x5782);
- displayMessage(0x5799);
+ displayMessage(dsAddr_whatAboutMsg); // "What about a new"
+ displayMessage(dsAddr_hotOffMsg); // "hot off the press"
+ displayMessage(dsAddr_fullColorMsg); // "full-color"
+ displayMessage(dsAddr_specialEdMsg); // "special edition"
+ displayMessage(dsAddr_soldierNewsMsg); // "of Soldier News?!"
playAnimation(856, 1);
playSound(5, 3);
//playActorAnimation(854);
- Dialog::show(scene, 0x66fe, 0, 856, 0xd1, 0xec, 0, 1);
+ dialog->show(163, scene, 0, 856, textColorMark, textColorCaptain, 0, 1);
playAnimation(855, 1);
wait(200);
moveTo(30, 181, 0);
disableObject(1);
setLan(1, 0);
- SET_FLAG(0xDBDF, 3);
- SET_FLAG(0xDBF0, 1);
+ SET_FLAG(dsAddr_FirstActTrialState, 3);
+ SET_FLAG(dsAddr_gotPasswordNeedSpeakBarmanFlag, 1);
loadScene(8, 155, 199);
- return true;
+ break;
- case 0x7fbd: //using bird & bartender
+ case 0x7fbd: // using bird & bartender
playSound(5, 3);
playActorAnimation(876);
setOns(1, 0);
@@ -1263,15 +2215,15 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playAnimation(877, 1);
playAnimation(880, 1, true);
- Dialog::show(scene, 0x6f0e, 0, 857, 0xd1, 0xef, 0, 1);
+ dialog->show(176, scene, 0, 857, textColorMark, textColorBarman, 0, 1);
setOns(2, 0x6a);
reloadLan();
playAnimation(878, 0);
- //playAnimation(879, 0); //background bartender animation
- inventory->remove(0x5c);
+ //playAnimation(879, 0); // background bartender animation
+ inventory->remove(kInvItemBird);
enableObject(1);
- SET_FLAG(0xDBE7, 1);
- return true;
+ SET_FLAG(dsAddr_birdOnBarRadioAntennaFlag, 1);
+ break;
case 0x8047:
playSound(32, 5);
@@ -1279,27 +2231,26 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playSound(52, 23);
playActorAnimation(881);
setOns(2, 0x6b);
- inventory->remove(0x56);
- inventory->add(0x55);
- SET_FLAG(0xDBE8, 1);
- return true;
+ inventory->remove(kInvItemMugOfMud);
+ inventory->add(kInvItemMug);
+ SET_FLAG(dsAddr_swappedBarmanMugFlag, 1);
+ break;
case 0x808b:
- if (CHECK_FLAG(0xDBDA, 1)) {
- //alredy shown
- displayMessage(0x53F2);
+ if (CHECK_FLAG(dsAddr_ShownPassToGuardFlag, 1)) {
+ displayMessage(dsAddr_gotPermissionMsg); // "I already got the permission"
} else {
- displayMessage(0x53DD);
+ displayMessage(dsAddr_showPapersMsg); // "Here are my papers"
playSound(5, 2);
playSound(5, 18);
playActorAnimation(810);
- Dialog::show(scene, 0x60BF, 0, 809, 0xd1, 0xd0, 0, 1);
- SET_FLAG(0xDBDA, 1);
+ dialog->show(147, scene, 0, 809, textColorMark, textColorCampGuard, 0, 1);
+ SET_FLAG(dsAddr_ShownPassToGuardFlag, 1);
}
- return true;
+ break;
- case 0x80c3: //show kaleydoscope to the guard
- Dialog::show(scene, 0x6811, 0, 809, 0xd1, 0xd0, 0, 1);
+ case 0x80c3: // show kaleidoscope to the guard
+ dialog->show(165, scene, 0, 809, textColorMark, textColorCampGuard, 0, 1);
playSound(5, 3);
playSound(5, 30);
playSound(26, 14);
@@ -1309,124 +2260,146 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playAnimation(851, 0);
playAnimation(850, 0);
reloadLan();
- inventory->add(0x53);
- inventory->remove(0x52);
+ inventory->add(kInvItemSoldierNews);
+ inventory->remove(kInvItemKaleidoscope);
enableObject(1);
- SET_FLAG(0xDBE2, 1);
- return true;
+ SET_FLAG(dsAddr_act1GuardState, 1);
+ break;
+
+ case 0x8398:
+ displayMessage(dsAddr_trySomewhereElseMsg); // "I'd better try somewhere else - I suppose this side is heavily guarded"
+ break;
+
+ case 0x85dd:
+ displayMessage(dsAddr_branchNotPaddleMsg); // "This branch is not a paddle. It doesn't even look like one"
+ break;
+
+ case 0x85e4:
+ displayMessage(dsAddr_sharpenNotPulverizeMsg); // "I needed to sharpen it, not pulverize"
+ break;
+
+ case 0x8d42:
+ displayMessage(dsAddr_bluntSickleMsg); // "The sickle is too blunt"
+ break;
- //Shore
+ case 0x8d49:
+ displayMessage(dsAddr_noChainsawFuelMsg); // "There's no fuel in the chainsaw"
+ break;
+
+ case 0x8d50:
+ displayMessage(dsAddr_thornsTooThinMsg); // "Thorns are too thin, the chainsaw is useless here"
+ break;
+
+ // Shore
case 0x5348:
- if (CHECK_FLAG(0xdb99, 1)) { //got broken paddle from boat
- displayMessage(0x351f);
+ if (CHECK_FLAG(dsAddr_alreadyGotBrokenPaddleFlag, 1)) { // got broken paddle from boat
+ displayMessage(dsAddr_boatEmptyMsg); // "There's nothing else in the boat"
} else {
- SET_FLAG(0xDB99, 1);
+ SET_FLAG(dsAddr_alreadyGotBrokenPaddleFlag, 1);
playSound(57, 6);
playActorAnimation(536);
- Dialog::showMono(scene, 0x30c3, 0, 0xd1, 0);
- inventory->add(0x8);
+ dialog->showMono(77, scene, 0, textColorMark, 0);
+ inventory->add(kInvItemBrokenPaddle);
}
- return true;
+ break;
case 0x53a1:
- if (CHECK_FLAG(0xdbb2, 1)) { //spoken to man in well
- displayMessage(0x411d);
+ if (CHECK_FLAG(dsAddr_spokenToManInWellFlag, 1)) { // spoken to man in well
+ displayMessage(dsAddr_stillThereMsg); // "Are you still there?"
} else {
- displayMessage(0x408a);
- displayMessage(0x4091, 0xe5, 52728);
- displayMessage(0x4098);
- displayMessage(0x40a7, 0xe5, 52705);
- displayMessage(0x40b6);
- displayMessage(0x40ce, 0xe5, 52652);
- displayMessage(0x40e8);
- displayMessage(0x410f, 0xe5, 52712);
+ displayMessage(dsAddr_echoMsg); // "Echo!"
+ displayMessage(dsAddr_loudEchoMsg, textColorWellEcho, 248, 164); // "ECHO!"
+ displayMessage(dsAddr_whoThereMsg); // "Who's there?!"
+ displayMessage(dsAddr_loudWhoThereMsg, textColorWellEcho, 225, 164); // "WHO'S THERE?!"
+ displayMessage(dsAddr_dontCopyMsg); // "DON'T COPY ME!"
+ displayMessage(dsAddr_loudDontCopyMsg, textColorWellEcho, 172, 164); // "DON'T COPY ME!!!"
+ displayMessage(dsAddr_throwRockMsg); // "OR I WILL THROW A ROCK DOWN THERE!"
+ displayMessage(dsAddr_orIWillMsg, textColorWellEcho, 232, 164); // "OR I WILL"
wait(100);
- displayMessage(0x4091, 0xe5, 52728);
- SET_FLAG(0xDBB2, 1);
+ displayMessage(dsAddr_loudEchoMsg, textColorWellEcho, 248, 164);
+ SET_FLAG(dsAddr_spokenToManInWellFlag, 1);
}
- return true;
+ break;
+ case 0x5458:
+ {
+ setOns(2, 0);
+ playSound(34, 7);
+ playActorAnimation(535);
+ inventory->add(kInvItemSecondFlower);
+ disableObject(1);
- case 0x5458: {
- setOns(2, 0);
- playSound(34, 7);
- playActorAnimation(535);
- inventory->add(11);
- disableObject(1);
-
- byte *scene_15_ons = scene->getOns(15); //patch ons for the scene 15
- scene_15_ons[0] = 0;
+ byte *scene_15_ons = scene->getOns(15); // patch ons for the scene 15
+ scene_15_ons[0] = 0;
- byte f = GET_FLAG(0xDB98) + 1;
- SET_FLAG(0xDB98, f);
- if (f >= 2) {
- //disable object boat for scene 15!!
- disableObject(1, 15);
+ byte f = GET_FLAG(dsAddr_flowerIsleState) + 1;
+ SET_FLAG(dsAddr_flowerIsleState, f);
+ if (f >= 2) {
+ // disable object boat for scene 15!!
+ disableObject(1, 15);
+ }
}
- }
- return true;
+ break;
- case 0x54b3: {
- setOns(1, 0);
- setOns(3, 0);
- playSound(33, 6);
- playActorAnimation(534);
- inventory->add(10);
- disableObject(2);
- setOns(1, 10);
- setOns(1, 0, 15);
- byte f = GET_FLAG(0xDB98) + 1;
- SET_FLAG(0xDB98, f);
- if (f >= 2) {
- //disable object boat for scene 15!!
- disableObject(1, 15);
+ case 0x54b3:
+ {
+ setOns(1, 0);
+ setOns(3, 0);
+ playSound(33, 6);
+ playActorAnimation(534);
+ inventory->add(kInvItemFirstFlower);
+ disableObject(2);
+ setOns(1, 10);
+ setOns(1, 0, 15);
+ byte f = GET_FLAG(dsAddr_flowerIsleState) + 1;
+ SET_FLAG(dsAddr_flowerIsleState, f);
+ if (f >= 2) {
+ // disable object boat for scene 15!!
+ disableObject(1, 15);
+ }
}
- }
- return true;
+ break;
case 0x5502:
setOns(0, 0);
loadScene(15, 115, 180, 1);
playMusic(6);
playActorAnimation(568);
- return true;
+ break;
- case 0x5561://Enter lakeside house
- moveTo(94, 115, 4); //call 557e, but it's not needed I guess
+ case 0x5561: // Enter lakeside house
+ fnEgoDefaultPosition();
loadScene(19, 223, 199, 1);
- return true;
+ break;
case 0x55a1:
- processCallback(0x557e);
+ fnEgoDefaultPosition();
rejectMessage();
- return true;
+ break;
- case 0x557e:
- if (scene->getPosition().y <= 149)
- moveTo(94, 115, 4);
- else
- moveTo(51, 149, 4);
- return true;
+ case csAddr_egoDefaultPosition:
+ fnEgoDefaultPosition();
+ break;
case 0x563b:
playSound(5, 10);
setOns(1, 0);
playActorAnimation(561);
- inventory->add(26);
+ inventory->add(kInvItemNut);
disableObject(6);
- return true;
+ break;
case 0x56f6:
playSound(32, 7);
setOns(1, 0);
playActorAnimation(626);
disableObject(12);
- inventory->add(45);
- displayMessage(0x3b04);
- return true;
+ inventory->add(kInvItemCheese);
+ displayMessage(dsAddr_foundFoodMsg); // "People leave food in unbelievable places"
+ break;
- case 0x5756://Open car door
+ case 0x5756: // Open car door
playSound(11, 4);
playActorAnimation(514);
setOns(4, 8);
@@ -1435,106 +2408,94 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
enableObject(15);
enableObject(16);
disableObject(1);
- return true;
+ break;
- case 0x5805://Enter basketball house
+ case 0x5805: // Enter basketball house
playSound(70, 6);
playActorAnimation(513);
loadScene(22, 51, 180, 2);
- return true;
+ break;
- case 0x5832://Ring doorbell
+ case 0x5832: // Ring doorbell
playActorAnimation(509);
- displayMessage(0x5dce);
- return true;
+ displayMessage(dsAddr_outOfOrderMsg); // "It's out of order"
+ break;
case 0x58a2:
- Dialog::pop(scene, 0xdaba, 0, 502, 0xd1, 0xe5, 0, 1);
- scene->getObject(13)->setName((const char *)res->dseg.ptr(0x92e5));
- return true;
+ dialog->pop(scene, dsAddr_dialogStackSonny, 0, 502, textColorMark, textColorSonny, 0, 1);
+ scene->getObject(13)->setName((const char *)res->dseg.ptr(dsAddr_scnObjNameSonny));
+ break;
- case 0x58b7://Get comb from car
+ case 0x58b7: // Get comb from car
disableObject(14);
setOns(4, 0);
playSound(5, 7);
playActorAnimation(521);
setOns(4, 0);
- inventory->add(0x6);
- return true;
+ inventory->add(kInvItemComb);
+ break;
- case 0x58df://Pull trunk lever in car
- SET_FLAG(0xDB94, 1);
+ case 0x58df: // Pull trunk lever in car
+ SET_FLAG(dsAddr_alreadyPulledTrunkReleaseLeverFlag, 1);
playSound(6, 1);
setOns(3, 6);
playActorAnimation(515);
- return true;
+ break;
- case 0x593e://Enter annes house
+ case 0x593e: // Enter annes house
playSound(89, 4);
playActorAnimation(980);
loadScene(23, 76, 199, 1);
- if (CHECK_FLAG(0xDBEE, 1))
+ if (CHECK_FLAG(dsAddr_lovestruckByAnneFlag, 1))
playMusic(7);
- return true;
+ break;
case 0x5994:
- processCallback(0x599b);
- processCallback(0x5a21);
- return true;
+ fnEnterCave();
+ break;
- case 0x599b:
- return true;
+ case csAddr_caveNOP:
+ break;
- case 0x5a21:
- loadScene(24, 230, 170, 1);
- playSound(52, 3);
- playSound(52, 7);
- playSound(52, 11);
- playSound(52, 14);
- playSound(52, 18);
- playSound(52, 21);
- playSound(52, 25);
- playActorAnimation(601);
- moveTo(230, 179, 3);
- if (!CHECK_FLAG(0xDBA4, 1))
- displayMessage(0x37ea); //it's kinda dark here
- return true;
+ case csAddr_enterCave:
+ fnEnterCave();
+ break;
case 0x5a8b:
- if (!CHECK_FLAG(0xDBAD, 1)) {
- playSound(43, 4); //grrrrrr
+ if (!CHECK_FLAG(dsAddr_dogHasBoneFlag, 1)) {
+ playSound(43, 4); // grrrrrr
playSound(42, 15);
playSound(42, 17);
playSound(42, 19);
playAnimation(656, 0);
wait(50);
- displayMessage(0x3c16);
- } else if (!CHECK_FLAG(0xDBA3, 1)) {//Dog has bone
+ displayMessage(dsAddr_goodDoggyMsg); // "I understand. Good doggy"
+ } else if (!CHECK_FLAG(dsAddr_cellarDoorOpenFlag, 1)) { // Dog has bone
playSound(28, 3);
playActorAnimation(596);
setOns(1, 30);
- SET_FLAG(0xDBA3, 1);
+ SET_FLAG(dsAddr_cellarDoorOpenFlag, 1);
enableObject(8);
} else {
setOns(1, 0);
playSound(4, 4);
playActorAnimation(597);
- SET_FLAG(0xDBA3, 0);
+ SET_FLAG(dsAddr_cellarDoorOpenFlag, 0);
disableObject(8);
- displayMessage(0x37b8);
+ displayMessage(dsAddr_wallShakenMsg); // "Wow! This must have shaken all the nearby walls!"
setOns(1, 32, 24);
enableObject(4, 24);
}
- return true;
+ break;
- case 0x5b3a://Click on dog
- Dialog::popMark(scene, 0xDB14);
- return true;
+ case 0x5b3a: // Click on dog
+ dialog->popMark(scene, dsAddr_dialogStackDog);
+ break;
- case 0x5b59: //picking up the rope
- Dialog::showMark(scene, 0x2cbd);
+ case 0x5b59: // picking up the rope
+ dialog->showMark(70, scene);
wait(150);
- Dialog::showMark(scene, 0x2dc2);
+ dialog->showMark(71, scene);
moveRel(0, -12, 0);
playSound(34, 5);
playActorAnimation(607);
@@ -1545,81 +2506,81 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playSound(5, 25);
playActorAnimation(611);
moveTo(16, scene->getPosition().y, 4, true);
- inventory->add(38);
+ inventory->add(kInvItemRopeAct2);
disableObject(12);
- return true;
+ break;
- case 0x5be1://Talk to grandpa
- Dialog::pop(scene, 0xDAC4, 0, 522, 0xd1, 0xd8, 0, 1);
- return true;
+ case 0x5be1: // Talk to grandpa
+ dialog->pop(scene, dsAddr_dialogStackGrandpa, 0, 522, textColorMark, textColorGrandpa, 0, 1);
+ break;
case 0x5bee:
playSound(89, 5);
playSound(67, 11);
playActorAnimation(982);
- displayMessage(0x5955);
- return true;
+ displayMessage(dsAddr_emptyMsg); // "It's Empty"
+ break;
- case 0x5c0d: //grandpa - drawers
- if (CHECK_FLAG(0xDBA7, 1)) {
- displayMessage(0x3bac);
+ case 0x5c0d: // grandpa - drawers
+ if (CHECK_FLAG(dsAddr_SearchedGrandpaDrawersFlag, 1)) {
+ displayMessage(dsAddr_drawersEmptyMsg); // "There's nothing else in the drawers"
} else {
- if (!CHECK_FLAG(0xDB92, 1))
- Dialog::show(scene, 0x15a0, 0, 522, 0xd1, 0xd8, 0, 1); //can I search your drawers?
+ if (!CHECK_FLAG(dsAddr_alreadyAdjustedHoopPoleFlag, 1))
+ dialog->show(24, scene, 0, 522, textColorMark, textColorGrandpa, 0, 1);
playSound(66, 5);
playSound(67, 20);
playSound(5, 23);
playActorAnimation(631);
- inventory->add(47);
- SET_FLAG(0xDBA7, 1);
+ inventory->add(kInvItemHandkerchief);
+ SET_FLAG(dsAddr_SearchedGrandpaDrawersFlag, 1);
}
- return true;
+ break;
case 0x5c84:
- if (CHECK_FLAG(0xDB92, 1)) {
- inventory->add(2);
+ if (CHECK_FLAG(dsAddr_alreadyAdjustedHoopPoleFlag, 1)) {
+ inventory->add(kInvItemShotgun);
disableObject(7);
playSound(32, 7);
setOns(0, 0);
playActorAnimation(520);
} else {
- Dialog::pop(scene, 0xDACE, 0, 522, 0xd1, 0xd8, 0, 1);
+ dialog->pop(scene, dsAddr_dialogStackGrandpaShotgun, 0, 522, textColorMark, textColorGrandpa, 0, 1);
}
- return true;
+ break;
- case 0x5cf0://Exit basketball house
+ case 0x5cf0:// Exit basketball house
playSound(88, 5);
playActorAnimation(981);
loadScene(20, 161, 165);
- return true;
+ break;
- case 0x5d24: //getting the fan
- if (CHECK_FLAG(0xDB92, 1)) {
+ case 0x5d24: // getting the fan
+ if (CHECK_FLAG(dsAddr_alreadyAdjustedHoopPoleFlag, 1)) {
setLan(2, 0);
playSound(32, 7);
playActorAnimation(508);
disableObject(13);
- inventory->add(7);
+ inventory->add(kInvItemFan);
} else {
- Dialog::pop(scene, 0xDAD4, 0, 522, 0xd1, 0xd8, 0, 1);
+ dialog->pop(scene, dsAddr_dialogStackGrandpaFan, 0, 522, textColorMark, textColorGrandpa, 0, 1);
}
- return true;
+ break;
- case 0x5e4d: //right click on ann
- if (!CHECK_FLAG(0xDB97, 0)) {
- displayMessage(0x3d59);
+ case 0x5e4d: // right click on ann
+ if (!CHECK_FLAG(dsAddr_alreadySpokenToAnneFlag, 0)) {
+ displayMessage(dsAddr_girlTalkMsg); // "I really don't know how to talk to girls"
} else {
moveTo(245, 198, 1);
- Dialog::show(scene, 0x21d7, 0, 524, 0xd1, 0xe5, 0, 2);
- //waitLanAnimationFrame(2, 1); //too long, about 200 frames! seems to be present in original game (sic)
- SET_FLAG(0xDB97, 1);
+ dialog->show(51, scene, 0, 524, textColorMark, textColorAnne, 0, 2);
+ //waitLanAnimationFrame(2, 1); // too long, about 200 frames! seems to be present in original game (sic)
+ SET_FLAG(dsAddr_alreadySpokenToAnneFlag, 1);
for (byte i = 10; i <= 20; i += 2)
playSound(13, i);
playAnimation(528, 1);
wait(50);
playMusic(7);
- SET_FLAG(0xDBEE, 1);
+ SET_FLAG(dsAddr_lovestruckByAnneFlag, 1);
for (byte i = 3; i <= 17; i += 2)
playSound(56, i);
playActorAnimation(525);
@@ -1633,163 +2594,146 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playSound(55, 5);
playActorAnimation(527);
wait(50);
- Dialog::show(scene, 0x2219, 0, 524, 0xd1, 0xe5, 0, 2);
- scene->getObject(2)->setName((const char *)res->dseg.ptr(0x9820));
+ dialog->show(52, scene, 0, 524, textColorMark, textColorAnne, 0, 2);
+ scene->getObject(2)->setName((const char *)res->dseg.ptr(dsAddr_scnObjNameAnne));
}
- return true;
+ break;
- case 0x5f73: //exiting ann's house
- if (CHECK_FLAG(0xDBEE, 1))
+ case 0x5f73: // exiting ann's house
+ if (CHECK_FLAG(dsAddr_lovestruckByAnneFlag, 1))
playMusic(6);
loadScene(21, 99, 180, 3);
- return true;
+ break;
case 0x5fba:
- if (CHECK_FLAG(0xDBB1, 1)) {
- displayMessage(0x4380);
+ if (CHECK_FLAG(dsAddr_nutSwappedForAppleFlag, 1)) {
+ displayMessage(dsAddr_noFruitMsg); // "There are no more interesting fruits here"
} else {
- Dialog::pop(scene, 0xDAFC, 0, 523, 0xd1, 0xe5, 0, 1);
+ dialog->pop(scene, dsAddr_dialogStackGetAppleOldLady, 0, 523, textColorMark, textColorOldLady, 0, 1);
}
- return true;
+ break;
case 0x607f:
- return processCallback(0x60b5);
+ fnEgoScaredBySpider();
+ break;
case 0x6083:
- if (CHECK_FLAG(0xDBA4, 1)) {
+ if (CHECK_FLAG(dsAddr_lightOnFlag, 1)) {
setOns(0, 0);
playSound(56, 10);
playActorAnimation(599);
- inventory->add(37);
+ inventory->add(kInvItemShovelAct2);
disableObject(2);
} else
- processCallback(0x60b5);
- return true;
+ fnEgoScaredBySpider();
+ break;
- case 0x60b5:
- if (CHECK_FLAG(0xDBAE, 1)) {
- processCallback(0x60d9);
- Dialog::showMark(scene, 0x2fdd);
- } else {
- Dialog::showMark(scene, 0x2e41);
- processCallback(0x60d9);
- wait(100);
- Dialog::showMark(scene, 0x2e6d);
- }
- return true;
+ case csAddr_egoScaredBySpider:
+ fnEgoScaredBySpider();
+ break;
- case 0x60d9: {
- Object *obj = scene->getObject(3);
- moveTo(obj);
- processCallback(0x612b);
- moveTo(48, 190, 3);
- }
- return true;
+ case csAddr_moveToLadderAndLeaveCellar:
+ fnMoveToLadderAndLeaveCellar();
+ break;
- case 0x612b:
- playSound(52, 10);
- playSound(52, 14);
- playSound(52, 18);
- playSound(52, 21);
- playSound(52, 25);
- playSound(52, 28);
- playSound(52, 32);
- playActorAnimation(600);
- loadScene(21, 297, 178, 3);
- return true;
+ case csAddr_leaveCellar:
+ fnLeaveCellar();
+ break;
case 0x6176:
- if (CHECK_FLAG(0xDBA4, 1)) {
- displayMessage(0x3801);
- return true;
+ if (CHECK_FLAG(dsAddr_lightOnFlag, 1)) {
+ displayMessage(dsAddr_notInDarkMsg); // "I'm not going to wander here in the dark again"
+ } else {
+ playSound(71, 6);
+ playActorAnimation(598);
+ loadScene(24, scene->getPosition());
+ setOns(2, 0);
+ setLan(1, 0);
+ playAnimation(660, 0);
+ disableObject(1);
+ SET_FLAG(dsAddr_lightOnFlag, 1);
+ loadScene(24, scene->getPosition());
}
- playSound(71, 6);
- playActorAnimation(598);
- loadScene(24, scene->getPosition());
- setOns(2, 0);
- setLan(1, 0);
- playAnimation(660, 0);
- disableObject(1);
- SET_FLAG(0xDBA4, 1);
- loadScene(24, scene->getPosition());
-
- return true;
+ break;
case 0x61e9:
- if (CHECK_FLAG(0xDBA4, 1)) {
- Dialog::popMark(scene, 0xdb1e);
- } else
- processCallback(0x61fe);
+ if (CHECK_FLAG(dsAddr_lightOnFlag, 1))
+ dialog->popMark(scene, dsAddr_dialogStackTakeAxe);
+ else
+ fnTooDark();
+ break;
- return true;
+ case csAddr_TooDark:
+ displayMessage(dsAddr_TooDarkMsg); // "It's too dark to see clearly"
+ break;
- case 0x6229: //shelves in cellar
- if (CHECK_FLAG(0xDBA4, 1)) {
+ case 0x6229: // shelves in cellar
+ if (CHECK_FLAG(dsAddr_lightOnFlag, 1)) {
Common::Point p = scene->getPosition();
- byte v = GET_FLAG(0xDBB4);
+ byte v = GET_FLAG(dsAddr_cellarShelfExamineCount);
switch (v) {
case 0:
- displayMessage(0x4532);
+ displayMessage(dsAddr_whatGotMsg); // "Let's look what we've got here"
moveRel(-34, 0, 1);
- displayMessage(0x4555);
+ displayMessage(dsAddr_strawberryJamMsg); // "Strawberry jam"
moveRel(20, 0, 1);
- displayMessage(0x4568);
+ displayMessage(dsAddr_gooseberryJamMsg); // "Gooseberry jam"
moveRel(20, 0, 1);
- displayMessage(0x457b);
+ displayMessage(dsAddr_blackberryJamMsg); // "Blackberry jam"
moveRel(20, 0, 1);
- displayMessage(0x458e);
+ displayMessage(dsAddr_bilberryJamMsg); // "Bilberry jam"
moveTo(p, 3);
- displayMessage(0x459f);
- SET_FLAG(0xDBB4, 1);
+ displayMessage(dsAddr_getMeOutJamMsg); // "Get me out of this jam!"
+ SET_FLAG(dsAddr_cellarShelfExamineCount, 1);
break;
case 1:
- displayMessage(0x45b8);
+ displayMessage(dsAddr_rosemaryJamMsg); // "Oh, and there is Rosemary jam"
wait(100);
- displayMessage(0x45da);
- SET_FLAG(0xDBB4, 2);
+ displayMessage(dsAddr_knowRosemaryMsg); // "I used to know someone called Rosemary"
+ SET_FLAG(dsAddr_cellarShelfExamineCount, 2);
break;
default:
- displayMessage(0x4603);
+ displayMessage(dsAddr_unwantedJamsMsg); // "I don't want those jams"
+ break;
}
} else
- processCallback(0x61fe);
-
- return true;
+ fnTooDark();
+ break;
- case 0x6480: //dive mask
- if (CHECK_FLAG(0xDB96, 1)) {
+ case 0x6480: // dive mask
+ if (CHECK_FLAG(dsAddr_birdsGoneFromScarecrowFlag, 1)) {
playSound(56, 7);
playSound(5, 15);
playActorAnimation(613);
setOns(3, 36);
- inventory->add(39);
+ inventory->add(kInvItemMask);
disableObject(5);
- displayMessage(0x387c);
+ displayMessage(dsAddr_needSunglassesMsg); // "Sorry buddy, but I need your sunglasses"
} else
- displayMessage(0x3eb2);
- return true;
+ displayMessage(dsAddr_crowKillMsg); // "I'm sure these crows will kill me"
+ break;
- case 0x64c4: //flippers
- if (CHECK_FLAG(0xDB96, 1)) {
+ case 0x64c4: // flippers
+ if (CHECK_FLAG(dsAddr_birdsGoneFromScarecrowFlag, 1)) {
setOns(2, 35);
playSound(63, 8);
playSound(24, 10);
playActorAnimation(612);
- inventory->add(40);
+ inventory->add(kInvItemFins);
disableObject(6);
} else
- displayMessage(0x3eb2);
- return true;
+ displayMessage(dsAddr_crowKillMsg); // "I'm sure these crows will kill me"
+ break;
- case 0x7907://Describe car lever
- if (CHECK_FLAG(0xdb94, 1)) {//Already pulled lever?
- displayMessage(0x3e4f);
- return true;
+ case 0x7907: // Describe car lever
+ if (CHECK_FLAG(dsAddr_alreadyPulledTrunkReleaseLeverFlag, 1)) { // Already pulled lever?
+ displayMessage(dsAddr_openBootMsg); // "It opens the boot"
} else
- return false;
+ retVal = false;
+ break;
- case 0x62d0://Get bone from under rock
- displayAsyncMessage(0x463c, 30938, 16, 24);
+ case 0x62d0: // Get bone from under rock
+ displayAsyncMessage(dsAddr_yeowMsg, 218, 96, 16, 24); // "YEEEOOOWWWW!"
playSound(26, 6);
playSound(26, 10);
playSound(24, 13);
@@ -1798,35 +2742,34 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playActorAnimation(594);
setOns(0, 29);
disableObject(1);
- inventory->add(36);
+ inventory->add(kInvItemBone);
playSound(5, 2);
playActorAnimation(595);
- displayMessage(0x3790);
- return true;
+ displayMessage(dsAddr_dinoBoneMsg); // "I really hope this is DINOSAUR bone"
+ break;
case 0x6351:
- if (CHECK_FLAG(0xdaca, 1)) { //cave bush is cut down
+ if (CHECK_FLAG(dsAddr_caveThornsCutDownFlag, 1)) { // cave bush is cut down
playMusic(8);
loadScene(26, 319, 169, 4);
} else
- displayMessage(0x3bd2);
- return true;
+ displayMessage(dsAddr_ridBushMsg); // "I must get rid of this bush first"
+ break;
case 0x63ea:
playSound(5, 10);
setOns(0, 0);
playActorAnimation(640);
- inventory->add(50);
+ inventory->add(kInvItemNugget);
disableObject(6);
- return true;
+ break;
- case 0x6411://Kick hen
- if (CHECK_FLAG(0xdb93, 1)) { //already kicked hen
- displayMessage(0x3e08);
- return true;
+ case 0x6411: // Kick hen
+ if (CHECK_FLAG(dsAddr_alreadyKickedHenFlag, 1)) { // already kicked hen
+ displayMessage(dsAddr_ridFrustationsMsg); // "I'd already got rid of my frustrations"
} else {
- SET_FLAG(0xdb93, 1);
- displayMessage(0x3dc6);
+ SET_FLAG(dsAddr_alreadyKickedHenFlag, 1);
+ displayMessage(dsAddr_henFlyMsg); // "I wonder if hens can fly. Come here, baby"
waitLanAnimationFrame(1, 87);
playSound(30, 26);
playSound(29, 49);
@@ -1835,198 +2778,191 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
waitAnimation();
setOns(0, 1);
enableObject(14);
- displayMessage(0x3df4);
- return true;
+ displayMessage(dsAddr_firstTestFailMsg); // "First test failed"
}
+ break;
- case 0x6592: //Rake
+ case 0x6592: // Rake
setOns(1, 0);
playSound(18, 10);
playActorAnimation(553);
- inventory->add(0x15);
+ inventory->add(kInvItemRakeBroken);
wait(50);
- displayMessage(0x3605);
+ displayMessage(dsAddr_trousersMsg); // "Good I always asked mum for trousers with BIG pockets"
disableObject(11);
- return true;
+ break;
case 0x66b5:
playSound(89, 5);
playActorAnimation(969);
loadScene(33, 319, 181, 4);
- return true;
+ break;
- case 0x6519://Sickle
+ case 0x6519: // Sickle
setOns(4, 0);
playSound(5, 11);
playActorAnimation(625);
- inventory->add(0x2c);
+ inventory->add(kInvItemSickleBlunt);
disableObject(8);
- return true;
+ break;
- case 0x655b://Get needle from haystack
- if (CHECK_FLAG(0xdb9d, 1)) { //already have needle
- displayMessage(0x356a);
- return true;
+ case 0x655b: // Get needle from haystack
+ if (CHECK_FLAG(dsAddr_gotNeedleAlreadyFlag, 1)) { // already have needle
+ displayMessage(dsAddr_dontPushLuckMsg); // "I don't think I should push my luck"
} else {
- SET_FLAG(0xdb9d, 1);
+ SET_FLAG(dsAddr_gotNeedleAlreadyFlag, 1);
playSound(49, 3);
playActorAnimation(548);
- inventory->add(0x11);
- displayMessage(0x35b2);
- return true;
+ inventory->add(kInvItemNeedle);
+ displayMessage(dsAddr_needleHaystackMsg); // "And they say you can't find a needle in a haystack"
}
+ break;
- case 0x663c://Feather
+ case 0x663c: // Feather
setOns(0, 0);
playSound(5, 9);
playActorAnimation(511);
- inventory->add(1);
+ inventory->add(kInvItemFeather);
disableObject(15);
- return true;
+ break;
case 0x667c:
playSound(70, 4);
playActorAnimation(972);
loadScene(29, 160, 199, 1);
- return true;
+ break;
case 0x66a9:
- displayMessage(0x4a7e);
+ displayMessage(dsAddr_dontLeaveMansionMsg); // "I don't want to leave the mansion, I want blood!"
disableObject(4);
- return true;
+ break;
case 0x66e2:
playSound(88, 4);
playActorAnimation(970);
loadScene(35, 160, 199, 1);
- return true;
+ break;
case 0x70bb:
- Dialog::pop(scene, 0xdb24, 0, 709, 0xd1, 0xef, 0, 1);
- return true;
+ dialog->pop(scene, dsAddr_dialogStackBusyCook, 0, 709, textColorMark, textColorCook, 0, 1);
+ break;
case 0x71ae:
- if (CHECK_FLAG(0xDBCD, 1)) {
- if (CHECK_FLAG(0xDBCE, 1)) {
- displayMessage(0x4f9b);
+ if (CHECK_FLAG(dsAddr_MansionRadioBrokenFlag, 1)) {
+ if (CHECK_FLAG(dsAddr_MansionGotRadioBatteriesFlag, 1)) {
+ displayMessage(dsAddr_restUselessMsg); // "The rest is useless"
} else {
- displayMessage(0x4fb1);
+ displayMessage(dsAddr_twoBatteriesMsg); // "Wow! Two 1.5V batteries!"
playSound(32, 6);
playActorAnimation(717);
- inventory->add(66);
- SET_FLAG(0xDBCE, 1);
+ inventory->add(kInvItemBatteries);
+ SET_FLAG(dsAddr_MansionGotRadioBatteriesFlag, 1);
}
} else
- Dialog::showMark(scene, 0x3c9d);
- return true;
+ dialog->showMark(97, scene);
+ break;
case 0x70c8:
- if (!processCallback(0x70e0))
- return true;
- moveTo(81, 160, 4);
- displayMessage(0x5cac);
- return true;
-
- case 0x70e0:
- if (!CHECK_FLAG(0xDBCC, 1)) {
- displayMessage(0x4ece);
- return false;
+ if (fnIsCookGone()) {
+ moveTo(81, 160, 4);
+ displayMessage(dsAddr_cognacMsg); // "Pfui! The cognac really didn't do any good"
}
- return true;
+ break;
+
+ case csAddr_isCookGone:
+ retVal = fnIsCookGone();
+ break;
case 0x70ef:
- if (!processCallback(0x70e0))
- return true;
- displayMessage(0x5046);
- return true;
+ if (fnIsCookGone())
+ displayMessage(dsAddr_tooHotMsg); // "It's too hot to touch!"
+ break;
case 0x70f9:
- if (inventory->has(68)) {
- inventory->remove(68);
+ if (inventory->has(kInvItemBurningPaper)) {
+ inventory->remove(kInvItemBurningPaper);
loadScene(29, 40, 176, 2);
- displayMessage(0x500a);
+ displayMessage(dsAddr_paperBurntMsg); // "The paper burnt out completely!"
} else
loadScene(29, 40, 176, 2);
- return true;
+ break;
case 0x712c:
- if (!processCallback(0x70e0))
- return true;
-
- if (CHECK_FLAG(0xDBCF, 1)) {
- playSound(89, 4);
- playActorAnimation(719);
- setOns(4, 67);
- ++ *res->dseg.ptr(READ_LE_UINT16(res->dseg.ptr(0x6746 + (scene->getId() - 1) * 2)));
- disableObject(5);
- enableObject(12);
- } else {
- playSound(89, 4);
- playSound(89, 4);
- playSound(87, 45);
- displayAsyncMessage(0x4fcb, 34672, 11, 35, 0xe5);
- playActorAnimation(718);
- wait(100);
- displayMessage(0x4fe2);
- SET_FLAG(0xDBCF, 1);
+ if (fnIsCookGone()) {
+ if (CHECK_FLAG(dsAddr_MansionHaveOpenedFridgeBeforeFlag, 1)) {
+ playSound(89, 4);
+ playActorAnimation(719);
+ setOns(4, 67);
+ ++ *res->dseg.ptr(READ_LE_UINT16(res->dseg.ptr(dsAddr_sceneWalkboxTablePtr + (scene->getId() - 1) * 2)));
+ disableObject(5);
+ enableObject(12);
+ } else {
+ playSound(89, 4);
+ playSound(89, 4);
+ playSound(87, 45);
+ displayAsyncMessage(dsAddr_oneTakenMsg, 112, 108, 11, 35, textColorEskimo); // "This one's taken, OK?"
+ playActorAnimation(718);
+ wait(100);
+ displayMessage(dsAddr_slightMadMsg); // "It finally happened. I'm slightly mad"
+ SET_FLAG(dsAddr_MansionHaveOpenedFridgeBeforeFlag, 1);
+ }
}
- return true;
+ break;
case 0x71eb:
setOns(2, 0);
playSound(32, 7);
playActorAnimation(710);
- inventory->add(62);
+ inventory->add(kInvItemChilliWithLabel);
disableObject(7);
enableObject(8);
- return true;
+ break;
case 0x7244:
- if (!processCallback(0x70e0))
- return true;
- displayMessage(0x5c60);
- return true;
+ if (fnIsCookGone())
+ displayMessage(dsAddr_neverLearntMsg); // "I never learnt to how use one"
+ break;
case 0x7255:
- if (CHECK_FLAG(0xDBD0, 1)) {
+ if (CHECK_FLAG(dsAddr_MansionPutBurningPaperInFridgeFlag, 1)) {
setOns(4, 69);
playSound(32, 5);
playActorAnimation(725);
disableObject(12);
- inventory->add(69);
+ inventory->add(kInvItemMeat);
} else {
playActorAnimation(721);
- displayMessage(0x505e);
+ displayMessage(dsAddr_frozenShelfMsg); // "It has frozen hard onto the shelf!"
}
- return true;
+ break;
case 0x721c:
setOns(3, 0);
playSound(32, 7);
playActorAnimation(715);
- inventory->add(63);
+ inventory->add(kInvItemPastryRoller);
disableObject(9);
- return true;
+ break;
case 0x7336:
setOns(1, 0);
playSound(5, 42);
- displayAsyncMessage(0x4d02, 32642, 20, 38);
+ displayAsyncMessage(dsAddr_noDepraveMsg, 2, 102, 20, 38); // "Nah, I don't want to deprave the kids"
playActorAnimation(697);
- inventory->add(56);
+ inventory->add(kInvItemCognac);
disableObject(1);
- return true;
+ break;
case 0x7381:
playSound(5, 12);
playActorAnimation(704);
disableObject(2);
- inventory->add(58);
- return true;
+ inventory->add(kInvItemIceTongs);
+ break;
case 0x7408:
- if (CHECK_FLAG(0xDBC4, 1)) {
- displayMessage(0x4d2a);
+ if (CHECK_FLAG(dsAddr_mansionReadNewspaperFlag, 1)) {
+ displayMessage(dsAddr_noReadAgainMsg); // "I don't want to read it again. I might like it."
} else {
setOns(0, 0);
playSound(26, 17);
@@ -2038,45 +2974,45 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playActorAnimation(698);
setOns(0, 52);
setOns(2, 61);
- Dialog::showMark(scene, 0x38b6);
+ dialog->showMark(92, scene);
enableObject(11);
- SET_FLAG(0xDBC4, 1);
+ SET_FLAG(dsAddr_mansionReadNewspaperFlag, 1);
}
- return true;
+ break;
case 0x7476:
- if (CHECK_FLAG(0xDBC9, 1)) {
- displayMessage(0x4dbb);
+ if (CHECK_FLAG(dsAddr_mansionExaminedCouchBeforeFlag, 1)) {
+ displayMessage(dsAddr_noSleepMsg); // "I don't want to sleep"
} else {
- SET_FLAG(0xDBC9, 1);
- Dialog::showMark(scene, 0x3aca);
+ SET_FLAG(dsAddr_mansionExaminedCouchBeforeFlag, 1);
+ dialog->showMark(94, scene);
playSound(61, 5);
playSound(5, 14);
playActorAnimation(705);
- displayMessage(0x4dd3);
- inventory->add(59);
+ displayMessage(dsAddr_justCorkMsg); // "It's just a cork"
+ inventory->add(kInvItemCork);
}
- return true;
+ break;
case 0x74d1:
setOns(2, 0);
playSound(5, 12);
playActorAnimation(699);
- inventory->add(57);
+ inventory->add(kInvItemRemoteControl);
disableObject(11);
- return true;
+ break;
- case 0x7513: //fatso + doctor: pre-final
- if (CHECK_FLAG(0xDBD7, 1)) {
- if (CHECK_FLAG(0xDBD8, 1)) {
+ case 0x7513: // fatso + doctor: pre-final
+ if (CHECK_FLAG(dsAddr_MansionThruFanByTimePillFlag, 1)) {
+ if (CHECK_FLAG(dsAddr_MansionVentFanStoppedFlag, 1)) {
playSound(88, 4);
playActorAnimation(979);
loadScene(37, 51, 183);
- Dialog::show(scene, 0x54ea, 768, 769, 0xd9, 0xe5, 1, 2);
+ dialog->show(125, scene, 768, 769, textColorMansionGuard, textColorProfessor, 1, 2);
playAnimation(770, 0, true, true, true);
playAnimation(771, 1, true, true, true);
- Dialog::showMono(scene, 0x5523, 0, 0xd1, 0);
+ dialog->showMono(126, scene, 0, textColorMark, 0);
playAnimation(770, 0, true, true, true);
playAnimation(771, 1, true, true, true);
playSound(5, 3);
@@ -2090,11 +3026,11 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
waitAnimation();
setOns(0, 74);
hideActor();
- Dialog::showMono(scene, 0x5556, 775, 0xd0, 1);
+ dialog->showMono(127, scene, 775, textColorJohnNoty, 1);
playAnimation(771, 1, true, true, true);
playAnimation(776, 0);
- Dialog::show(scene, 0x55f7, 777, 778, 0xd0, 0xe5, 1, 2); //i have to kill you anyway
+ dialog->show(128, scene, 777, 778, textColorJohnNoty, textColorProfessor, 1, 2);
playAnimation(779, 0, true, true, true);
playAnimation(780, 1, true, true, true);
@@ -2151,7 +3087,7 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
setOns(0, 80);
playAnimation(792, 3, true, true, true);
- Dialog::show(scene, 0x5665, 0, 791, 0xd1, 0xd0, 0, 4);
+ dialog->show(129, scene, 0, 791, textColorMark, textColorJohnNoty, 0, 4);
playAnimation(792, 3, true, true, true);
moveTo(40, 171, 4);
@@ -2161,43 +3097,47 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playAnimation(0, 3);
loadScene(31, 298, 177, 4);
- SET_FLAG(0xDBD9, 1);
- } else {
- displayMessage(0x52fe);
- }
+ SET_FLAG(dsAddr_MansionJohnNotyEscapingFlag, 1);
+ } else
+ displayMessage(dsAddr_ventFirstMsg); // "I'd better stop this ventilator first"
} else
- displayMessage(0x52cb);
- return true;
+ displayMessage(dsAddr_noSaladMsg); // "I don't want to turn myself into a salad"
+ break;
case 0x783d:
- Dialog::pop(scene, 0xdb36, 0, 797, 0xd1, 0xd0, 0, 1);
- return true;
+ dialog->pop(scene, dsAddr_dialogStackJohnNotyEndgame, 0, 797, textColorMark, textColorJohnNoty, 0, 1);
+ break;
case 0x7966:
- if (CHECK_FLAG(0xDBA4, 1))
- return false;
- return processCallback(0x60b5);
+ if (CHECK_FLAG(dsAddr_lightOnFlag, 1))
+ retVal = false;
+ else
+ fnEgoScaredBySpider();
+ break;
case 0x7ad0:
case 0x7ad7:
- return !processCallback(0x70e0);
+ retVal = !fnIsCookGone();
+ break;
case 0x7ab9:
- if (CHECK_FLAG(0xDBB6, 1))
- return false;
- Dialog::showMono(scene, 0x37d0, 0, 0xd1, 0);
- SET_FLAG(0xDBB6, 1);
- return true;
+ if (CHECK_FLAG(dsAddr_vgaArtistQuipAlreadySaidFlag, 1))
+ retVal = false;
+ else {
+ dialog->showMono(90, scene, 0, textColorMark, 0);
+ SET_FLAG(dsAddr_vgaArtistQuipAlreadySaidFlag, 1);
+ }
+ break;
case 0x7ade:
- if (CHECK_FLAG(0xdbcd, 1)) {
- displayMessage(0x4f69);
- return true;
- } else
- return false;
+ if (CHECK_FLAG(dsAddr_MansionRadioBrokenFlag, 1))
+ displayMessage(dsAddr_whatInsideMsg); // "I was always curious what's inside these things"
+ else
+ retVal = false;
+ break;
- case 0x7f23://Use grenade on captains drawer
- if (CHECK_FLAG(0xDBDF, 3)) {
+ case 0x7f23: // Use grenade on captains drawer
+ if (CHECK_FLAG(dsAddr_FirstActTrialState, 3)) {
enableOn(false);
playSound(5, 3);
playSound(58, 11);
@@ -2207,123 +3147,120 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playActorAnimation(870);
playSound(54, 15);
playActorAnimation(871);
- SET_FLAG(0xDBE6, 1);
+ SET_FLAG(dsAddr_captainDrawerState, 1);
setOns(1, 0x66);
moveTo(224, 194, 0, true);
- displayCutsceneMessage(0x57df, 30423);
- inventory->remove(0x59);
+ displayCutsceneMessage(dsAddr_cutsceneMsg1, 23, 95); // "sixty seven rude words later"
+ inventory->remove(kInvItemRopeAndGrenade);
enableOn(true);
- } else {
- displayMessage(0x5de2);
- }
- return true;
+ } else
+ displayMessage(dsAddr_captainWatchingMsg); // "with captain watching? Better not"
+ break;
- case 0x505c: {
- //suspicious stuff
- Common::Point p = scene->getPosition();
- if (p.x != 203 && p.y != 171)
- moveTo(203, 169, 2);
- else
- moveTo(203, 169, 1);
- }
- return true;
+ case csAddr_egoSuspiciousPosition:
+ fnEgoSuspiciousPosition();
+ break;
case 0x509a:
- processCallback(0x505c);
+ fnEgoSuspiciousPosition();
setOns(1, 0);
playSound(5, 10);
playActorAnimation(543);
- inventory->add(15);
+ inventory->add(kInvItemBranch);
disableObject(9);
- return true;
+ break;
case 0x7802:
- if (CHECK_FLAG(0xDBD7, 1)) {
- if (CHECK_FLAG(0xDBD8, 1))
- displayMessage(0x52f6);
+ if (CHECK_FLAG(dsAddr_MansionThruFanByTimePillFlag, 1)) {
+ if (CHECK_FLAG(dsAddr_MansionVentFanStoppedFlag, 1))
+ displayMessage(dsAddr_nahMsg); // "Nah"
else {
playSound(71, 4);
playActorAnimation(796);
setLan(1, 0);
- SET_FLAG(0xDBD8, 1);
+ SET_FLAG(dsAddr_MansionVentFanStoppedFlag, 1);
}
} else
- displayMessage(0x52cb);
- return true;
+ displayMessage(dsAddr_noSaladMsg); // "I don't want to turn myself into a salad"
+ break;
case 0x78e0:
- processCallback(0x505c);
- return false;
+ fnEgoSuspiciousPosition();
+ retVal = false;
+ break;
case 0x78e7:
- processCallback(0x557e);
- return false;
-
case 0x78ee:
- processCallback(0x557e);
- return false;
+ fnEgoDefaultPosition();
+ retVal = false;
+ break;
case 0x78f5:
- if (CHECK_FLAG(0xDB95, 1)) {
- displayMessage(0x3E75);
- return true;
+ if (CHECK_FLAG(dsAddr_carTrunkEmptyFlag, 1)) {
+ displayMessage(dsAddr_bootEmptyMsg); // "There's nothing else in the boot"
} else
- return false;
+ retVal = false;
+ break;
case 0x7919:
- if (!CHECK_FLAG(0xDBA5, 1))
- return false;
- displayMessage(0x3E98);
- return true;
+ if (!CHECK_FLAG(dsAddr_laundryState, 1))
+ retVal = false;
+ else
+ displayMessage(dsAddr_clothesDryMsg); // "The clothes are dry now."
+ break;
case 0x7950:
- if (!CHECK_FLAG(0xDBB1, 1))
- return false;
-
- displayMessage(0x3DAF);
- return true;
+ if (CHECK_FLAG(dsAddr_nutSwappedForAppleFlag, 1))
+ displayMessage(dsAddr_nutRealMsg); // "Only the nut is real"
+ else
+ retVal = false;
+ break;
case 0x7975:
- if (CHECK_FLAG(0xDBA4, 1))
- return false;
- displayMessage(0x3832);
- return true;
+ if (CHECK_FLAG(dsAddr_lightOnFlag, 1))
+ retVal = false;
+ else
+ displayMessage(dsAddr_shutValveMsg); // "Shutting the valve shook the dirt from the wall..."
+ break;
case 0x7987:
case 0x7996:
case 0x79a5:
case 0x79b4:
- if (CHECK_FLAG(0xDBA4, 1))
- return false;
- return processCallback(0x61fe);
+ if (CHECK_FLAG(dsAddr_lightOnFlag, 1))
+ retVal = false;
+ else
+ fnTooDark();
+ break;
case 0x79d2:
- if (!CHECK_FLAG(0xDB9D, 1))
- return false;
- displayMessage(0x3590);
- return true;
+ if (!CHECK_FLAG(dsAddr_gotNeedleAlreadyFlag, 1))
+ retVal = false;
+ else
+ displayMessage(dsAddr_ordinaryHaystackMsg); // "Just an ordinary hay stack. Now."
+ break;
case 0x7af0:
- if (!processCallback(0x70e0))
- return true;
- return false;
+ if (fnIsCookGone())
+ retVal = false;
+ break;
case 0x8117:
- Dialog::show(scene, 0x0a41, 0, 529, 0xd1, 0xd9, 0, 1);
+ dialog->show(9, scene, 0, 529, textColorMark, textColorMansionGuard, 0, 1);
playSound(5, 2);
playSound(5, 44);
playAnimation(642, 0, true);
playActorAnimation(641, true);
waitAnimation();
- Dialog::show(scene, 0x0aff, 0, 529, 0xd1, 0xd9, 0, 1);
+ dialog->show(10, scene, 0, 529, textColorMark, textColorMansionGuard, 0, 1);
wait(170);
- Dialog::show(scene, 0x0ba0, 0, 529, 0xd1, 0xd9, 0, 1);
+ dialog->show(11, scene, 0, 529, textColorMark, textColorMansionGuard, 0, 1);
moveRel(0, 1, 0);
wait(100);
- Dialog::show(scene, 0x0c10, 0, 529, 0xd1, 0xd9, 0, 1);
- inventory->remove(50);
- processCallback(0x9d45);
- return true;
+ dialog->show(12, scene, 0, 529, textColorMark, textColorMansionGuard, 0, 1);
+ inventory->remove(kInvItemNugget);
+ fnMansionIntrusionAttempt();
+ break;
case 0x8174:
setOns(0, 0);
@@ -2336,7 +3273,7 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
setOns(1, 15);
disableObject(3);
enableObject(9);
- return true;
+ break;
case 0x81c2:
playSound(56, 11);
@@ -2353,12 +3290,12 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playActorAnimation(588, true);
waitAnimation();
wait(50);
- displayMessage(0x367f);
- inventory->remove(34);
- SET_FLAG(0xDBA1, 1);
- return true;
+ displayMessage(dsAddr_itsGoneMsg); // "At least it's gone"
+ inventory->remove(kInvItemPaintedPotato);
+ SET_FLAG(dsAddr_mansionTreeHollowEmptyFlag, 1);
+ break;
- case 0x823d: //grappling hook on the wall
+ case 0x823d: // grappling hook on the wall
playSound(5, 3);
for (byte i = 16; i <= 28; i += 2)
playSound(65, i);
@@ -2367,27 +3304,26 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
for (byte i = 3; i <= 18; i += 3)
playSound(56, i);
- displayAsyncMessage(0x3ace, 3878, 20, 37, 0xd9);
+ displayAsyncMessage(dsAddr_heyLetGoMsg, 38, 12, 20, 37, textColorMansionGuard); // "Hey, let go, will ya?!"
playActorAnimation(621, true);
playAnimation(623, 1, true);
waitAnimation();
- displayAsyncMessage(0x3ae6, 3870, 1, 9, 0xd9);
+ displayAsyncMessage(dsAddr_aaahhhMsg, 30, 12, 1, 9, textColorMansionGuard); // "Aaaaaaaaaaaaahhh!"
playSound(35, 1);
playActorAnimation(622, true);
playAnimation(624, 0, true);
waitAnimation();
wait(150);
- displayMessage(0x3afd);
-
- inventory->remove(43);
- processCallback(0x9d45);
- return true;
+ displayMessage(dsAddr_oopsMsg); // "Oops"
+ inventory->remove(kInvItemGrapplingHook);
+ fnMansionIntrusionAttempt();
+ break;
- case 0x8312: //hedgehog + plastic apple
- Dialog::showMark(scene, 0x3000);
+ case 0x8312: // hedgehog + plastic apple
+ dialog->showMark(76, scene);
setLan(1, 0);
playSound(5, 24);
playSound(26, 32);
@@ -2405,13 +3341,13 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
waitAnimation();
disableObject(6);
- displayMessage(0x363f);
- inventory->remove(27);
- inventory->add(28);
- return true;
+ displayMessage(dsAddr_lifeIsBrutalMsg); // "Life is brutal"
+ inventory->remove(kInvItemPlasticApple);
+ inventory->add(kInvItemCone);
+ break;
case 0x839f:
- inventory->remove(32);
+ inventory->remove(kInvItemDart);
playSound(37, 14);
playSound(16, 17);
playActorAnimation(564, true);
@@ -2437,10 +3373,10 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playSound(55, 18);
playAnimation(581, 1);
disableObject(2);
- SET_FLAG(0xDB9F, 1);
- return true;
+ SET_FLAG(dsAddr_beesGoneFlag, 1);
+ break;
- case 0x84c7: //using paddle on boat
+ case 0x84c7: // using paddle on boat
playSound(20, 9);
playActorAnimation(530);
loadScene(16, 236, 95, 1);
@@ -2451,12 +3387,12 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playActorAnimation(533);
setOns(0, 9);
moveTo(236, 95, 1, true);
- return true;
+ break;
- case 0x8538://Sharpen sickle on well
+ case 0x8538: // Sharpen sickle on well
moveTo(236, 190, 0);
setOns(2, 0);
- //TODO: Remove handle sprite
+ // FIXME: Add code to Remove handle sprite (visible GFX glitch)
playSound(5, 4);
playSound(14, 14);
playSound(14, 33);
@@ -2464,52 +3400,58 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playActorAnimation(643);
setOns(2, 43);
moveTo(236, 179, 3);
- inventory->remove(0x2c);
- inventory->add(0x2e);
- return true;
+ inventory->remove(kInvItemSickleBlunt);
+ inventory->add(kInvItemSickleSharp);
+ break;
+
+ case 0x85d6:
+ displayMessage(dsAddr_paddleBrokenMsg); // "The paddle is BROKEN"
+ break;
case 0x85eb:
- if (CHECK_FLAG(0xDBB0, 1)) {
+ if (CHECK_FLAG(dsAddr_squirrelNutState, 1)) {
enableObject(6);
playSound(25, 10);
playSound(25, 14);
playSound(25, 18);
playActorAnimation(559);
setOns(1, 23);
- SET_FLAG(0xDBB0, 2);
+ SET_FLAG(dsAddr_squirrelNutState, 2);
} else
- displayMessage(0x3d86);
-
- return true;
+ displayMessage(dsAddr_dontWorkPurposeMsg); // "I usually don't work without a purpose"
+ break;
case 0x863d:
playSound(12, 4);
playSound(50, 20);
playSound(50, 29);
playActorAnimation(554);
- inventory->remove(19);
- inventory->add(22);
- return true;
+ inventory->remove(kInvItemChocCandy);
+ inventory->add(kInvItemHeartShapedCandy);
+ break;
case 0x8665:
playSound(5, 3);
for (byte i = 12; i <= 24; i += 2)
playSound(56, i);
playActorAnimation(567);
- inventory->remove(12);
- inventory->add(33);
- return true;
+ inventory->remove(kInvItemFeatherDusterClean);
+ inventory->add(kInvItemFeatherDusterDirty);
+ break;
case 0x862c:
- displayMessage(CHECK_FLAG(0xDBB0, 1) ? 0x4882 : 0x3457);
- return true;
+ if (CHECK_FLAG(dsAddr_squirrelNutState, 1))
+ displayMessage(dsAddr_nutRakeMsg); // "It's pointless, the nut will slip between the rake's teeth"
+ else
+ displayMessage(dsAddr_objErrorMsg); // "That's no good"
+ break;
- case 0x86a9: //correcting height of the pole with spanner
- if (CHECK_FLAG(0xDB92, 1)) {
- displayMessage(0x3d40);
+ case 0x86a9: // correcting height of the pole with spanner
+ if (CHECK_FLAG(dsAddr_alreadyAdjustedHoopPoleFlag, 1)) {
+ displayMessage(dsAddr_noNeedMsg); // "No need to do it again"
} else {
- SET_FLAG(0xDB92, 1);
- Dialog::show(scene, 0x0fcd, 0, 502, 0xd0, 0xe5, 0, 1);
+ SET_FLAG(dsAddr_alreadyAdjustedHoopPoleFlag, 1);
+ dialog->show(17, scene, 0, 502, textColorMark, textColorSonny, 0, 1);
waitLanAnimationFrame(1, 7);
playSound(5, 16);
playSound(1, 25);
@@ -2528,7 +3470,7 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playSound(5, 43);
playSound(61, 70);
playSound(61, 91);
- displayAsyncMessage(0x3cfb, 28877, 6, 17);
+ displayAsyncMessage(dsAddr_ConfusionMsg, 77, 90, 6, 17); // "!?&!"
playActorAnimation(505, true);
playAnimation(507, 0, true);
waitAnimation();
@@ -2552,8 +3494,8 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
disableObject(15);
disableObject(16);
moveTo(162, 164, 2);
- displayMessage(0x3d01, 0xe5, 24390);
- displayMessage(0x3d20, 0xd8, 24410);
+ displayMessage(dsAddr_grandpaPromiseMsg, textColorSonny, 70, 76); // "But grandpa, you promised!"
+ displayMessage(dsAddr_ohLetsGoMsg, textColorGrandpa, 90, 76); // "Oh all right. Let's go"
moveTo(162, 191, 2);
setOns(1, 0);
setOns(2, 0);
@@ -2572,133 +3514,118 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playAnimation(512, 0);
wait(100);
- displayMessage(0x3d3a);
+ displayMessage(dsAddr_byeMsg); // "Bye."
{
Object *obj = scene->getObject(7);
- obj->actor_rect.left = obj->actor_rect.right = 228;
- obj->actor_rect.top = obj->actor_rect.bottom = 171;
- obj->actor_rect.save();
+ obj->actorRect.left = obj->actorRect.right = 228;
+ obj->actorRect.top = obj->actorRect.bottom = 171;
+ obj->actorRect.save();
}
{
Object *obj = scene->getObject(8);
- obj->actor_rect.left = obj->actor_rect.right = 290;
- obj->actor_rect.top = obj->actor_rect.bottom = 171;
- obj->actor_rect.save();
+ obj->actorRect.left = obj->actorRect.right = 290;
+ obj->actorRect.top = obj->actorRect.bottom = 171;
+ obj->actorRect.save();
}
}
- return true;
+ break;
- case 0x88c9: //give flower to old lady
- if (CHECK_FLAG(0xDB9A, 1))
- return processCallback(0x890b);
-
- inventory->remove(10);
- SET_FLAG(0xDB9A, 1);
- processCallback(0x88DE);
- return true;
-
- case 0x88de:
- playSound(5, 2);
- Dialog::show(scene, 0x1B5F, 0, 523, 0xd1, 0xe5, 0, 1);
- playActorAnimation(537, true);
- playAnimation(538, 0, true);
- waitAnimation();
- wait(100);
- Dialog::show(scene, 0x1BE0, 0, 523, 0xd1, 0xe5, 0, 1);
- return true;
+ case 0x88c9: // give flower to old lady
+ if (CHECK_FLAG(dsAddr_givenFlowerToOldLadyAlreadyFlag, 1))
+ fnGiveAnotherFlowerToOldLady();
+ else {
+ inventory->remove(kInvItemFirstFlower);
+ SET_FLAG(dsAddr_givenFlowerToOldLadyAlreadyFlag, 1);
+ fnGivingFlowerToOldLady();
+ }
+ break;
- case 0x890b:
- Dialog::pop(scene, 0xDAF0, 0, 523, 0xd1, 0xe5, 0, 1);
- return true;
+ case csAddr_givingFlowerToOldLady:
+ fnGivingFlowerToOldLady();
+ break;
- case 0x8918://give flower to old lady
- if (CHECK_FLAG(0xDB9A, 1))
- return processCallback(0x890B);
+ case csAddr_giveAnotherFlowerToOldLady:
+ fnGiveAnotherFlowerToOldLady();
+ break;
- inventory->remove(11);
- SET_FLAG(0xDB9A, 1);
- processCallback(0x88DE);
- return true;
+ case 0x8918: // give flower to old lady
+ if (CHECK_FLAG(dsAddr_givenFlowerToOldLadyAlreadyFlag, 1))
+ fnGiveAnotherFlowerToOldLady();
+ else {
+ inventory->remove(kInvItemSecondFlower);
+ SET_FLAG(dsAddr_givenFlowerToOldLadyAlreadyFlag, 1);
+ fnGivingFlowerToOldLady();
+ }
+ break;
case 0x892d:
- if (CHECK_FLAG(0xDB9B, 1))
- return processCallback(0x89aa);
+ if (CHECK_FLAG(dsAddr_givenFlowerToAnneAlreadyFlag, 1))
+ fnGiveAnotherFlowerToAnne();
+ else {
+ fnGivingFlowerToAnne();
+ inventory->remove(kInvItemFirstFlower);
+ SET_FLAG(dsAddr_givenFlowerToAnneAlreadyFlag, 1);
+ }
+ break;
- processCallback(0x8942);
- inventory->remove(10);
- SET_FLAG(0xDB9B, 1);
- return true;
+ case csAddr_givingFlowerToAnne:
+ fnGivingFlowerToAnne();
+ break;
- case 0x8942:
- Dialog::show(scene, 0x2293, 0, 524, 0xd1, 0xe5, 0, 2);
- playSound(5, 10);
- playActorAnimation(540, true);
- playAnimation(539, 1, true);
- waitAnimation();
- wait(100);
- Dialog::show(scene, 0x24b1, 0, 524, 0xd1, 0xe5, 0, 2);
- wait(50);
- Dialog::show(scene, 0x24d7, 0, 524, 0xd1, 0xe5, 0, 2);
- Dialog::show(scene, 0x2514, 0, 524, 0xd1, 0xe5, 0, 2);
- wait(50);
- moveRel(0, 1, 0);
- Dialog::show(scene, 0x2570, 0, 524, 0xd1, 0xe5, 0, 2);
- moveRel(0, -1, 0);
- wait(50);
- return true;
-
- case 0x89aa:
- Dialog::pop(scene, 0xdb02, 0, 524, 0xd1, 0xe5, 0, 2);
- return true;
+ case csAddr_giveAnotherFlowerToAnne:
+ fnGiveAnotherFlowerToAnne();
+ break;
case 0x89b7:
- if (CHECK_FLAG(0xDB9B, 1))
- return processCallback(0x89aa);
-
- processCallback(0x8942);
- inventory->remove(11);
- SET_FLAG(0xDB9B, 1);
- return true;
+ if (CHECK_FLAG(dsAddr_givenFlowerToAnneAlreadyFlag, 1))
+ fnGiveAnotherFlowerToAnne();
+ else {
+ fnGivingFlowerToAnne();
+ inventory->remove(kInvItemSecondFlower);
+ SET_FLAG(dsAddr_givenFlowerToAnneAlreadyFlag, 1);
+ }
+ break;
case 0x89cc:
- inventory->remove(23);
+ inventory->remove(kInvItemWrappedCandy);
playSound(5, 6);
- Dialog::show(scene, 0x2634, 0, 524, 0xd1, 0xe5, 0, 2);
+ dialog->show(60, scene, 0, 524, textColorMark, textColorAnne, 0, 2);
+ // FIXME - Dialog #61 not explicitly called. Does Dialog #60 run on somehow?
playActorAnimation(555, true);
playAnimation(556, 1, true);
waitAnimation();
playActorAnimation(557, true);
playAnimation(558, 1, true);
waitAnimation();
- Dialog::show(scene, 0x2971, 0, 524, 0xd1, 0xe5, 0, 2);
- inventory->add(24);
- return true;
+ dialog->show(62, scene, 0, 524, textColorMark, textColorAnne, 0, 2);
+ inventory->add(kInvItemRibbon);
+ break;
case 0x8a22:
playSound(45, 16);
playActorAnimation(560);
- inventory->remove(26);
- inventory->add(27);
+ inventory->remove(kInvItemNut);
+ inventory->add(kInvItemPlasticApple);
wait(50);
- Dialog::show(scene, 0x1ecd, 0, 523, 0xd1, 0xe5, 0, 1);
- Dialog::show(scene, 0x1f09, 0, 523, 0xd1, 0xe5, 0, 1);
- SET_FLAG(0xDBB1, 1);
- return true;
-
- case 0x8a6f: //banknote + ann
- if (CHECK_FLAG(0xDBB5, 1)) {
- Dialog::show(scene, 0x2992, 0, 524, 0xd1, 0xe5, 0, 2);
+ dialog->show(44, scene, 0, 523, textColorMark, textColorOldLady, 0, 1);
+ dialog->show(45, scene, 0, 523, textColorMark, textColorOldLady, 0, 1);
+ SET_FLAG(dsAddr_nutSwappedForAppleFlag, 1);
+ break;
+
+ case 0x8a6f: // banknote + ann
+ if (CHECK_FLAG(dsAddr_examinedBanknoteFlag, 1)) {
+ dialog->show(63, scene, 0, 524, textColorMark, textColorAnne, 0, 2);
playSound(5, 3);
playSound(5, 20);
playAnimation(671, 1, true);
playActorAnimation(670, true);
waitAnimation();
//playAnimation(672, 1);
- Dialog::show(scene, 0x2a00, 524, 672, 0xd1, 0xe5, 0, 2);
+ dialog->show(64, scene, 524, 672, textColorMark, textColorAnne, 0, 2);
//playAnimation(672, 1);
playSound(83, 12);
- displayAsyncMessage(0x4a5b, 36684, 23, 38, 0xe5);
+ displayAsyncMessage(dsAddr_hundredBucksMsg, 204, 114, 23, 38, textColorAnne); // "A hundred bucks!!!"
playActorAnimation(673);
loadScene(11, scene->getPosition());
playSound(24, 31);
@@ -2710,14 +3637,14 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
loadScene(28, 0, 167, 2);
playMusic(10);
moveTo(66, 167, 2);
- displayMessage(0x4a6f);
+ displayMessage(dsAddr_wantBloodMsg); // "I want Blood!"
inventory->clear();
- inventory->add(29);
+ inventory->add(kInvItemSuperGlue);
} else
- displayMessage(0x4a29);
- return true;
+ displayMessage(dsAddr_showHerMoneyMsg); // "If I just show her the money, she might take it"
+ break;
- case 0x8b82: //use fan on laundry
+ case 0x8b82: // use fan on laundry
setOns(0, 0);
playSound(5, 3);
playSound(5, 6);
@@ -2725,16 +3652,16 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playSound(92, 20);
playSound(92, 38);
playSound(92, 58);
- displayAsyncMessage(0x464a, 36510, 58, 67);
+ displayAsyncMessage(dsAddr_yawnMsg, 30, 114, 58, 67); // "(yawn)"
playActorAnimation(602);
playSound(5, 3);
playActorAnimation(603);
setOns(0, 27);
- SET_FLAG(0xDBA5, 1);
- return true;
+ SET_FLAG(dsAddr_laundryState, 1);
+ break;
- case 0x8bfc://Give bone to dog
- displayMessage(0x3c31);
+ case 0x8bfc: // Give bone to dog
+ displayMessage(dsAddr_hereBoyMsg); // "Here, boy"
playSound(5, 3);
playSound(26, 13);
playActorAnimation(657, true);
@@ -2744,20 +3671,20 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
reloadLan();
playAnimation(659, 0);
- inventory->remove(36);
- SET_FLAG(0xDBAD, 1);
+ inventory->remove(kInvItemBone);
+ SET_FLAG(dsAddr_dogHasBoneFlag, 1);
{
Object *o = scene->getObject(7);
- o->actor_rect.left = o->actor_rect.right = 297;
- o->actor_rect.top = o->actor_rect.bottom = 181;
- o->actor_orientation = 1;
+ o->actorRect.left = o->actorRect.right = 297;
+ o->actorRect.top = o->actorRect.bottom = 181;
+ o->actorOrientation = 1;
o->save();
}
{
Object *o = scene->getObject(9);
- o->actor_rect.left = o->actor_rect.right = 297;
- o->actor_rect.top = o->actor_rect.bottom = 181;
- o->actor_orientation = 1;
+ o->actorRect.left = o->actorRect.right = 297;
+ o->actorRect.top = o->actorRect.bottom = 181;
+ o->actorOrientation = 1;
o->save();
}
{
@@ -2767,10 +3694,10 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
w->save();
}
wait(100);
- displayMessage(0x3c3d);
- return true;
+ displayMessage(dsAddr_friendsNowMsg); // "I hope we're friends now"
+ break;
- case 0x8c6e://Use car jack on rock
+ case 0x8c6e: // Use car jack on rock
playSound(5, 3);
playSound(26, 13);
playSound(24, 22);
@@ -2782,10 +3709,10 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playActorAnimation(593);
setOns(0, 28);
enableObject(1);
- inventory->remove(35);
- return true;
+ inventory->remove(kInvItemCarJack);
+ break;
- case 0x8cc8://Cut bush with sickle
+ case 0x8cc8: // Cut bush with sickle
playSound(5, 3);
playActorAnimation(644);
setOns(1, 45);
@@ -2799,16 +3726,16 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playActorAnimation(646);
playSound(5, 21);
playActorAnimation(647);
- SET_FLAG(0xdaca, 1);
- inventory->remove(0x2e);
+ SET_FLAG(dsAddr_caveThornsCutDownFlag, 1);
+ inventory->remove(kInvItemSickleSharp);
disableObject(2);
- scene->getObject(3)->actor_rect.right = 156;
+ scene->getObject(3)->actorRect.right = 156;
scene->getObject(3)->save();
- return true;
+ break;
- case 0x8d79: //mouse falls back from the hole (cave)
- if (CHECK_FLAG(0, 1)) {
- inventory->add(48);
+ case csAddr_mouseOutOfHoleTimeout: // mouse falls back from the hole (cave)
+ if (CHECK_FLAG(dsAddr_timedCallbackState, 1)) {
+ inventory->add(kInvItemMouse);
playSound(24, 26);
playActorAnimation(650, true);
playAnimation(651, 2, true);
@@ -2824,54 +3751,26 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playActorAnimation(654, true);
playAnimation(655, 2, true);
waitAnimation();
- displayMessage(0x3bf6);
- inventory->add(49);
+ displayMessage(dsAddr_mouseGoneMsg); // "The mouse has gone!"
+ inventory->add(kInvItemRock);
setLan(2, 4, 27);
enableObject(4, 27);
- SET_FLAG(0xdba9, 0);
+ SET_FLAG(dsAddr_mouseHoleState, 0);
}
- SET_FLAG(0, 0);
- return true;
+ SET_FLAG(dsAddr_timedCallbackState, 0);
+ break;
- case 0x8d57:
- if (CHECK_FLAG(0, 0)) {
- playSound(5, 2);
- playSound(15, 12);
- playActorAnimation(638);
- inventory->remove(48);
- setTimerCallback(0x8d79, 100);
- SET_FLAG(0, 1);
- } else if (CHECK_FLAG(0, 1)) {
- playSound(5, 2);
- playSound(52, 13);
- playActorAnimation(648);
- setOns(1, 46);
- inventory->remove(49);
- setTimerCallback(0x8d79, 100);
- SET_FLAG(0, 2);
- } else if (CHECK_FLAG(0, 2)) {
- playActorAnimation(649);
- setOns(1, 47);
- wait(300);
- for (byte i = 1; i <= 37; i += 4)
- playSound(68, i);
- playAnimation(639, 2);
- setOns(0, 42);
- enableObject(6);
- disableObject(5);
- SET_FLAG(0xDBAB, 1);
- SET_FLAG(0, 0);
- setTimerCallback(0, 0);
- }
- return true;
+ case csAddr_putRockInHole:
+ fnPutRockInHole();
+ break;
case 0x8f1d:
- Dialog::showMark(scene, 0x2dd6);
+ dialog->showMark(72, scene);
for (uint i = 16; i <= 30; i += 2)
playSound(56, i);
playSound(2, 64);
playSound(3, 74);
- displayAsyncMessage(0x34c7, 25812, 35, 50);
+ displayAsyncMessage(dsAddr_lastChanceMsg, 212, 80, 35, 50); // "Last chance?"
playActorAnimation(516, true);
playAnimation(517, 2, true);
playAnimation(518, 3, true);
@@ -2880,12 +3779,12 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
setLan(4, 0);
disableObject(2);
disableObject(3);
- inventory->remove(2);
- SET_FLAG(0xDB96, 1);
- return true;
+ inventory->remove(kInvItemShotgun);
+ SET_FLAG(dsAddr_birdsGoneFromScarecrowFlag, 1);
+ break;
case 0x8fc8:
- displayMessage(0x3b2f);
+ displayMessage(dsAddr_comeHereMsg); // "Come here, I've got something for you"
waitLanAnimationFrame(2, 4);
playSound(5, 3);
playActorAnimation(627, true);
@@ -2894,25 +3793,25 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playSound(41, 10);
playSound(41, 47);
playSound(55, 52);
- if (CHECK_FLAG(0xDBA8, 1)) {
+ if (CHECK_FLAG(dsAddr_HankerchiefInMouseholeFlag, 1)) {
setLan(2, 0);
playActorAnimation(628, true);
playAnimation(634, 1, true);
waitAnimation();
disableObject(4);
- displayMessage(0x3b6c);
- SET_FLAG(0xDBA9, 1);
+ displayMessage(dsAddr_trappedMouseMsg); // "The mouse is trapped!"
+ SET_FLAG(dsAddr_mouseHoleState, 1);
} else {
playActorAnimation(628, true);
playAnimation(630, 1, true);
waitAnimation();
- displayMessage(0x3b59);
+ displayMessage(dsAddr_cantCatchMsg); // "I can't catch it!"
}
- return true;
+ break;
- case 0x9054: //mouse hole
- if (CHECK_FLAG(0xDBAB, 1)) {
- displayMessage(0x3c0b);
+ case 0x9054: // mouse hole
+ if (CHECK_FLAG(dsAddr_mouseGotGoldNuggetFlag, 1)) {
+ displayMessage(dsAddr_nonsenseMsg); // "Nonsense"
} else {
playSound(5, 11);
playSound(49, 21);
@@ -2920,50 +3819,48 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
setOns(5, 40);
moveTo(239, 139, 0, true);
playActorAnimation(633);
- SET_FLAG(0xDBA8, 1);
- inventory->remove(47);
- if (!CHECK_FLAG(0xDBAA, 1)) {
- SET_FLAG(0xDBAA, 1);
- displayMessage(0x3b8b);
+ SET_FLAG(dsAddr_HankerchiefInMouseholeFlag, 1);
+ inventory->remove(kInvItemHandkerchief);
+ if (!CHECK_FLAG(dsAddr_mouseNerveMsgSaidFlag, 1)) {
+ SET_FLAG(dsAddr_mouseNerveMsgSaidFlag, 1);
+ displayMessage(dsAddr_mouseNerveMsg); // "Boy, this mouse has some nerve!"
}
}
- return true;
+ break;
case 0x933d:
- if (!processCallback(0x70e0))
- return true;
-
- if (CHECK_FLAG(0xdbcd, 1)) {
- displayMessage(0x4f3d);
- return true;
+ if (fnIsCookGone()) {
+ if (CHECK_FLAG(dsAddr_MansionRadioBrokenFlag, 1))
+ displayMessage(dsAddr_breakFlattenMsg); // "I wanted to break it, not to flatten it!"
+ else {
+ setOns(1, 0);
+ playSound(5, 3);
+ playSound(5, 33);
+ playSound(24, 13);
+ playSound(24, 19);
+ playSound(24, 23);
+ playSound(24, 26);
+ playSound(24, 29);
+ playSound(23, 21);
+ playSound(74, 25);
+ playActorAnimation(716);
+ setOns(1, 66);
+ SET_FLAG(dsAddr_MansionRadioBrokenFlag, 1);
+ }
}
+ break;
- setOns(1, 0);
- playSound(5, 3);
- playSound(5, 33);
- playSound(24, 13);
- playSound(24, 19);
- playSound(24, 23);
- playSound(24, 26);
- playSound(24, 29);
- playSound(23, 21);
- playSound(74, 25);
- playActorAnimation(716);
- setOns(1, 66);
- SET_FLAG(0xDBCD, 1);
- return true;
-
- case 0x93af: //sheet + hot plate
- if (!processCallback(0x70e0))
- return true;
- playSound(5, 3);
- playSound(86, 11);
- playActorAnimation(720);
- inventory->add(68);
- inventory->remove(55);
- return true;
+ case 0x93af: // sheet + hot plate
+ if (fnIsCookGone()) {
+ playSound(5, 3);
+ playSound(86, 11);
+ playActorAnimation(720);
+ inventory->add(kInvItemBurningPaper);
+ inventory->remove(kInvItemSheetOfPaper);
+ }
+ break;
- case 0x93d5: //burning sheet + plate
+ case 0x93d5: // burning sheet + plate
setOns(4, 0);
playSound(87, 7);
playActorAnimation(722);
@@ -2971,323 +3868,298 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playSound(88, 12);
playSound(87, 24);
playActorAnimation(723);
- displayMessage(0x502b);
+ displayMessage(dsAddr_burnBabyMsg); // "Burn, baby, burn!"
wait(100);
playSound(89, 4);
playActorAnimation(724);
setOns(4, 68);
- displayMessage(0x503e);
- inventory->remove(68);
- SET_FLAG(0xDBD0, 1);
- return true;
-
- case 0x98fa://Right click to open toolbox
- inventory->remove(3);
- inventory->add(4);
- inventory->add(35);
+ displayMessage(dsAddr_voilaMsg); // "Voila"
+ inventory->remove(kInvItemBurningPaper);
+ SET_FLAG(dsAddr_MansionPutBurningPaperInFridgeFlag, 1);
+ break;
+
+ case csAddr_openFullToolbox: // Right click to open toolbox
+ inventory->remove(kInvItemToolboxFull);
+ inventory->add(kInvItemToolboxHalfEmpty);
+ inventory->add(kInvItemCarJack);
inventory->activate(false);
inventory->resetSelectedObject();
- displayMessage(0x3468);
- return true;
+ displayMessage(dsAddr_carJackMsg); // "Wow! There's a car jack inside! Great!"
+ break;
- case 0x9910:
- inventory->remove(4);
- inventory->add(5);
+ case csAddr_openHalfEmptyToolbox:
+ inventory->remove(kInvItemToolboxHalfEmpty);
+ inventory->add(kInvItemSpanner);
inventory->activate(false);
inventory->resetSelectedObject();
- displayMessage(0x3490);
- return true;
+ displayMessage(dsAddr_spannerMsg); // "There's something else inside the toolbox! A spanner!"
+ break;
-
- //very last part of the game:
- case 0x671d:
+ case 0x671d: // very last part of the game
moveTo(153, 163, 4);
playActorAnimation(973);
- if (CHECK_FLAG(0xDBC1, 0)) {
- SET_FLAG(0xDBC1, _rnd.getRandomNumber(5) + 1);
+ if (CHECK_FLAG(dsAddr_drawerPuzzleBookValue, 0)) {
+ SET_FLAG(dsAddr_drawerPuzzleBookValue, _rnd.getRandomNumber(5) + 1);
}
loadScene(30, 18, 159, 2);
- return true;
+ break;
case 0x67a6:
loadScene(29, 149, 163, 1);
playActorAnimation(974);
moveTo(160, 188, 0);
- return true;
+ break;
case 0x6805:
- processCallback(0x6849);
+ fnEgoBottomRightTurn();
playSound(32, 12);
playActorAnimation(694);
playSound(15, 8);
playAnimation(693, 0);
setOns(6, 0);
- displayMessage(0x4cc7);
- inventory->add(54);
+ displayMessage(dsAddr_fullAutomaticMsg); // "Fully Automatic"
+ inventory->add(kInvItemVideoTape);
disableObject(4);
- return true;
+ break;
- case 0x6849: {
- Common::Point p = scene->getPosition();
- if (p.x == 208 && p.y == 151) {
- moveRel(0, 0, 2);
- } else
- moveTo(208, 151, 1);
- }
- return true;
+ case csAddr_egoBottomRightTurn:
+ fnEgoBottomRightTurn();
+ break;
- case 0x687a: //using the book
- if (CHECK_FLAG(0xDBC2, 1)) {
- displayMessage(0x4ca0);
+ case 0x687a: // using the book
+ if (CHECK_FLAG(dsAddr_drawerPuzzleSolvedFlag, 1)) {
+ displayMessage(dsAddr_dontMessMsg); // "I don't need to mess with it anymore"
} else {
playSound(49, 5);
playSound(49, 17);
playActorAnimation(691);
- if (!processCallback(0x68e6)) {
- if (!CHECK_FLAG(0xDBC0, 1)) {
- displayMessage(0x4c61);
- SET_FLAG(0xDBC0, 1);
+ if (!fnCheckingDrawers()) {
+ if (!CHECK_FLAG(dsAddr_drawerPuzzleBookMessageFlag, 1)) {
+ displayMessage(dsAddr_bookHeldMsg); // "Something's got hold of the book!"
+ SET_FLAG(dsAddr_drawerPuzzleBookMessageFlag, 1);
}
} else {
- playSound(15, 8); //secret compartment
+ playSound(15, 8); // secret compartment
playAnimation(692, 0);
setOns(6, 59);
enableObject(4);
- displayMessage(0x4c84);
- SET_FLAG(0xDBC2, 1);
+ displayMessage(dsAddr_secretCompartmentMsg); // "Wow! A secret compartment!"
+ SET_FLAG(dsAddr_drawerPuzzleSolvedFlag, 1);
}
}
- return true;
+ break;
- case 0x68e6: { //checking drawers
- uint16 v = GET_FLAG(0xDBC1) - 1;
- uint bx = 0xDBB7;
- if (GET_FLAG(bx + v) != 1)
- return false;
-
- uint16 sum = 0;
- for (uint i = 0; i < 6; ++i) {
- sum += GET_FLAG(bx + i);
- }
- return sum == 1;
- }
+ case csAddr_checkingDrawers:
+ fnCheckingDrawers();
+ break;
case 0x6918:
- if (inventory->has(55)) {
- displayMessage(0x4cd9);
- return true;
- }
- if (!CHECK_FLAG(0xDBC3, 1)) {
- playActorAnimation(695);
- Dialog::showMark(scene, 0x386a);
- SET_FLAG(0xDBC3, 1);
- }
+ if (inventory->has(kInvItemSheetOfPaper))
+ displayMessage(dsAddr_noMoreSheetsMsg); // "Right now I don't need any more sheets"
+ else {
+ if (!CHECK_FLAG(dsAddr_mansionTrashcanSearchedFlag, 1)) {
+ playActorAnimation(695);
+ dialog->showMark(91, scene);
+ SET_FLAG(dsAddr_mansionTrashcanSearchedFlag, 1);
+ }
- playSound(5, 11);
- playActorAnimation(696);
- inventory->add(55);
- return true;
+ playSound(5, 11);
+ playActorAnimation(696);
+ inventory->add(kInvItemSheetOfPaper);
+ }
+ break;
case 0x6962:
- if (CHECK_FLAG(0xDBB7, 1)) {
+ if (CHECK_FLAG(dsAddr_blueDrawerOpenFlag, 1)) {
setOns(0, 0);
playSound(67, 4);
playActorAnimation(678);
- SET_FLAG(0xDBB7, 0);
- } else if (CHECK_FLAG(0xDBB8, 1)) {
- processCallback(0x6b86);
+ SET_FLAG(dsAddr_blueDrawerOpenFlag, 0);
+ } else if (CHECK_FLAG(dsAddr_redDrawerOpenFlag, 1)) {
+ fnDrawerOpenMessage();
} else {
playSound(66, 4);
playActorAnimation(677);
setOns(0, 53);
- SET_FLAG(0xDBB7, 1);
+ SET_FLAG(dsAddr_blueDrawerOpenFlag, 1);
}
- return true;
+ break;
case 0x69b8:
- if (CHECK_FLAG(0xDBB8, 1)) {
+ if (CHECK_FLAG(dsAddr_redDrawerOpenFlag, 1)) {
setOns(1, 0);
playSound(67, 4);
playActorAnimation(680);
- SET_FLAG(0xDBB8, 0);
- } else if (CHECK_FLAG(0xDBB7, 1)) {
- processCallback(0x6b86);
- } else if (CHECK_FLAG(0xDBB9, 1)) {
- processCallback(0x6b86);
+ SET_FLAG(dsAddr_redDrawerOpenFlag, 0);
+ } else if (CHECK_FLAG(dsAddr_blueDrawerOpenFlag, 1)) {
+ fnDrawerOpenMessage();
+ } else if (CHECK_FLAG(dsAddr_greyDrawerOpenFlag, 1)) {
+ fnDrawerOpenMessage();
} else {
playSound(66, 5);
playActorAnimation(679);
setOns(1, 54);
- SET_FLAG(0xDBB8, 1);
+ SET_FLAG(dsAddr_redDrawerOpenFlag, 1);
}
- return true;
+ break;
case 0x6a1b:
- if (CHECK_FLAG(0xDBB9, 1)) {
+ if (CHECK_FLAG(dsAddr_greyDrawerOpenFlag, 1)) {
setOns(2, 0);
playSound(67, 5);
playActorAnimation(682);
- SET_FLAG(0xDBB9, 0);
- } else if (CHECK_FLAG(0xDBB8, 1)) {
- processCallback(0x6b86);
+ SET_FLAG(dsAddr_greyDrawerOpenFlag, 0);
+ } else if (CHECK_FLAG(dsAddr_redDrawerOpenFlag, 1)) {
+ fnDrawerOpenMessage();
} else {
playSound(67, 5);
playActorAnimation(681);
setOns(2, 55);
- SET_FLAG(0xDBB9, 1);
+ SET_FLAG(dsAddr_greyDrawerOpenFlag, 1);
}
- return true;
+ break;
case 0x6a73:
- if (CHECK_FLAG(0xDBBA, 1)) {
+ if (CHECK_FLAG(dsAddr_greenDrawerOpenFlag, 1)) {
setOns(3, 0);
playSound(67, 4);
playActorAnimation(684);
- SET_FLAG(0xDBBA, 0);
- } else if (!CHECK_FLAG(0xDBBB, 1)) {
+ SET_FLAG(dsAddr_greenDrawerOpenFlag, 0);
+ } else if (!CHECK_FLAG(dsAddr_brownDrawerOpenFlag, 1)) {
playSound(66, 4);
playActorAnimation(683);
setOns(3, 56);
- SET_FLAG(0xDBBA, 1);
+ SET_FLAG(dsAddr_greenDrawerOpenFlag, 1);
} else
- processCallback(0x6b86);
- return true;
+ fnDrawerOpenMessage();
+ break;
case 0x6acb:
- if (CHECK_FLAG(0xDBBB, 1)) {
+ if (CHECK_FLAG(dsAddr_brownDrawerOpenFlag, 1)) {
setOns(4, 0);
playSound(67, 4);
playActorAnimation(686);
- SET_FLAG(0xDBBB, 0);
- } else if (CHECK_FLAG(0xDBBA, 1)) {
- processCallback(0x6b86);
- } else if (CHECK_FLAG(0xDBBC, 1)) {
- processCallback(0x6b86);
+ SET_FLAG(dsAddr_brownDrawerOpenFlag, 0);
+ } else if (CHECK_FLAG(dsAddr_greenDrawerOpenFlag, 1)) {
+ fnDrawerOpenMessage();
+ } else if (CHECK_FLAG(dsAddr_pinkDrawerOpenFlag, 1)) {
+ fnDrawerOpenMessage();
} else {
playSound(66, 5);
playActorAnimation(685);
setOns(4, 57);
- SET_FLAG(0xDBBB, 1);
+ SET_FLAG(dsAddr_brownDrawerOpenFlag, 1);
}
- return true;
+ break;
case 0x6b2e:
- if (CHECK_FLAG(0xdbbc, 1)) {
+ if (CHECK_FLAG(dsAddr_pinkDrawerOpenFlag, 1)) {
setOns(5, 0);
playSound(67, 5);
playActorAnimation(688);
- SET_FLAG(0xdbbc, 0);
- } else if (CHECK_FLAG(0xdbbb, 1)) {
- processCallback(0x6b86);
+ SET_FLAG(dsAddr_pinkDrawerOpenFlag, 0);
+ } else if (CHECK_FLAG(dsAddr_brownDrawerOpenFlag, 1)) {
+ fnDrawerOpenMessage();
} else {
playSound(66, 6);
playActorAnimation(687);
setOns(5, 58);
- SET_FLAG(0xDBBC, 1);
+ SET_FLAG(dsAddr_pinkDrawerOpenFlag, 1);
}
- return true;
-
+ break;
- case 0x6b86:
- if (CHECK_FLAG(0xDBBD, 1)) {
- displayMessage(0x4b39);
- } else {
- displayMessage(0x4acd);
- displayMessage(0x4b0d);
- SET_FLAG(0xDBBD, 1);
- }
- return true;
+ case csAddr_DrawerOpenMessage:
+ fnDrawerOpenMessage();
+ break;
- case 0x6be1: //handle to the bathroom
- if (CHECK_FLAG(0xDBD9, 1)) {
- displayMessage(0x5326); //i'd better catch johnny
- } else {
+ case 0x6be1: // handle to the bathroom
+ if (CHECK_FLAG(dsAddr_MansionJohnNotyEscapingFlag, 1))
+ displayMessage(dsAddr_catchJohnFirstMsg); // "I'd better catch John Noty first"
+ else {
playSound(88, 4);
playActorAnimation(808);
loadScene(36, 41, 195, 2);
}
- return true;
+ break;
case 0x6bad:
playSound(80, 4);
playActorAnimation(971);
loadScene(32, 139, 199, 1);
- return true;
+ break;
case 0x6c45:
playSound(89, 6);
- playActorAnimation(CHECK_FLAG(0xDBEF, 1) ? 985 : 806);
+ playActorAnimation(CHECK_FLAG(dsAddr_mansionHandleInDoorHoleFlag, 1) ? 985 : 806);
loadScene(34, 40, 133, 2);
- return true;
+ break;
case 0x6c83:
waitLanAnimationFrame(1, 1);
- Dialog::pop(scene, 0xdb2e, 0, 727, 0xd1, 0xef, 0, 1);
- scene->getObject(1)->setName((const char *)res->dseg.ptr(0xaa94));
- SET_FLAG(0xDBD1, 1);
- return true;
+ dialog->pop(scene, dsAddr_dialogStackRobotSafe, 0, 727, textColorMark, textColorMike, 0, 1);
+ scene->getObject(1)->setName((const char *)res->dseg.ptr(dsAddr_scnObjNameMike));
+ SET_FLAG(dsAddr_MansionRobotSafeUnlockedFlag, 1);
+ break;
- case 0x6c9d: //getting jar
+ case 0x6c9d: // getting jar
setOns(0, 71);
playSound(32, 5);
playActorAnimation(732);
disableObject(2);
- inventory->add(72);
- return true;
+ inventory->add(kInvItemTimePills);
+ break;
- case 0x6cc4: //secret diary
+ case 0x6cc4: // secret diary
playActorAnimation(754);
hideActor();
- displayCutsceneMessage(0x517b, 30430);
+ displayCutsceneMessage(dsAddr_cutsceneMsg0, 30, 95); // "A secret diary of ..."
playMusic(3);
loadScene(11, scene->getPosition());
playAnimation(750, 2);
- Dialog::show(scene, 0x4f50, 751, 529, 0xe5, 0xd9, 2, 1);
+ dialog->show(117, scene, 751, 529, textColorProfessor, textColorMansionGuard, 2, 1);
playAnimation(752, 0, true);
playAnimation(753, 1, true);
waitAnimation();
- Dialog::show(scene, 0x5168, 529, 751, 0xd9, 0xe5, 1, 2);
+ dialog->show(118, scene, 529, 751, textColorMansionGuard, textColorProfessor, 1, 2);
loadScene(30, scene->getPosition());
- Dialog::show(scene, 0x449e, 733, 734, 0xe5, 0xd0, 2, 3);
+ dialog->show(108, scene, 733, 734, textColorProfessor, textColorJohnNoty, 2, 3);
playSound(75, 13);
playSound(32, 22);
playAnimation(735, 1, true);
playAnimation(736, 2, true);
waitAnimation();
- Dialog::show(scene, 0x46cf, 737, 738, 0xd0, 0xe5, 3, 2);
-
+ dialog->show(109, scene, 737, 738, textColorJohnNoty, textColorProfessor, 3, 2);
playSound(32, 1);
playAnimation(739, 1, true);
playAnimation(740, 2, true);
waitAnimation();
- Dialog::show(scene, 0x4772, 733, 734, 0xe5, 0xd0, 2, 3);
+ dialog->show(110, scene, 733, 734, textColorProfessor, textColorJohnNoty, 2, 3);
playAnimation(742, 1, true);
playAnimation(741, 2, true);
waitAnimation();
- Dialog::show(scene, 0x481c, 743, 733, 0xd0, 0xe5, 3, 2); //where's my wallet??
+ dialog->show(111, scene, 743, 733, textColorJohnNoty, textColorProfessor, 3, 2);
playAnimation(744, 1, true);
playAnimation(745, 2, true);
waitAnimation();
- Dialog::show(scene, 0x4873, 734, 733, 0xd0, 0xe5, 3, 2);
+ dialog->show(112, scene, 734, 733, textColorJohnNoty, textColorProfessor, 3, 2);
playAnimation(746, 1, true);
playAnimation(747, 2, true);
waitAnimation();
-
- Dialog::show(scene, 0x4da5, 734, 734, 0xd0, 0xd0, 3, 3);
- Dialog::show(scene, 0x4eb9, 748, 748, 0xd0, 0xd0, 3, 3);
- Dialog::show(scene, 0x4f15, 749, 749, 0xd0, 0xd0, 3, 3);
- Dialog::show(scene, 0x4f2f, 748, 748, 0xd0, 0xd0, 3, 3);
+ dialog->show(113, scene, 734, 734, textColorJohnNoty, textColorJohnNoty, 3, 3);
+ dialog->show(114, scene, 748, 748, textColorJohnNoty, textColorJohnNoty, 3, 3);
+ dialog->show(115, scene, 749, 749, textColorJohnNoty, textColorJohnNoty, 3, 3);
+ dialog->show(116, scene, 748, 748, textColorJohnNoty, textColorJohnNoty, 3, 3);
playMusic(10);
loadScene(32, scene->getPosition());
@@ -3296,35 +4168,34 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playActorAnimation(755);
moveRel(0, 0, 3);
- Dialog::show(scene, 0x51bf, 0, 0, 0xd1, 0xd1, 0, 0);
+ dialog->showMark(119, scene);
hideActor();
loadScene(31, scene->getPosition());
- Dialog::show(scene, 0x539f, 763, 764, 0xd9, 0xd0, 1, 2);
+ dialog->show(123, scene, 763, 764, textColorMansionGuard, textColorJohnNoty, 1, 2);
loadScene(32, scene->getPosition());
showActor();
- Dialog::show(scene, 0x52c3, 0, 0, 0xd1, 0xd1, 0, 0); //i have to hide somewhere
+ dialog->showMark(120, scene);
disableObject(3);
enableObject(7);
- SET_FLAG(0xDBD5, 1);
- return true;
+ SET_FLAG(dsAddr_MansionJohnNotyOutsideBathroomFlag, 1);
+ break;
case 0x6f20:
- if (CHECK_FLAG(0xDBD5, 1)) {
- displayMessage(0x51a7);
- } else {
+ if (CHECK_FLAG(dsAddr_MansionJohnNotyOutsideBathroomFlag, 1))
+ displayMessage(dsAddr_cantHideMsg); // "I can't hide here!"
+ else
rejectMessage();
- }
- return true;
+ break;
- case 0x6f75: //hiding in left corner
+ case 0x6f75: // hiding in left corner
moveRel(0, 0, 3);
playActorAnimation(756);
hideActor();
playAnimation(758, 1);
- Dialog::show(scene, 0x52e6, 759, 759, 0xd0, 0xd0, 2, 2); //I have to buy...
+ dialog->show(121, scene, 759, 759, textColorJohnNoty, textColorJohnNoty, 2, 2);
playSound(40, 5);
playSound(52, 13);
@@ -3340,272 +4211,265 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playSound(58, 12);
playSound(58, 14);
playAnimation(765, 1);
- Dialog::show(scene, 0x5443, 766, 766, 0xd9, 0xd9, 1, 1);
+ dialog->show(124, scene, 766, 766, textColorMansionGuard, textColorMansionGuard, 1, 1);
loadScene(32, scene->getPosition());
- Dialog::show(scene, 0x5358, 761, 761, 0xd0, 0xd0, 2, 2);
+ dialog->show(122, scene, 761, 761, textColorJohnNoty, textColorJohnNoty, 2, 2);
playAnimation(762, 1);
setOns(2, 0);
showActor();
playActorAnimation(757);
moveRel(0, 0, 1);
- displayMessage(0x51e7);
+ displayMessage(dsAddr_wasCloseMsg); // "That was close"
enableObject(8);
disableObject(7);
- SET_FLAG(0xDBD5, 0);
- return true;
+ SET_FLAG(dsAddr_MansionJohnNotyOutsideBathroomFlag, 0);
+ break;
case 0x6f4d:
- if (CHECK_FLAG(0xDBD5, 1)) {
- displayMessage(0x51bb);
- } else {
+ if (CHECK_FLAG(dsAddr_MansionJohnNotyOutsideBathroomFlag, 1))
+ displayMessage(dsAddr_johnOutsideMsg); // "There's John Noty outside! I can't go out!"
+ else
loadScene(31, 139, 172, 3);
- }
- return true;
+ break;
case 0x6f32:
- if (CHECK_FLAG(0xDBD5, 1)) {
- displayMessage(0x51a7);
+ if (CHECK_FLAG(dsAddr_MansionJohnNotyOutsideBathroomFlag, 1)) {
+ displayMessage(dsAddr_cantHideMsg); // "I can't hide here!"
} else {
playActorAnimation(977);
- displayMessage(0x5511);
+ displayMessage(dsAddr_lockedMsg); // "It's Locked!"
}
- return true;
+ break;
case 0x7096:
playSound(32, 5);
playActorAnimation(767);
setOns(1, 0);
- inventory->add(73);
+ inventory->add(kInvItemHandle);
disableObject(8);
- return true;
+ break;
+
+ case 0x7218:
+ rejectMessage();
+ break;
case 0x7291:
playSound(89, 3);
playActorAnimation(975);
loadScene(31, 298, 177, 4);
- return true;
+ break;
case 0x72c2:
- if (CHECK_FLAG(0xDBD6, 2)) {
- displayMessage(0x522c);
+ if (CHECK_FLAG(dsAddr_MansionSinkState, 2)) {
+ displayMessage(dsAddr_enoughWaterMsg); // "There's enough water in the sink"
} else {
playSound(79, 6);
playSound(84, 9);
playActorAnimation(801);
wait(50);
- if (CHECK_FLAG(0xDBD6, 1)) {
- displayMessage(0x538d);
- SET_FLAG(0xDBD6, 2);
+ if (CHECK_FLAG(dsAddr_MansionSinkState, 1)) {
+ displayMessage(dsAddr_sinkFullMsg); // "The sink is full of hot water"
+ SET_FLAG(dsAddr_MansionSinkState, 2);
} else
- displayMessage(0x5372);
+ displayMessage(dsAddr_waterHotMsg); // "The water looks very hot"
}
- return true;
+ break;
case 0x7309:
playSound(66, 5);
playSound(67, 11);
playActorAnimation(976);
- displayMessage(0x5955);
- return true;
+ displayMessage(dsAddr_emptyMsg); // "It's Empty"
+ break;
case 0x77d5:
- if (CHECK_FLAG(0xdbd7, 1) && !CHECK_FLAG(0xdbd8, 1)) { //disallow exiting through the first door until switch turned on, not present in original game
- displayMessage(0x52cb);
- return true;
+ if (CHECK_FLAG(dsAddr_MansionThruFanByTimePillFlag, 1) && !CHECK_FLAG(dsAddr_MansionVentFanStoppedFlag, 1)) { // disallow exiting through the first door until switch turned on, not present in original game
+ displayMessage(dsAddr_noSaladMsg); // "I don't want to turn myself into a salad"
+ } else {
+ playSound(89, 6);
+ playActorAnimation(978);
+ loadScene(31, 298, 177, 4);
}
- playSound(89, 6);
- playActorAnimation(978);
- loadScene(31, 298, 177, 4);
- return true;
+ break;
case 0x79e4:
- processCallback(0x6849);
- return false;
+ fnEgoBottomRightTurn();
+ retVal = false;
+ break;
- case 0x79eb: //color of the book
- displayMessage(res->dseg.get_word(0x5f3c + GET_FLAG(0xDBC1) * 2 - 2));
- return true;
+ case 0x79eb: // color of the book
+ // FIXME - Replace with internal lookup and switch
+ displayMessage(res->dseg.get_word(dsAddr_bookColorMsgPtr + GET_FLAG(dsAddr_drawerPuzzleBookValue) * 2 - 2));
+ break;
case 0x79fd:
- if (CHECK_FLAG(0xDBB7, 1)) {
- displayMessage(0x4b6c);
- return true;
- } else
- return false;
+ if (CHECK_FLAG(dsAddr_blueDrawerOpenFlag, 1))
+ displayMessage(dsAddr_blueInteriorMsg); // "It's got a blue interior"
+ else
+ retVal = false;
+ break;
case 0x7a0f:
- if (CHECK_FLAG(0xDBB8, 1)) {
- if (!CHECK_FLAG(0xDBBF, 1)) {
- displayMessage(0x4c32);
+ if (CHECK_FLAG(dsAddr_redDrawerOpenFlag, 1)) {
+ if (!CHECK_FLAG(dsAddr_drawerGotPolaroidFlag, 1)) {
+ displayMessage(dsAddr_foundPolaroidMsg); // "There's a polaroid inside! I might need that"
playSound(5, 11);
playActorAnimation(690);
- inventory->add(53);
- SET_FLAG(0xDBBF, 1);
+ inventory->add(kInvItemPolaroidCamera);
+ SET_FLAG(dsAddr_drawerGotPolaroidFlag, 1);
}
- displayMessage(0x4b87);
- return true;
+ displayMessage(dsAddr_redInteriorMsg); // "It's got a red interior"
} else
- return false;
+ retVal = false;
+ break;
case 0x7a49:
- if (CHECK_FLAG(0xDBB9, 1)) {
- displayMessage(0x4ba1);
- return true;
- } else
- return false;
+ if (CHECK_FLAG(dsAddr_greyDrawerOpenFlag, 1))
+ displayMessage(dsAddr_greyInteriorMsg); // "It's got a grey interior"
+ else
+ retVal = false;
+ break;
case 0x7a5b:
- if (CHECK_FLAG(0xDBBA, 1)) {
- displayMessage(0x4bbc);
- return true;
- } else
- return false;
+ if (CHECK_FLAG(dsAddr_greenDrawerOpenFlag, 1))
+ displayMessage(dsAddr_greenInteriorMsg); // "It's got a green interior"
+ else
+ retVal = false;
+ break;
case 0x7a6d:
- if (CHECK_FLAG(0xDBBB, 1)) {
- displayMessage(0x4bd8);
- return true;
- } else
- return false;
+ if (CHECK_FLAG(dsAddr_brownDrawerOpenFlag, 1))
+ displayMessage(dsAddr_brownInteriorMsg); // "It's got a brown interior"
+ else
+ retVal = false;
+ break;
case 0x7a7f:
- if (CHECK_FLAG(0xDBBC, 1)) {
- if (!CHECK_FLAG(0xDBBE, 1)) {
- displayMessage(0x4c0f); //there's dictaphone inside!
+ if (CHECK_FLAG(dsAddr_pinkDrawerOpenFlag, 1)) {
+ if (!CHECK_FLAG(dsAddr_drawerGotDictaphoneFlag, 1)) {
+ displayMessage(dsAddr_dictaphoneInsideMsg); // "Wow! There's a dictaphone inside!"
playSound(5, 12);
playActorAnimation(689);
- inventory->add(52);
- SET_FLAG(0xDBBE, 1);
+ inventory->add(kInvItemDictaphoneNoBatteries);
+ SET_FLAG(dsAddr_drawerGotDictaphoneFlag, 1);
}
- displayMessage(0x4bf4);
- return true;
+ displayMessage(dsAddr_pinkInteriorMsg); // "It's got a pink interior"
} else
- return false;
+ retVal = false;
+ break;
case 0x7af7:
- if (CHECK_FLAG(0xDBD0, 1)) {
- displayMessage(0x5082);
- return true;
- } else
- return false;
-
- case 0x7b09: {
- byte v = GET_FLAG(0xDBD6);
- switch (v) {
- case 1:
- displayMessage(0x51f8);
- return true;
- case 2:
- displayMessage(0x538d);
- return true;
- default:
- return false;
- }
- }
+ if (CHECK_FLAG(dsAddr_MansionPutBurningPaperInFridgeFlag, 1))
+ displayMessage(dsAddr_yummyMsg); // "Yummy"
+ else
+ retVal = false;
+ break;
- case 0x9166:
- if (CHECK_FLAG(0xDBD1, 1)) {
- return true;
- } else {
- displayMessage(0x50a6);
- return false;
+ case 0x7b09:
+ {
+ byte v = GET_FLAG(dsAddr_MansionSinkState);
+ switch (v) {
+ case 1:
+ displayMessage(dsAddr_corkInHoleMsg); // "The cork is stuck in the hole"
+ break;
+ case 2:
+ displayMessage(dsAddr_sinkFullMsg); // "The sink is full of hot water"
+ break;
+ default:
+ retVal = false;
+ break;
+ }
}
+ break;
- case 0x9175:
- if (CHECK_FLAG(0xDBD2, 0) || CHECK_FLAG(0xDBD3, 0) || CHECK_FLAG(0xDBD4, 0))
- return true;
+ case csAddr_robotSafeAlreadyUnlockedCheck:
+ fnRobotSafeAlreadyUnlockedCheck();
+ break;
- waitLanAnimationFrame(1, 1);
- playSound(89, 2);
- playActorAnimation(731);
- setOns(0, 70);
- setLan(1, 0);
- disableObject(1);
- enableObject(2);
- enableObject(3);
- return true;
+ case csAddr_robotSafeUnlockCheck:
+ fnRobotSafeUnlockCheck();
+ break;
- case 0x90bc: //handle on the hole
+ case 0x90bc: // handle on the hole
playSound(5, 3);
playSound(6, 9);
playActorAnimation(807);
setOns(0, 83);
- inventory->remove(73);
+ inventory->remove(kInvItemHandle);
disableObject(2);
enableObject(3);
- SET_FLAG(0xDBEF, 1);
- return true;
-
- case 0x90fc: //dictaphone on robot
- if (!processCallback(0x9166))
- return true;
-
- if (CHECK_FLAG(0xDBD2, 1)) {
- displayMessage(0x50c3);
- return true;
- }
+ SET_FLAG(dsAddr_mansionHandleInDoorHoleFlag, 1);
+ break;
- if (!CHECK_FLAG(0xDBCB, 1)) {
- displayMessage(0x5101);
- return true;
+ case 0x90fc: // dictaphone on robot
+ if (fnRobotSafeAlreadyUnlockedCheck()) {
+ if (CHECK_FLAG(dsAddr_MansionRobotSafeVoiceTestPassedFlag, 1)) {
+ displayMessage(dsAddr_fooledOnceMsg); // "I'd already fooled him once"
+ } else {
+ if (!CHECK_FLAG(dsAddr_usedDictaphoneOnTVFlag, 1)) {
+ displayMessage(dsAddr_notMyVoiceMsg); // "I won't cheat Mike with MY voice"
+ } else {
+ displayMessage(dsAddr_mikeVoiceTestMsg); // "Mike, activate the voice test"
+ waitLanAnimationFrame(1, 1);
+
+ playSound(5, 3);
+ playSound(5, 39);
+ displayAsyncMessage(dsAddr_singingMsg, 68, 126, 9, 35, textColorJohnNoty); // "siiiiinging!"
+ playActorAnimation(728);
+
+ waitLanAnimationFrame(1, 1);
+ dialog->show(98, scene, 0, 727, textColorMark, textColorMike, 0, 1);
+ SET_FLAG(dsAddr_MansionRobotSafeVoiceTestPassedFlag, 1);
+ fnRobotSafeUnlockCheck();
+ }
+ }
}
+ break;
- displayMessage(0x50e1);
- waitLanAnimationFrame(1, 1);
-
- playSound(5, 3);
- playSound(5, 39);
- displayAsyncMessage(0x5124, 40388, 9, 35, 0xd0);
- playActorAnimation(728);
-
- waitLanAnimationFrame(1, 1);
- Dialog::show(scene, 0x3d17, 0, 727, 0xd1, 0xef, 0, 1);
- SET_FLAG(0xDBD2, 1);
- processCallback(0x9175);
- return true;
+ case 0x91cb: // use socks on robot
+ if (fnRobotSafeAlreadyUnlockedCheck()) {
+ if (CHECK_FLAG(dsAddr_MansionRobotSafeScentTestPassedFlag, 1)) {
+ displayMessage(dsAddr_fooledOnceMsg); // "I'd already fooled him once"
+ } else {
+ displayMessage(dsAddr_mikeScentTestMsg); // "Mike, let's get on with the scent test"
- case 0x91cb: //use socks on robot
- if (!processCallback(0x9166))
- return true;
+ waitLanAnimationFrame(1, 1);
+ playSound(5, 3);
+ playSound(5, 23);
+ playActorAnimation(729);
- if (CHECK_FLAG(0xDBD3, 1)) {
- displayMessage(0x50c3);
- return true;
+ waitLanAnimationFrame(1, 1);
+ dialog->show(99, scene, 0, 727, textColorMark, textColorMike, 0, 1);
+ SET_FLAG(dsAddr_MansionRobotSafeScentTestPassedFlag, 1);
+ fnRobotSafeUnlockCheck();
+ }
}
- displayMessage(0x5138);
-
- waitLanAnimationFrame(1, 1);
- playSound(5, 3);
- playSound(5, 23);
- playActorAnimation(729);
+ break;
- waitLanAnimationFrame(1, 1);
- Dialog::show(scene, 0x3d70, 0, 727, 0xd1, 0xef, 0, 1);
- SET_FLAG(0xDBD3, 1);
- processCallback(0x9175);
- return true;
+ case 0x9209: // photo on robot
+ if (fnRobotSafeAlreadyUnlockedCheck()) {
+ if (CHECK_FLAG(dsAddr_MansionRobotSafeViewTestPassedFlag, 1)) {
+ displayMessage(dsAddr_fooledOnceMsg); // "I'd already fooled him once"
+ } else {
+ displayMessage(dsAddr_mikeViewTestMsg); // "Mike, run the view test"
+ waitLanAnimationFrame(1, 1);
- case 0x9209: //photo on robot
- if (!processCallback(0x9166))
- return true;
+ playSound(5, 3);
+ playSound(5, 25);
+ playActorAnimation(730);
- if (CHECK_FLAG(0xDBD4, 1)) {
- displayMessage(0x50c3);
- return true;
+ waitLanAnimationFrame(1, 1);
+ dialog->show(100, scene, 0, 727, textColorMark, textColorMike, 0, 1);
+ SET_FLAG(dsAddr_MansionRobotSafeViewTestPassedFlag, 1);
+ fnRobotSafeUnlockCheck();
+ }
}
- displayMessage(0x5161);
- waitLanAnimationFrame(1, 1);
-
- playSound(5, 3);
- playSound(5, 25);
- playActorAnimation(730);
+ break;
- waitLanAnimationFrame(1, 1);
- Dialog::show(scene, 0x3dd6, 0, 727, 0xd1, 0xef, 0, 1);
- SET_FLAG(0xDBD4, 1);
- processCallback(0x9175);
- return true;
+ case 0x9247:
+ displayMessage(dsAddr_sameBottleMsg); // "The bottle's the same, but I doubt if it's enough to fool anyone"
+ break;
case 0x924e:
setOns(2, 64);
@@ -3613,9 +4477,9 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playSound(52, 10);
playActorAnimation(711);
moveRel(0, 0, 4);
- Dialog::show(scene, 0x3b21, 0, 709, 0xd1, 0xef, 0, 1);
+ dialog->show(95, scene, 0, 709, textColorMark, textColorCook, 0, 1);
moveTo(300, 190, 4);
- inventory->remove(64);
+ inventory->remove(kInvItemFakeChilli);
disableObject(8);
playAnimation(712, 0);
setOns(2, 0);
@@ -3623,90 +4487,90 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playSound(15, 28);
playSound(16, 37);
playAnimation(713, 0);
- Dialog::show(scene, 0x3c0d, 0, 709, 0xd1, 0xef, 0, 1);
+ dialog->show(96, scene, 0, 709, textColorMark, textColorCook, 0, 1);
playSound(85, 2);
playAnimation(714, 0);
setLan(1, 0);
disableObject(1);
{
Object *obj = scene->getObject(2);
- obj->actor_rect.left = obj->actor_rect.right = 81;
- obj->actor_rect.top = obj->actor_rect.bottom = 160;
- obj->actor_orientation = 4;
+ obj->actorRect.left = obj->actorRect.right = 81;
+ obj->actorRect.top = obj->actorRect.bottom = 160;
+ obj->actorOrientation = 4;
obj->save();
}
{
Object *obj = scene->getObject(3);
- obj->actor_rect.left = obj->actor_rect.right = 64;
- obj->actor_rect.top = obj->actor_rect.bottom = 168;
- obj->actor_orientation = 4;
+ obj->actorRect.left = obj->actorRect.right = 64;
+ obj->actorRect.top = obj->actorRect.bottom = 168;
+ obj->actorOrientation = 4;
obj->save();
}
{
Object *obj = scene->getObject(10);
- obj->actor_rect.left = obj->actor_rect.right = 105;
- obj->actor_rect.top = obj->actor_rect.bottom = 160;
- obj->actor_orientation = 1;
+ obj->actorRect.left = obj->actorRect.right = 105;
+ obj->actorRect.top = obj->actorRect.bottom = 160;
+ obj->actorOrientation = 1;
obj->save();
}
- SET_FLAG(0xDBCC, 1);
- return true;
+ SET_FLAG(dsAddr_MansionCookGoneFlag, 1);
+ break;
case 0x9472:
playSound(5, 4);
playSound(19, 14);
playActorAnimation(793);
- displayMessage(0x5218);
- inventory->remove(60);
- SET_FLAG(0xDBD6, 1);
- return true;
+ displayMessage(dsAddr_fitsPerfectMsg); // "It fits perfectly!"
+ inventory->remove(kInvItemWrappedCork);
+ SET_FLAG(dsAddr_MansionSinkState, 1);
+ break;
- case 0x9449: //meat + stew
+ case 0x9449: // meat + stew
playSound(5, 4);
playSound(63, 12);
playActorAnimation(726);
- displayMessage(0x508a);
- inventory->remove(69);
- inventory->add(70);
- return true;
+ displayMessage(dsAddr_dislikeVealMsg); // "I never liked veal anyway"
+ inventory->remove(kInvItemMeat);
+ inventory->add(kInvItemPlasticBag);
+ break;
case 0x949b:
- if (CHECK_FLAG(0xDBD6, 2)) {
+ if (CHECK_FLAG(dsAddr_MansionSinkState, 2)) {
playSound(5, 4);
playSound(5, 25);
playActorAnimation(802);
- displayMessage(0x5272);
- inventory->remove(62);
- inventory->add(74);
- inventory->add(65);
+ displayMessage(dsAddr_labelOffMsg); // "The label has come off!"
+ inventory->remove(kInvItemChilliWithLabel);
+ inventory->add(kInvItemChilliNoLabel);
+ inventory->add(kInvItemLabel);
} else
- displayMessage(0x524f);
- return true;
+ displayMessage(dsAddr_noHotWaterMsg); // "There's no hot water in the sink"
+ break;
case 0x94d4:
- if (inventory->has(70)) {
+ if (inventory->has(kInvItemPlasticBag)) {
setOns(0, 0);
playSound(5, 3);
playSound(5, 18);
playSound(13, 12);
playActorAnimation(803);
disableObject(7);
- inventory->remove(70);
- inventory->add(71);
+ inventory->remove(kInvItemPlasticBag);
+ inventory->add(kInvItemSocks);
} else
- displayMessage(0x53ad);
- return true;
+ displayMessage(dsAddr_noSockStoreMsg); // "I don't have anything to store these socks in"
+ break;
case 0x951b:
playSound(5, 4);
playSound(5, 22);
playActorAnimation(804);
- displayMessage(0x528b);
- return true;
+ displayMessage(dsAddr_corkTooSmallMsg); // "The cork is a bit too small"
+ break;
case 0x73a3:
- if (CHECK_FLAG(0xdbc5, 1)) {
- SET_FLAG(0xdbc5, 0);
+ if (CHECK_FLAG(dsAddr_mansionTVOnFlag, 1)) {
+ SET_FLAG(dsAddr_mansionTVOnFlag, 0);
//call 73e6
playSound(71, 3);
@@ -3714,92 +4578,94 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playAnimation(0, 0, true);
reloadLan();
- if (CHECK_FLAG(0xDBC6, 1)) {
- displayMessage(0x4da6);
+ if (CHECK_FLAG(dsAddr_mansionVCRPlayingTapeFlag, 1)) {
+ displayMessage(dsAddr_muchBetterMsg); // "That's much better"
}
} else {
- SET_FLAG(0xdbc5, 1);
+ SET_FLAG(dsAddr_mansionTVOnFlag, 1);
//call 73e6
playSound(71, 3);
playActorAnimation(700);
reloadLan();
}
- return true;
+ break;
- case 0x9537: //using remote on VCR
+ case 0x9537: // using remote on VCR
playSound(5, 3);
playSound(5, 16);
playActorAnimation(703);
- if (!CHECK_FLAG(0xDBC8, 1)) {
- displayMessage(0x4D80); //nothing happened
- return true;
- }
-
- //0x955a
- if (CHECK_FLAG(0xDBC6, 0)) {
- if (CHECK_FLAG(0xDBC5, 1)) { //tv on
- if (!CHECK_FLAG(0xDBC7, 1))
- displayMessage(0x4d93); //the tape started
-
- SET_FLAG(0xDBC6, 1);
- reloadLan();
- if (!CHECK_FLAG(0xDBC7, 1)) {
- Dialog::show(scene, 0x392c, 0, 702, 0xd1, 0xd0, 0, 1);
- SET_FLAG(0xDBC7, 1);
+ if (!CHECK_FLAG(dsAddr_mansionVCRTapeLoadedFlag, 1))
+ displayMessage(dsAddr_NotHappenMsg); // "Nothing happened"
+ else {
+ //0x955a
+ if (CHECK_FLAG(dsAddr_mansionVCRPlayingTapeFlag, 0)) {
+ if (CHECK_FLAG(dsAddr_mansionTVOnFlag, 1)) {
+ if (!CHECK_FLAG(dsAddr_mansionVCRPlayedTapeBeforeFlag, 1))
+ displayMessage(dsAddr_tapeStartedMsg); // "The tape started!"
+
+ SET_FLAG(dsAddr_mansionVCRPlayingTapeFlag, 1);
+ reloadLan();
+ if (!CHECK_FLAG(dsAddr_mansionVCRPlayedTapeBeforeFlag, 1)) {
+ dialog->show(93, scene, 0, 702, textColorMark, textColorJohnNoty, 0, 1);
+ SET_FLAG(dsAddr_mansionVCRPlayedTapeBeforeFlag, 1);
+ }
+ } else
+ displayMessage(dsAddr_tvOffMsg); // "I just realised that the TV is off"
+ } else {
+ SET_FLAG(dsAddr_mansionVCRPlayingTapeFlag, 0);
+ if (CHECK_FLAG(dsAddr_mansionTVOnFlag, 1)) {
+ reloadLan();
+ displayMessage(dsAddr_muchBetterMsg); // "That's much better"
}
- } else
- displayMessage(0x4d5b); //i just realized that tv is off
- } else {
- SET_FLAG(0xDBC6, 0);
- if (CHECK_FLAG(0xDBC5, 1)) { //tv on
- reloadLan();
- displayMessage(0x4da6); //much better!
}
}
- return true;
+ break;
- case 0x95eb: //polaroid + tv
- if (CHECK_FLAG(0xDBC6, 1)) {
- if (CHECK_FLAG(0xDBCA, 1)) {
- displayMessage(0x4de6);
+ case 0x95eb: // polaroid + tv
+ if (CHECK_FLAG(dsAddr_mansionVCRPlayingTapeFlag, 1)) {
+ if (CHECK_FLAG(dsAddr_usedPolaroidOnTVFlag, 1)) {
+ displayMessage(dsAddr_enoughPhotosMsg); // "I don't need any more photos"
} else {
playSound(5, 3);
playSound(5, 24);
playSound(90, 18);
playActorAnimation(707);
- inventory->add(61);
- SET_FLAG(0xDBCA, 1);
+ inventory->add(kInvItemPhoto);
+ SET_FLAG(dsAddr_usedPolaroidOnTVFlag, 1);
}
} else
- displayMessage(0x4ea5);
- return true;
+ displayMessage(dsAddr_notRightMomentMsg); // "I don't think this is the right moment"
+ break;
- case 0x962f: //polaroid + tv
- if (CHECK_FLAG(0xDBC6, 1)) {
- if (CHECK_FLAG(0xDBCB, 1)) {
- displayMessage(0x4e32);
+ case 0x962f: // dictaphone + tv
+ if (CHECK_FLAG(dsAddr_mansionVCRPlayingTapeFlag, 1)) {
+ if (CHECK_FLAG(dsAddr_usedDictaphoneOnTVFlag, 1)) {
+ displayMessage(dsAddr_alreadyRecordedMsg); // "I already recorded what I wanted to"
} else {
- displayMessage(0x4e05);
+ displayMessage(dsAddr_recordScareMsg); // "Yeah, I can record this and scare the cats"
playSound(5, 3);
playSound(5, 27);
playActorAnimation(708);
- SET_FLAG(0xDBCB, 1);
+ SET_FLAG(dsAddr_usedDictaphoneOnTVFlag, 1);
}
} else
- displayMessage(0x4ea5);
- return true;
-
+ displayMessage(dsAddr_notRightMomentMsg); // "I don't think this is the right moment"
+ break;
case 0x95c8:
playSound(5, 3);
playSound(91, 12);
playActorAnimation(706);
- inventory->remove(54);
- SET_FLAG(0xDBC8, 1);
- return true;
+ inventory->remove(kInvItemVideoTape);
+ SET_FLAG(dsAddr_mansionVCRTapeLoadedFlag, 1);
+ break;
- case 0x9673: //hit fatso - final scene
+ case 0x966c:
+ displayMessage(dsAddr_cantRecordNoBatteriesMsg); // "I can't record anything until I find some batteries"
+ break;
+
+ case 0x9673: // hit fatso - final scene
playSound(5, 3);
playSound(24, 10);
playActorAnimation(798);
@@ -3811,12 +4677,12 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
wait(100);
playActorAnimation(805);
moveTo(50, 170, 3);
- displayMessage(0x5349);
+ displayMessage(dsAddr_onlyChilliMsg); // "Good this red stuff is only a chilli"
//moveTo(105, 157, 0, true);
playMusic(3);
loadScene(11, 105, 157, 4);
- Dialog::show(scene, 0x8409, 0, 938, 0xd1, 0xec, 0, 1);
+ dialog->show(203, scene, 0, 938, textColorMark, textColorCaptain, 0, 1);
playAnimation(939, 0, true, true);
playActorAnimation(942, true);
@@ -3837,9 +4703,9 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playActorAnimation(945, true);
waitAnimation();
- Dialog::show(scene, 0x844f, 0, 938, 0xd1, 0xec, 0, 1);
+ dialog->show(204, scene, 0, 938, textColorMark, textColorCaptain, 0, 1);
playAnimation(946, 0);
- Dialog::show(scene, 0x87c7, 0, 938, 0xd1, 0xec, 0, 1);
+ dialog->show(205, scene, 0, 938, textColorMark, textColorCaptain, 0, 1);
playSound(24, 7);
playAnimation(948, 0, true);
@@ -3847,16 +4713,16 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
waitAnimation();
loadScene(40, 198, 186, 1);
- Dialog::show(scene, 0x8890, 0, 920, 0xd1, 0xe7, 0, 1);
- Dialog::show(scene, 0x8a2f, 0, 921, 0xd1, 0xe7, 0, 1);
+ dialog->show(206, scene, 0, 920, textColorMark, textColorRGBBoss, 0, 1);
+ dialog->show(207, scene, 0, 921, textColorMark, textColorRGBBoss, 0, 1);
playAnimation(923, 0);
- Dialog::show(scene, 0x8aa7, 0, 920, 0xd1, 0xe7, 0, 1);
+ dialog->show(208, scene, 0, 920, textColorMark, textColorRGBBoss, 0, 1);
moveTo(237, 186, 0);
moveTo(237, 177, 0);
moveTo(192, 177, 4);
playAnimation(949, 0);
- Dialog::showMono(scene, 0x8af6, 950, 0xe7, 1);
+ dialog->showMono(209, scene, 950, textColorRGBBoss, 1);
playSound(32, 5);
playSound(40, 14);
@@ -3869,98 +4735,89 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
displayCredits();
loadScene(39, 192, 177, 0);
hideActor();
- Dialog::showMono(scene, 0x8b4d, 953, 0xe3, 1); //well...
+ dialog->showMono(210, scene, 953, textColorMarkEnd, 1);
playSound(5, 15);
playAnimation(954, 0);
- Dialog::showMono(scene, 0x8b7a, 955, 0xe3, 1); //that's all folks
+ dialog->showMono(211, scene, 955, textColorMarkEnd, 1);
playMusic(2);
- displayCredits(0xe47c, 4500); //3 minutes (infinite until key pressed in original)
+ displayCredits(dsAddr_finalCredits6, 4500); // 3 minutes (infinite until key pressed in original)
scene->push(SceneEvent(SceneEvent::kQuit));
+ break;
- return true;
-
- case 0x9921: { //using diving eq
- int id = scene->getId();
- if (id != 15) {
- displayMessage(id == 16 ? 0x38ce : 0x38a7);
- } else {
- playSound(5, 3);
- playSound(38, 16);
- playSound(38, 22);
- playActorAnimation(614);
- playSound(5, 3);
- playSound(44, 10);
- playSound(20, 26);
- playActorAnimation(615);
- loadScene(17, 156, 180, 3);
- SET_FLAG(0, 4);
- playSound(64, 7);
- playSound(64, 21);
- playSound(64, 42);
- playSound(64, 63);
- setTimerCallback(0x9a1d, 30);
- playActorAnimation(617, false, true);
+ case csAddr_useDivingEquipment: // using diving eq
+ // FIXME - Some code is missing here as displayMessage(dsAddr_cantTalkUnderwaterMsg),
+ // displayMessage(dsAddr_notSwimmingThereMsg), displayMessage(dsAddr_tooLittleAirMsg)
+ // displayMessage(dsAddr_fishDontWorryMsg) are never called.
+ {
+ int id = scene->getId();
+ if (id != 15) {
+ if (id == 16)
+ displayMessage(dsAddr_notHereMsg); // "Not here"
+ else
+ displayMessage(dsAddr_notBestPlaceMsg); // "It's not the best place for diving"
+ } else {
+ playSound(5, 3);
+ playSound(38, 16);
+ playSound(38, 22);
+ playActorAnimation(614);
+ playSound(5, 3);
+ playSound(44, 10);
+ playSound(20, 26);
+ playActorAnimation(615);
+ loadScene(17, 156, 180, 3);
+ SET_FLAG(dsAddr_timedCallbackState, 4);
+ playSound(64, 7);
+ playSound(64, 21);
+ playSound(64, 42);
+ playSound(64, 63);
+ setTimerCallback(csAddr_noAnchorTimeout, 30);
+ playActorAnimation(617, false, true);
+ }
}
- }
- return true;
+ break;
- case 0x9a1d: //no anchor, timeout
- SET_FLAG(0, 0);
- processCallback(0x9a7a);
- INC_FLAG(0xDBA6);
- switch (GET_FLAG(0xDBA6)) {
+ case csAddr_noAnchorTimeout: // no anchor, timeout
+ SET_FLAG(dsAddr_timedCallbackState, 0);
+ fnGetOutOfLake();
+ INC_FLAG(dsAddr_lakeDivingExitMessage);
+ switch (GET_FLAG(dsAddr_lakeDivingExitMessage)) {
case 1:
- displayMessage(0x39ae);
+ displayMessage(dsAddr_seaweedMsg); // "This seaweed is just like the flowers I gave mum on her last birthday"
break;
case 2:
- displayMessage(0x39f6);
+ displayMessage(dsAddr_fishBoatMsg); // "I wonder what fish do inside this boat at night"
break;
case 3:
- displayMessage(0x3a28);
+ displayMessage(dsAddr_fishSomethingMsg); // "I think I have to fish out something down there"
break;
case 4:
- displayMessage(0x3a85);
+ displayMessage(dsAddr_notRedHerringMsg); // "I hope all this fish stuff is not a red herring"
break;
case 5:
- displayMessage(0x39ae);
+ displayMessage(dsAddr_seaweedMsg); // "This seaweed is just like the flowers I gave mum on her last birthday"
break;
default:
- displayMessage(0x3ab7);
+ displayMessage(dsAddr_niceDownMsg); // "It's nice down there"
+ break;
}
- return true;
+ break;
- case 0x99e0: //success getting an anchor
- SET_FLAG(0, 0);
- setTimerCallback(0, 0);
- scene->getActorAnimation()->free();
- playSound(64, 7);
- playActorAnimation(618);
- disableObject(5);
- setOns(0, 0);
- playSound(31, 1);
- playActorAnimation(619);
- processCallback(0x9a7a);
- inventory->add(42);
- displayMessage(0x3989);
- return true;
+ case csAddr_gotAnchor:
+ fnGotAnchor();
+ break;
- case 0x9a7a:
- loadScene(15, 156, 180, 3);
- playSound(5, 5);
- playSound(38, 14);
- playSound(38, 20);
- playSound(5, 25);
- playActorAnimation(616);
- return true;
+ case csAddr_getOutOfLake:
+ fnGetOutOfLake();
+ break;
- case 0x9aca:
+ case csAddr_digMansionWall:
if (scene->getId() == 13) {
moveTo(172, 181, 1);
playSound(26, 19);
for (uint i = 0; i < 8; ++i)
playSound(26, 30 + i * 11);
playActorAnimation(661);
- displayCutsceneMessage(0x3c80, 30484);
+ displayCutsceneMessage(dsAddr_cutsceneMsgA, 84, 95); // "Hundred moments later"
playSound(56, 10);
playSound(56, 21);
@@ -3974,7 +4831,7 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
waitAnimation();
setOns(1, 49);
- displayCutsceneMessage(0x3c9a, 30453);
+ displayCutsceneMessage(dsAddr_cutsceneMsgB, 53, 95); // "Another hundred moments later"
moveTo(162, 184, 0, true);
playSound(26, 6);
playSound(26, 17);
@@ -3986,27 +4843,32 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
playActorAnimation(664);
playAnimation(665, 1);
wait(100);
- displayMessage(0x3cbc);
+ displayMessage(dsAddr_foundCrudeOilMsg); // "At least I found crude oil and I'll be rich"
wait(100);
- displayMessage(0x3cea);
- inventory->remove(37);
- processCallback(0x9d45); //another mansion try
+ displayMessage(dsAddr_myLifeMsg); // "That's my life"
+ inventory->remove(kInvItemShovelAct2);
+ fnMansionIntrusionAttempt();
} else
- displayMessage(0x3c58);
- return true;
+ displayMessage(dsAddr_notThinkRightPlaceMsg); // "I don't think this is the right place"
+ break;
- case 0x9c6d:
- displayMessage(0x49d1);
- SET_FLAG(0xDBB5, 1);
- return false;
+ case csAddr_tooDarkHere:
+ displayMessage(dsAddr_cantDoTooDarkMsg); // "I can't do anything here, it's too dark"
+ break;
+
+ case csAddr_examineBanknote:
+ displayMessage(dsAddr_bankNoteMsg); // "It's a note from some bank..."
+ SET_FLAG(dsAddr_examinedBanknoteFlag, 1);
+ retVal = false;
+ break;
- case 0x9c79: //use pills
+ case csAddr_useTimePills: // use pills
if (scene->getId() != 36) {
- displayMessage(0x52a9);
- } else if (CHECK_FLAG(0xDBF1, 1)) {
- displayMessage(0x52F6);
+ displayMessage(dsAddr_notTryNowMsg); // "There's no need to try them now"
+ } else if (CHECK_FLAG(dsAddr_mansionAlreadyUsedTimePillsFlag, 1)) {
+ displayMessage(dsAddr_nahMsg); // "Nah"
} else {
- SET_FLAG(0xDBF1, 1);
+ SET_FLAG(dsAddr_mansionAlreadyUsedTimePillsFlag, 1);
moveTo(102, 195, 2);
playSound(5, 3);
playSound(75, 12);
@@ -4020,131 +4882,59 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
{
Walkbox *w = scene->getWalkbox(0);
w->rect.left = 0;
- w->rect.bottom = 199;
+ w->rect.bottom = kScreenHeight-1;
w->save();
}
setLan(1, 0xff);
- Dialog::showMark(scene, 0x58a9);
+ dialog->showMark(130, scene);
Object *obj = scene->getObject(1);
- obj->actor_rect.left = obj->actor_rect.right = 270;
- obj->actor_rect.top = obj->actor_rect.bottom = 193;
- obj->actor_orientation = 2;
+ obj->actorRect.left = obj->actorRect.right = 270;
+ obj->actorRect.top = obj->actorRect.bottom = 193;
+ obj->actorOrientation = 2;
obj->save();
obj = scene->getObject(3);
- obj->actor_rect.left = obj->actor_rect.right = 254;
- obj->actor_rect.top = obj->actor_rect.bottom = 193;
- obj->actor_orientation = 1;
+ obj->actorRect.left = obj->actorRect.right = 254;
+ obj->actorRect.top = obj->actorRect.bottom = 193;
+ obj->actorOrientation = 1;
obj->save();
- SET_FLAG(0xDBD7, 1);
+ SET_FLAG(dsAddr_MansionThruFanByTimePillFlag, 1);
}
- return true;
+ break;
- case 0x9d45: {
- wait(50);
- byte attempts = ++ *(res->dseg.ptr(0xDBEA));
- debug(0, "mansion intrusion attempt #%u", attempts);
- if (attempts >= 7)
- return false;
+ case csAddr_mansionIntrusionAttempt:
+ retVal = fnMansionIntrusionAttempt();
+ break;
- uint16 ptr = res->dseg.get_word((attempts - 2) * 2 + 0x6035);
- debug(0, "mansion callback = %04x", ptr);
- byte id = scene->getId();
+ case csAddr_secondMansionIntrusion:
+ fnSecondMansionIntrusion();
+ break;
- playMusic(11);
- displayCutsceneMessage(0x580a, 30484);
- processCallback(ptr);
- playMusic(6);
- if (getFlag(0xdbec) != 1 || ptr != 0x9f3e) //ptr check eq. scene_id == 11
- loadScene(id, scene->getPosition());
- return true;
- }
+ case csAddr_thirdMansionIntrusion:
+ fnThirdMansionIntrusion();
+ break;
- case 0x9d90:
- hideActor();
- loadScene(34, scene->getPosition());
- playAnimation(986, 0, true);
- playAnimation(987, 1, true);
- waitAnimation();
- Dialog::show(scene, 0x6f60, 988, 989, 0xd9, 0xd0, 1, 2);
- playAnimation(990, 0, true);
- playAnimation(991, 1, true);
- waitAnimation();
- showActor();
- return true;
-
- case 0x9de5:
- hideActor();
- loadScene(30, scene->getPosition());
- playAnimation(887, 1);
- playAnimation(888, 2, true, true, true);
- //waitAnimation();
- Dialog::showMono(scene, 0x6fb8, 889, 0xd9, 2);
- playSound(26, 3);
- playAnimation(891, 1, true, true, true);
- playAnimation(892, 2);
- waitAnimation();
- Dialog::show(scene, 0x6ff0, 890, 889, 0xd0, 0xd9, 3, 2);
- showActor();
- return true;
-
- case 0x9e54:
- hideActor();
- loadScene(32, scene->getPosition());
- playAnimation(894, 1, true, true, true);
- playAnimation(893, 2, true);
- waitAnimation();
- Dialog::showMono(scene, 0x706e, 895, 0xd9, 3);
- playSound(75, 9);
- playAnimation(898, 1, true);
- playAnimation(897, 2, true);
- Dialog::show(scene, 0x7096, 896, 895, 0xd0, 0xd9, 2, 3);
- showActor();
- return true;
+ case csAddr_fourthMansionIntrusion:
+ fnFourthMansionIntrusion();
+ break;
- case 0x9ec3:
- hideActor();
- loadScene(29, scene->getPosition());
- playActorAnimation(901, true);
- playAnimation(900, 1, true);
- waitAnimation();
- Dialog::show(scene, 0x7161, 903, 902, 0xd0, 0xd9, 2, 3);
- for (byte i = 3; i <= 9; i += 2)
- playSound(56, i);
+ case csAddr_fifthMansionIntrusion:
+ fnFifthMansionIntrusion();
+ break;
- playActorAnimation(905, true);
- playAnimation(904, 1, true);
- Dialog::show(scene, 0x71c6, 903, 902, 0xd0, 0xd9, 2, 3);
- showActor();
- return true;
+ case csAddr_sixthMansionIntrusion:
+ fnSixthMansionIntrusion();
+ break;
- case 0x9f3e:
- hideActor();
- loadScene(35, scene->getPosition());
- playAnimation(907, 2, true);
- playAnimation(906, 3, true);
- waitAnimation();
- Dialog::show(scene, 0x7243, 908, 909, 0xd9, 0xd0, 2, 3);
- Dialog::show(scene, 0x7318, 910, 908, 0xd0, 0xd9, 3, 2);
- loadScene(11, scene->getPosition());
- showActor();
- setOns(3, 51);
- playAnimation(911, 1);
- playAnimation(899, 1);
- setFlag(0xDBEC, 1);
- reloadLan();
- wait(200);
- enableObject(8);
- setLan(2, 8);
- return true;
+ default:
+ error("unknown callback 0x%04x called", addr);
+ break;
}
- //error("invalid callback %04x called", addr);
- warning("invalid callback %04x called", addr);
- return true;
+ return retVal;
}
} // End of namespace TeenAgent
diff --git a/engines/teenagent/detection.cpp b/engines/teenagent/detection.cpp
index 2de6f49c44..0c1268a5fc 100644
--- a/engines/teenagent/detection.cpp
+++ b/engines/teenagent/detection.cpp
@@ -26,6 +26,7 @@
#include "base/plugins.h"
#include "engines/advancedDetector.h"
+#include "teenagent/resources.h"
#include "teenagent/teenagent.h"
#include "graphics/thumbnail.h"
@@ -168,7 +169,7 @@ public:
Common::String desc = buf;
- in->seek(0x777a);
+ in->seek(TeenAgent::saveStateSize);
if (!Graphics::checkThumbnailHeader(*in))
return SaveStateDescriptor(slot, desc);
diff --git a/engines/teenagent/dialog.cpp b/engines/teenagent/dialog.cpp
index 400bd7cec2..870aca6400 100644
--- a/engines/teenagent/dialog.cpp
+++ b/engines/teenagent/dialog.cpp
@@ -22,99 +22,103 @@
#include "teenagent/dialog.h"
#include "teenagent/resources.h"
#include "teenagent/scene.h"
+#include "teenagent/teenagent.h"
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
+ // 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.
+ // Similar issue occurs with Dialog 190 which is used from dialogue stack at 0x7403, rather than start of 0x7405
+ // Similar issue occurs with Dialog 0 which is used from dialogue stack at 0x0001, rather than start of 0x0000
+ if (dialogNum == 163)
+ addr -= 2;
+ show(scene, addr, animation1, animation2, color1, color2, slot1, slot2);
+}
+
void Dialog::show(Scene *scene, uint16 addr, uint16 animation1, uint16 animation2, byte color1, byte color2, byte slot1, byte slot2) {
- debug(0, "Dialog::show(%04x, %u:%u, %u:%u)", addr, slot1, animation1, slot2, animation2);
- Resources *res = Resources::instance();
+ debugC(0, kDebugDialog, "Dialog::show(%04x, %u:%u, %u:%u)", addr, slot1, animation1, slot2, animation2);
int n = 0;
Common::String message;
byte color = color1;
if (animation1 != 0) {
- SceneEvent e(SceneEvent::kPlayAnimation);
- e.animation = animation1;
- e.slot = 0xc0 | slot1; //looped, paused
- scene->push(e);
+ SceneEvent e1(SceneEvent::kPlayAnimation);
+ e1.animation = animation1;
+ e1.slot = 0xc0 | slot1; //looped, paused
+ scene->push(e1);
}
if (animation2 != 0) {
- SceneEvent e(SceneEvent::kPlayAnimation);
- e.animation = animation2;
- e.slot = 0xc0 | slot2; //looped, paused
- scene->push(e);
+ SceneEvent e2(SceneEvent::kPlayAnimation);
+ e2.animation = animation2;
+ e2.slot = 0xc0 | slot2; //looped, paused
+ scene->push(e2);
}
while (n < 4) {
- byte c = res->eseg.get_byte(addr++);
- //debug(0, "%02x: %c", c, c > 0x20? c: '.');
+ byte c = _vm->res->eseg.get_byte(addr++);
+ debugC(1, kDebugDialog, "%02x: %c", c, c > 0x20? c: '.');
switch (c) {
case 0:
++n;
switch (n) {
case 1:
- //debug(0, "new line\n");
+ debugC(1, kDebugDialog, "new line\n");
if (!message.empty())
message += '\n';
break;
case 2:
- //debug(0, "displaymessage %s", message.c_str());
+ debugC(1, kDebugDialog, "displaymessage %s", message.c_str());
if (color == color2) {
//pause animation in other slot
- {
- SceneEvent e(SceneEvent::kPauseAnimation);
- e.slot = 0x80 | slot1;
- scene->push(e);
- }
- {
- SceneEvent e(SceneEvent::kPlayAnimation);
- e.animation = animation2;
- e.slot = 0x80 | slot2;
- scene->push(e);
- }
+ SceneEvent e1(SceneEvent::kPauseAnimation);
+ e1.slot = 0x80 | slot1;
+ scene->push(e1);
+
+ SceneEvent e2(SceneEvent::kPlayAnimation);
+ e2.animation = animation2;
+ e2.slot = 0x80 | slot2;
+ scene->push(e2);
} else if (color == color1) {
//pause animation in other slot
- {
- SceneEvent e(SceneEvent::kPauseAnimation);
- e.slot = 0x80 | slot2;
- scene->push(e);
- }
- {
- SceneEvent e(SceneEvent::kPlayAnimation);
- e.animation = animation1;
- e.slot = 0x80 | slot1;
- scene->push(e);
- }
- }
+ SceneEvent e2(SceneEvent::kPauseAnimation);
+ e2.slot = 0x80 | slot2;
+ scene->push(e2);
- {
- message.trim();
- if (message.empty())
- break;
+ SceneEvent e1(SceneEvent::kPlayAnimation);
+ e1.animation = animation1;
+ e1.slot = 0x80 | slot1;
+ scene->push(e1);
+ }
- SceneEvent e(SceneEvent::kMessage);
- e.message = message;
- e.color = color;
+ message.trim();
+ if (!message.empty()) {
+ SceneEvent em(SceneEvent::kMessage);
+ em.message = message;
+ em.color = color;
if (color == color1)
- e.slot = slot1;
+ em.slot = slot1;
if (color == color2)
- e.slot = slot2;
- scene->push(e);
+ em.slot = slot2;
+ scene->push(em);
message.clear();
}
break;
case 3:
- color = color == color1 ? color2 : color1;
- //debug(0, "changing color to %02x", color);
+ color = (color == color1) ? color2 : color1;
+ debugC(1, kDebugDialog, "changing color to %02x", color);
break;
}
break;
case 0xff: {
- //fixme : wait for the next cycle of the animation
+ //FIXME : wait for the next cycle of the animation
}
break;
@@ -124,21 +128,20 @@ void Dialog::show(Scene *scene, uint16 addr, uint16 animation1, uint16 animation
}
}
- SceneEvent e(SceneEvent::kClearAnimations);
- scene->push(e);
+ SceneEvent ec(SceneEvent::kClearAnimations);
+ scene->push(ec);
}
uint16 Dialog::pop(Scene *scene, uint16 addr, uint16 animation1, uint16 animation2, byte color1, byte color2, byte slot1, byte slot2) {
- debug(0, "Dialog::pop(%04x, %u:%u, %u:%u)", addr, slot1, animation1, slot2, animation2);
- Resources *res = Resources::instance();
+ debugC(0, kDebugDialog, "Dialog::pop(%04x, %u:%u, %u:%u)", addr, slot1, animation1, slot2, animation2);
uint16 next;
do {
- next = res->dseg.get_word(addr);
+ next = _vm->res->dseg.get_word(addr);
addr += 2;
} while (next == 0);
- uint16 next2 = res->dseg.get_word(addr);
+ uint16 next2 = _vm->res->dseg.get_word(addr);
if (next2 != 0xffff)
- res->dseg.set_word(addr - 2, 0);
+ _vm->res->dseg.set_word(addr - 2, 0);
show(scene, next, animation1, animation2, color1, color2, slot1, slot2);
return next;
}
diff --git a/engines/teenagent/dialog.h b/engines/teenagent/dialog.h
index 3bb7d818c1..6672ce7206 100644
--- a/engines/teenagent/dialog.h
+++ b/engines/teenagent/dialog.h
@@ -27,20 +27,59 @@
namespace TeenAgent {
+// Text Color Symbols
+enum {
+ textColorJohnNoty = 0xd0,
+ textColorCampGuard = 0xd0,
+ textColorShockedCaptain = 0xd0,
+ textColorMark = 0xd1,
+ textColorCredits = 0xd1,
+ textColorBankGuard = 0xd7,
+ textColorGrandpa = 0xd8,
+ textColorMansionGuard = 0xd9,
+ textColorMarkEnd = 0xe3,
+ textColorProfessor = 0xe5,
+ textColorOldLady = 0xe5,
+ textColorAnne = 0xe5,
+ textColorWellEcho = 0xe5,
+ textColorSonny = 0xe5,
+ textColorEskimo = 0xe5,
+ textColorRGBBoss = 0xe7,
+ textColorGoldDriver = 0xe7,
+ textColorFortuneTeller = 0xeb,
+ textColorCaptain = 0xec,
+ textColorMike = 0xef,
+ textColorCook = 0xef,
+ textColorBarman = 0xef
+};
+
class Scene;
+class TeenAgentEngine;
+
class Dialog {
public:
- static uint16 pop(Scene *scene, uint16 addr, uint16 animation1, uint16 animation2, byte color1, byte color2, byte slot1, byte slot2);
- static uint16 popMark(Scene *scene, uint16 addr) {
- return pop(scene, addr, 0, 0, 0xd1, 0xd1, 0, 0);
+ Dialog(TeenAgentEngine *vm) : _vm(vm) { }
+
+ uint16 pop(Scene *scene, uint16 addr, uint16 animation1, uint16 animation2, byte color1, byte color2, byte slot1, byte slot2);
+
+ uint16 popMark(Scene *scene, uint16 addr) {
+ return pop(scene, addr, 0, 0, textColorMark, textColorMark, 0, 0);
}
- static void show(Scene *scene, uint16 addr, uint16 animation1, uint16 animation2, byte color1, byte color2, byte slot1, byte slot2);
- static void showMono(Scene *scene, uint16 addr, uint16 animation, byte color, byte slot) {
- show(scene, addr, animation, animation, color, color, slot, slot);
+
+ void show(uint16 dialogNum, Scene *scene, uint16 animation1, uint16 animation2, byte color1, byte color2, byte slot1, byte slot2);
+
+ void showMono(uint16 dialogNum, Scene *scene, uint16 animation, byte color, byte slot) {
+ show(dialogNum, scene, animation, animation, color, color, slot, slot);
}
- static void showMark(Scene *scene, uint16 addr) {
- show(scene, addr, 0, 0, 0xd1, 0xd1, 0, 0);
+
+ void showMark(uint16 dialogNum, Scene *scene) {
+ show(dialogNum, scene, 0, 0, textColorMark, textColorMark, 0, 0);
}
+
+private:
+ TeenAgentEngine *_vm;
+
+ void show(Scene *scene, uint16 addr, uint16 animation1, uint16 animation2, byte color1, byte color2, byte slot1, byte slot2);
};
} // End of namespace TeenAgent
diff --git a/engines/teenagent/font.cpp b/engines/teenagent/font.cpp
index f7558b60f2..47f52ff90f 100644
--- a/engines/teenagent/font.cpp
+++ b/engines/teenagent/font.cpp
@@ -20,8 +20,10 @@
*/
#include "teenagent/font.h"
+
#include "teenagent/pack.h"
-#include "common/debug.h"
+#include "teenagent/teenagent.h"
+
#include "common/endian.h"
#include "common/stream.h"
#include "common/textconsole.h"
@@ -30,34 +32,41 @@
namespace TeenAgent {
-Font::Font() : grid_color(0xd0), shadow_color(0), height(0), width_pack(0), data(0) {
+Font::Font() : _gridColor(0xd0), _shadowColor(0), _height(0), _widthPack(0), _data(0) {
+}
+
+Font::~Font() {
+ delete[] _data;
}
-void Font::load(const Pack &pack, int id) {
- delete[] data;
- data = NULL;
+void Font::load(const Pack &pack, int id, byte height, byte widthPack) {
+ delete[] _data;
+ _data = NULL;
Common::ScopedPtr<Common::SeekableReadStream> s(pack.getStream(id));
if (!s)
error("loading font %d failed", id);
- data = new byte[s->size()];
- s->read(data, s->size());
- debug(0, "font size: %d", s->size());
+ _data = new byte[s->size()];
+ s->read(_data, s->size());
+ debugC(0, kDebugFont, "font size: %d", s->size());
+
+ _height = height;
+ _widthPack = widthPack;
}
uint Font::render(Graphics::Surface *surface, int x, int y, char c, byte color) {
unsigned idx = (unsigned char)c;
if (idx < 0x20 || idx >= 0x81) {
- debug(0, "unhandled char 0x%02x", idx);
+ debugC(0, kDebugFont, "unhandled char 0x%02x", idx);
return 0;
}
idx -= 0x20;
- byte *glyph = data + READ_LE_UINT16(data + idx * 2);
+ 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 >= 200 || x + w <= 0 || x >= 320)
- return w - width_pack;
+ if (surface == NULL || surface->pixels == NULL || y + h <= 0 || y >= kScreenHeight || x + w <= 0 || x >= kScreenWidth)
+ return w - _widthPack;
int i0 = 0, j0 = 0;
if (x < 0) {
@@ -68,7 +77,7 @@ uint Font::render(Graphics::Surface *surface, int x, int y, char c, byte color)
i0 = -y;
y = 0;
}
- //debug(0, "char %c, width: %dx%d", c, w, h);
+ debugC(0, kDebugFont, "char %c, width: %dx%d", c, w, h);
glyph += 2;
glyph += i0 * w + j0;
byte *dst = (byte *)surface->getBasePtr(x, y);
@@ -80,7 +89,7 @@ uint Font::render(Graphics::Surface *surface, int x, int y, char c, byte color)
case 0:
break;
case 1:
- dst[j] = shadow_color;
+ dst[j] = _shadowColor;
break;
case 2:
dst[j] = color;
@@ -91,57 +100,57 @@ uint Font::render(Graphics::Surface *surface, int x, int y, char c, byte color)
}
dst += surface->pitch;
}
- return w - width_pack;
+ return w - _widthPack;
}
-static uint find_in_str(const Common::String &str, char c, uint pos = 0) {
+static uint findInStr(const Common::String &str, char c, uint pos = 0) {
while (pos < str.size() && str[pos] != c) ++pos;
return pos;
}
-uint Font::render(Graphics::Surface *surface, int x, int y, const Common::String &str, byte color, bool show_grid) {
+uint Font::render(Graphics::Surface *surface, int x, int y, const Common::String &str, byte color, bool showGrid) {
if (surface != NULL) {
- uint max_w = render(NULL, 0, 0, str, false);
- if (show_grid)
- grid(surface, x - 4, y - 2, max_w + 8, 8 + 6, grid_color);
+ uint maxW = render(NULL, 0, 0, str, false);
+ if (showGrid)
+ grid(surface, x - 4, y - 2, maxW + 8, 8 + 6, _gridColor);
uint i = 0, j;
do {
- j = find_in_str(str, '\n', i);
+ j = findInStr(str, '\n', i);
Common::String line(str.c_str() + i, j - i);
- //debug(0, "line: %s", line.c_str());
+ debugC(0, kDebugFont, "line: %s", line.c_str());
- if (y + (int)height >= 0) {
+ if (y + (int)_height >= 0) {
uint w = render(NULL, 0, 0, line, false);
- int xp = x + (max_w - w) / 2;
+ int xp = x + (maxW - w) / 2;
for (uint k = 0; k < line.size(); ++k) {
xp += render(surface, xp, y, line[k], color);
}
- } else if (y >= 200)
+ } else if (y >= kScreenHeight)
break;
- y += height;
+ y += _height;
i = j + 1;
} while (i < str.size());
- return max_w;
+ return maxW;
} else {
- //surface == NULL;
- uint w = 0, max_w = 0;
+ // surface == NULL;
+ uint w = 0, maxW = 0;
for (uint i = 0; i < str.size(); ++i) {
char c = str[i];
if (c == '\n') {
- y += height;
- if (w > max_w)
- max_w = w;
+ y += _height;
+ if (w > maxW)
+ maxW = w;
w = 0;
continue;
}
w += render(NULL, 0, 0, c, color);
}
- if (w > max_w)
- max_w = w;
+ if (w > maxW)
+ maxW = w;
- return max_w;
+ return maxW;
}
}
@@ -156,8 +165,4 @@ void Font::grid(Graphics::Surface *surface, int x, int y, int w, int h, byte col
}
}
-Font::~Font() {
- delete[] data;
-}
-
} // End of namespace TeenAgent
diff --git a/engines/teenagent/font.h b/engines/teenagent/font.h
index 5146ace21f..a61f145fa6 100644
--- a/engines/teenagent/font.h
+++ b/engines/teenagent/font.h
@@ -28,20 +28,24 @@
namespace TeenAgent {
class Pack;
+
class Font {
public:
- byte grid_color, shadow_color;
- byte height, width_pack;
-
Font();
- void load(const Pack &pack, int id);
- uint render(Graphics::Surface *surface, int x, int y, const Common::String &str, byte color, bool grid = false);
+ ~Font();
+
+ void load(const Pack &pack, int id, byte height, byte widthPack);
+ uint render(Graphics::Surface *surface, int x, int y, const Common::String &str, byte color, bool showGrid = false);
uint render(Graphics::Surface *surface, int x, int y, char c, byte color);
static void grid(Graphics::Surface *surface, int x, int y, int w, int h, byte color);
- ~Font();
+ byte getHeight() { return _height; }
+ void setShadowColor(byte color) { _shadowColor = color; }
private:
- byte *data;
+ byte *_data;
+
+ byte _gridColor, _shadowColor;
+ byte _height, _widthPack;
};
} // End of namespace TeenAgent
diff --git a/engines/teenagent/inventory.cpp b/engines/teenagent/inventory.cpp
index 59dd44baa3..354371666c 100644
--- a/engines/teenagent/inventory.cpp
+++ b/engines/teenagent/inventory.cpp
@@ -24,6 +24,7 @@
#include "common/textconsole.h"
#include "teenagent/inventory.h"
+
#include "teenagent/resources.h"
#include "teenagent/objects.h"
#include "teenagent/teenagent.h"
@@ -31,47 +32,44 @@
namespace TeenAgent {
-Inventory::Inventory(TeenAgentEngine *engine) {
- _engine = engine;
+Inventory::Inventory(TeenAgentEngine *vm) : _vm(vm) {
_active = false;
FilePack varia;
varia.open("varia.res");
- {
- Common::ScopedPtr<Common::SeekableReadStream> s(varia.getStream(3));
- if (!s)
- error("no inventory background");
- debug(0, "loading inventory background...");
- _background.load(*s, Surface::kTypeOns);
- }
+ Common::ScopedPtr<Common::SeekableReadStream> s(varia.getStream(3));
+ if (!s)
+ error("no inventory background");
+ debugC(0, kDebugInventory, "loading inventory background...");
+ _background.load(*s, Surface::kTypeOns);
- uint32 items_size = varia.getSize(4);
- if (items_size == 0)
+ uint32 itemsSize = varia.getSize(4);
+ if (itemsSize == 0)
error("invalid inventory items size");
- debug(0, "loading items, size: %u", items_size);
- _items = new byte[items_size];
- varia.read(4, _items, items_size);
+ debugC(0, kDebugInventory, "loading items, size: %u", itemsSize);
+ _items = new byte[itemsSize];
+ varia.read(4, _items, itemsSize);
byte offsets = _items[0];
- assert(offsets == 92);
+ assert(offsets == kNumInventoryItems);
for (byte i = 0; i < offsets; ++i) {
_offset[i] = READ_LE_UINT16(_items + i * 2 + 1);
}
- _offset[92] = items_size;
+ _offset[kNumInventoryItems] = itemsSize;
- Resources *res = Resources::instance();
- for (byte i = 0; i <= 92; ++i) {
+ InventoryObject ioBlank;
+ _objects.push_back(ioBlank);
+ for (byte i = 0; i < kNumInventoryItems; ++i) {
InventoryObject io;
- uint16 obj_addr = res->dseg.get_word(0xc4a4 + i * 2);
- if (obj_addr != 0)
- io.load(res->dseg.ptr(obj_addr));
+ uint16 objAddr = vm->res->dseg.get_word(dsAddr_inventoryItemDataPtrTable + i * 2);
+ io.load(vm->res->dseg.ptr(objAddr));
_objects.push_back(io);
}
- _inventory = res->dseg.ptr(0xc48d);
+ _inventory = vm->res->dseg.ptr(dsAddr_inventory);
- for (int y = 0; y < 4; ++y)
+ for (int y = 0; y < 4; ++y) {
for (int x = 0; x < 6; ++x) {
int i = y * 6 + x;
_graphics[i]._rect.left = 28 + 45 * x - 1;
@@ -79,6 +77,7 @@ Inventory::Inventory(TeenAgentEngine *engine) {
_graphics[i]._rect.right = _graphics[i]._rect.left + 40;
_graphics[i]._rect.bottom = _graphics[i]._rect.top + 26;
}
+ }
varia.close();
_hoveredObj = _selectedObj = NULL;
@@ -89,7 +88,7 @@ Inventory::~Inventory() {
}
bool Inventory::has(byte item) const {
- for (int i = 0; i < 24; ++i) {
+ for (int i = 0; i < kInventorySize; ++i) {
if (_inventory[i] == item)
return true;
}
@@ -97,34 +96,34 @@ bool Inventory::has(byte item) const {
}
void Inventory::remove(byte item) {
- debug(0, "removing %u from inventory", item);
+ debugC(0, kDebugInventory, "removing %u from inventory", item);
int i;
- for (i = 0; i < 24; ++i) {
+ for (i = 0; i < kInventorySize; ++i) {
if (_inventory[i] == item) {
break;
}
}
- for (; i < 23; ++i) {
+ for (; i < (kInventorySize - 1); ++i) {
_inventory[i] = _inventory[i + 1];
_graphics[i].free();
}
- _inventory[23] = 0;
- _graphics[23].free();
+ _inventory[kInventorySize - 1] = kInvItemNoItem;
+ _graphics[kInventorySize - 1].free();
}
void Inventory::clear() {
- debug(0, "clearing inventory");
- for (int i = 0; i < 24; ++i) {
- _inventory[i] = 0;
+ debugC(0, kDebugInventory, "clearing inventory");
+ for (int i = 0; i < kInventorySize; ++i) {
+ _inventory[i] = kInvItemNoItem;
_graphics[i].free();
}
}
void Inventory::reload() {
- for (int i = 0; i < 24; ++i) {
+ for (int i = 0; i < kInventorySize; ++i) {
_graphics[i].free();
uint item = _inventory[i];
- if (item != 0)
+ if (item != kInvItemNoItem)
_graphics[i].load(this, item);
}
}
@@ -132,9 +131,9 @@ void Inventory::reload() {
void Inventory::add(byte item) {
if (has(item))
return;
- debug(0, "adding %u to inventory", item);
- for (int i = 0; i < 24; ++i) {
- if (_inventory[i] == 0) {
+ debugC(0, kDebugInventory, "adding %u to inventory", item);
+ for (int i = 0; i < kInventorySize; ++i) {
+ if (_inventory[i] == kInvItemNoItem) {
_inventory[i] = item;
return;
}
@@ -143,13 +142,14 @@ void Inventory::add(byte item) {
}
bool Inventory::tryObjectCallback(InventoryObject *obj) {
- byte id = obj->id;
- uint i = 0;
- for (byte *table = Resources::instance()->dseg.ptr(0xBB6F + 3); table[0] != 0 && i < 7; table += 3, ++i) {
- if (table[0] == id) {
+ byte objId = obj->id;
+ for (uint i = 0; i < 7; ++i) {
+ byte tableId = _vm->res->dseg.get_byte(dsAddr_objCallbackTablePtr + (3 * i));
+ uint16 callbackAddr = _vm->res->dseg.get_word(dsAddr_objCallbackTablePtr + (3 * i) + 1);
+ if (tableId == objId) {
resetSelectedObject();
activate(false);
- if (_engine->processCallback(READ_LE_UINT16(table + 1)))
+ if (_vm->processCallback(callbackAddr))
return true;
}
}
@@ -157,8 +157,6 @@ bool Inventory::tryObjectCallback(InventoryObject *obj) {
}
bool Inventory::processEvent(const Common::Event &event) {
- Resources *res = Resources::instance();
-
switch (event.type) {
case Common::EVENT_MOUSEMOVE:
@@ -178,9 +176,9 @@ bool Inventory::processEvent(const Common::Event &event) {
_mouse = event.mouse;
_hoveredObj = NULL;
- for (int i = 0; i < 24; ++i) {
+ for (int i = 0; i < kInventorySize; ++i) {
byte item = _inventory[i];
- if (item == 0)
+ if (item == kInvItemNoItem)
continue;
_graphics[i]._hovered = _graphics[i]._rect.in(_mouse);
@@ -197,14 +195,14 @@ bool Inventory::processEvent(const Common::Event &event) {
if (_hoveredObj == NULL)
return true;
- debug(0, "lclick on %u:%s", _hoveredObj->id, _hoveredObj->name.c_str());
+ debugC(0, kDebugInventory, "lclick on %u:%s", _hoveredObj->id, _hoveredObj->name.c_str());
if (_selectedObj == NULL) {
if (tryObjectCallback(_hoveredObj))
return true;
//activate(false);
- int w = res->font7.render(NULL, 0, 0, _hoveredObj->description, 0xd1);
- _engine->scene->displayMessage(_hoveredObj->description, 0xd1, Common::Point((320 - w) / 2, 162));
+ int w = _vm->res->font7.render(NULL, 0, 0, _hoveredObj->description, textColorMark);
+ _vm->scene->displayMessage(_hoveredObj->description, textColorMark, Common::Point((kScreenWidth - w) / 2, 162));
return true;
}
@@ -213,30 +211,27 @@ bool Inventory::processEvent(const Common::Event &event) {
if (id1 == id2)
return true;
- debug(0, "combine(%u, %u)!", id1, id2);
- byte *table = res->dseg.ptr(0xC335);
+ debugC(0, kDebugInventory, "combine(%u, %u)!", id1, id2);
+ byte *table = _vm->res->dseg.ptr(dsAddr_objCombiningTablePtr);
while (table[0] != 0 && table[1] != 0) {
- if (
- (id1 == table[0] && id2 == table[1]) ||
- (id2 == table[0] && id1 == table[1])
- ) {
- byte new_obj = table[2];
- if (new_obj != 0) {
+ if ((id1 == table[0] && id2 == table[1]) || (id2 == table[0] && id1 == table[1])) {
+ byte newObj = table[2];
+ if (newObj != 0) {
remove(id1);
remove(id2);
- debug(0, "adding object %u", new_obj);
- add(new_obj);
- _engine->playSoundNow(69);
+ debugC(0, kDebugInventory, "adding object %u", newObj);
+ add(newObj);
+ _vm->playSoundNow(69);
}
uint16 msg = READ_LE_UINT16(table + 3);
- _engine->displayMessage(msg);
+ _vm->displayMessage(msg);
activate(false);
resetSelectedObject();
return true;
}
table += 5;
}
- _engine->displayMessage(0xc3e2);
+ _vm->displayMessage(dsAddr_objCombineErrorMsg);
activate(false);
resetSelectedObject();
return true;
@@ -247,14 +242,15 @@ bool Inventory::processEvent(const Common::Event &event) {
return false;
if (_hoveredObj != NULL) {
- debug(0, "rclick object %u:%s", _hoveredObj->id, _hoveredObj->name.c_str());
- if (_hoveredObj->id != 51 && tryObjectCallback(_hoveredObj)) //do not process callback for banknote on r-click
+ debugC(0, kDebugInventory, "rclick object %u:%s", _hoveredObj->id, _hoveredObj->name.c_str());
+ // do not process callback for banknote on r-click
+ if (_hoveredObj->id != kInvItemBanknote && tryObjectCallback(_hoveredObj))
return true;
}
_selectedObj = _hoveredObj;
if (_selectedObj)
- debug(0, "selected object %s", _selectedObj->name.c_str());
+ debugC(0, kDebugInventory, "selected object %s", _selectedObj->name.c_str());
return true;
case Common::EVENT_KEYDOWN:
@@ -262,7 +258,7 @@ bool Inventory::processEvent(const Common::Event &event) {
activate(false);
return true;
}
- if (event.kbd.keycode == Common::KEYCODE_RETURN) { //triangle button on psp
+ if (event.kbd.keycode == Common::KEYCODE_RETURN) {
activate(!_active);
return true;
}
@@ -277,7 +273,6 @@ bool Inventory::processEvent(const Common::Event &event) {
}
}
-
void Inventory::Item::free() {
_animation.free();
_surface.free();
@@ -294,30 +289,29 @@ void Inventory::Item::backgroundEffect(Graphics::Surface *s) {
}
}
-void Inventory::Item::load(Inventory *inventory, uint item_id) {
- InventoryObject *obj = &inventory->_objects[item_id];
+void Inventory::Item::load(Inventory *inventory, uint itemId) {
+ InventoryObject *obj = &inventory->_objects[itemId];
if (obj->animated) {
if (_animation.empty()) {
- debug(0, "loading item %d from offset %x", obj->id, inventory->_offset[obj->id - 1]);
+ debugC(0, kDebugInventory, "loading item %d from offset %x", obj->id, inventory->_offset[obj->id - 1]);
Common::MemoryReadStream s(inventory->_items + inventory->_offset[obj->id - 1], inventory->_offset[obj->id] - inventory->_offset[obj->id - 1]);
_animation.load(s, Animation::kTypeInventory);
}
} else {
if (_surface.empty()) {
- debug(0, "loading item %d from offset %x", obj->id, inventory->_offset[obj->id - 1]);
+ debugC(0, kDebugInventory, "loading item %d from offset %x", obj->id, inventory->_offset[obj->id - 1]);
Common::MemoryReadStream s(inventory->_items + inventory->_offset[obj->id - 1], inventory->_offset[obj->id] - inventory->_offset[obj->id - 1]);
_surface.load(s, Surface::kTypeOns);
}
}
}
-void Inventory::Item::render(Inventory *inventory, uint item_id, Graphics::Surface *dst, int delta) {
- InventoryObject *obj = &inventory->_objects[item_id];
- Resources *res = Resources::instance();
+void Inventory::Item::render(Inventory *inventory, uint itemId, Graphics::Surface *dst, int delta) {
+ InventoryObject *obj = &inventory->_objects[itemId];
backgroundEffect(dst);
_rect.render(dst, _hovered ? 233 : 234);
- load(inventory, item_id);
+ load(inventory, itemId);
if (obj->animated) {
if (_hovered) {
Surface *s = _animation.currentFrame(delta);
@@ -342,15 +336,16 @@ void Inventory::Item::render(Inventory *inventory, uint item_id, Graphics::Surfa
if (inventory->_selectedObj != inventory->_hoveredObj)
name += obj->name;
- if (_hovered && inventory->_engine->scene->getMessage().empty()) {
- int w = res->font7.render(NULL, 0, 0, name, 0xd1, true);
- res->font7.render(dst, (320 - w) / 2, 180, name, 0xd1, true);
+ if (_hovered && inventory->_vm->scene->getMessage().empty()) {
+ int w = inventory->_vm->res->font7.render(NULL, 0, 0, name, textColorMark, true);
+ inventory->_vm->res->font7.render(dst, (kScreenWidth - w) / 2, 180, name, textColorMark, true);
}
}
void Inventory::render(Graphics::Surface *surface, int delta) {
if (!_active)
return;
+ debugC(0, kDebugInventory, "Inventory::render()");
_background.render(surface);
@@ -358,11 +353,10 @@ void Inventory::render(Graphics::Surface *surface, int delta) {
for (int x = 0; x < 6; x++) {
int idx = x + 6 * y;
byte item = _inventory[idx];
- if (item == 0)
- continue;
-
- //debug(0, "%d,%d -> %u", x0, y0, item);
- _graphics[idx].render(this, item, surface, delta);
+ if (item != 0) {
+ debugC(0, kDebugInventory, "\t(x, y): %d,%d -> item: %u", x, y, item);
+ _graphics[idx].render(this, item, surface, delta);
+ }
}
}
}
diff --git a/engines/teenagent/inventory.h b/engines/teenagent/inventory.h
index 61e5364542..d487848c2c 100644
--- a/engines/teenagent/inventory.h
+++ b/engines/teenagent/inventory.h
@@ -33,9 +33,112 @@ namespace TeenAgent {
struct InventoryObject;
class TeenAgentEngine;
+// Maximum number of items found within game
+const uint8 kNumInventoryItems = 92;
+
+// Inventory Item Ids
+enum {
+ kInvItemNoItem = 0, // No item i.e. empty inventory slot
+ kInvItemFeather = 1,
+ kInvItemShotgun = 2,
+ kInvItemToolboxFull = 3, // Contains Car Jack and Spanner
+ kInvItemToolboxHalfEmpty = 4, // Contains Spanner
+ kInvItemSpanner = 5,
+ kInvItemComb = 6,
+ kInvItemFan = 7,
+ kInvItemBrokenPaddle = 8,
+ kInvItemPaddle = 9, // Repaired - BrokenPaddle combined with Branch (with Glue)
+ kInvItemFirstFlower = 10, // Smells nice
+ kInvItemSecondFlower = 11, // Really beautiful
+ kInvItemFeatherDusterClean = 12,
+ kInvItemChainsaw = 13, // Unfueled
+ kInvItemDrunkenChainsaw = 14, // Fueled with Whisky (Chainsaw combined with Whiskey)
+ kInvItemBranch = 15,
+ kInvItemWhisky = 16,
+ kInvItemNeedle = 17,
+ kInvItemWrapper = 18,
+ kInvItemChocCandy = 19,
+ kInvItemPotato = 20,
+ kInvItemRakeBroken = 21,
+ kInvItemHeartShapedCandy = 22,
+ kInvItemWrappedCandy = 23, // HeartShapedCandy combined with Wrapper
+ kInvItemRibbon = 24,
+ kInvItemRakeFixed = 25, // Rake combined with Ribbon
+ kInvItemNut = 26,
+ kInvItemPlasticApple = 27,
+ kInvItemCone = 28,
+ kInvItemSuperGlue = 29,
+ kInvItemConeAndNeedle = 30, // Cone combined with Needle
+ kInvItemConeAndFeather = 31, // Cone combined with Feather
+ kInvItemDart = 32, // Needle combined with ConeAndFeather or Feather combined with ConeAndNeedle
+ kInvItemFeatherDusterDirty = 33,
+ kInvItemPaintedPotato = 34, // Potato combined with Dirty Feather Duster (Soot)
+ kInvItemCarJack = 35,
+ kInvItemBone = 36,
+ kInvItemShovelAct2 = 37,
+ kInvItemRopeAct2 = 38,
+ kInvItemMask = 39,
+ kInvItemFins = 40,
+ kInvItemDiveEquipment = 41, // Mask combined with Fins
+ kInvItemAnchor = 42,
+ kInvItemGrapplingHook = 43,
+ kInvItemSickleBlunt = 44,
+ kInvItemCheese = 45,
+ kInvItemSickleSharp = 46,
+ kInvItemHandkerchief = 47,
+ kInvItemMouse = 48,
+ kInvItemRock = 49,
+ kInvItemNugget = 50,
+ kInvItemBanknote = 51,
+ kInvItemDictaphoneNoBatteries = 52,
+ kInvItemPolaroidCamera = 53,
+ kInvItemVideoTape = 54,
+ kInvItemSheetOfPaper = 55,
+ kInvItemCognac = 56,
+ kInvItemRemoteControl = 57,
+ kInvItemIceTongs = 58,
+ kInvItemCork = 59,
+ kInvItemWrappedCork = 60, // Cork combined with Sheet Of Paper
+ kInvItemPhoto = 61,
+ kInvItemChilliWithLabel = 62,
+ kInvItemPastryRoller = 63,
+ kInvItemFakeChilli = 64,
+ kInvItemLabel = 65,
+ kInvItemBatteries = 66,
+ kInvItemDictaphoneWithBatteries = 67, // Dictaphone combined with Batteries
+ kInvItemBurningPaper = 68,
+ kInvItemMeat = 69,
+ kInvItemPlasticBag = 70,
+ kInvItemSocks = 71,
+ kInvItemTimePills = 72,
+ kInvItemHandle = 73,
+ kInvItemChilliNoLabel = 74,
+ kInvItemPass = 75,
+ kInvItemBulb = 76,
+ kInvItemJailKey = 77,
+ kInvItemDelicatePlant = 78,
+ kInvItemSwissArmyKnife = 79,
+ kInvItemSpring = 80,
+ kInvItemShovelAct1 = 81,
+ kInvItemKaleidoscope = 82,
+ kInvItemSoldierNews = 83,
+ kInvItemGrenade = 84,
+ kInvItemMug = 85, // Empty
+ kInvItemMugOfMud = 86, // Full of mud
+ kInvItemCrumbs = 87,
+ kInvItemRopeAct1 = 88,
+ kInvItemRopeAndGrenade = 89, // Rope combined with Grenade
+ kInvItemMedicine = 90,
+ kInvItemDruggedFood = 91, // Crumbs combined with Medicine
+ kInvItemBird = 92
+};
+
+// Maximum number of inventory items held by Ego (Mark)
+const uint8 kInventorySize = 24;
+
class Inventory {
public:
- Inventory(TeenAgentEngine *engine);
+ Inventory(TeenAgentEngine *vm);
~Inventory();
void render(Graphics::Surface *surface, int delta);
@@ -55,10 +158,10 @@ public:
void resetSelectedObject() { _selectedObj = NULL; }
private:
- TeenAgentEngine *_engine;
+ TeenAgentEngine *_vm;
Surface _background;
byte *_items;
- uint _offset[93];
+ uint _offset[kNumInventoryItems+1];
Common::Array<InventoryObject> _objects;
byte *_inventory;
@@ -71,12 +174,12 @@ private:
Item() : _hovered(false) {}
void free();
- void load(Inventory *inventory, uint item_id);
+ void load(Inventory *inventory, uint itemId);
void backgroundEffect(Graphics::Surface *s);
- void render(Inventory *inventory, uint item_id, Graphics::Surface *surface, int delta);
+ void render(Inventory *inventory, uint itemId, Graphics::Surface *surface, int delta);
};
- Item _graphics[24];
+ Item _graphics[kInventorySize];
bool _active;
Common::Point _mouse;
diff --git a/engines/teenagent/music.cpp b/engines/teenagent/music.cpp
index 1f44e9cfcb..b06a5f1f5e 100644
--- a/engines/teenagent/music.cpp
+++ b/engines/teenagent/music.cpp
@@ -22,6 +22,8 @@
#include "teenagent/music.h"
#include "teenagent/resources.h"
+#include "teenagent/teenagent.h"
+
#include "common/debug.h"
#include "common/ptr.h"
#include "common/textconsole.h"
@@ -34,36 +36,36 @@ static const uint32 noteToPeriod[3][12] = {
{214, 201, 189, 179, 170, 160, 151, 143, 135, 127, 120, 113}
};
-MusicPlayer::MusicPlayer() : Paula(false, 44100, 5000), _id(0) {
+MusicPlayer::MusicPlayer(TeenAgentEngine *vm) : Paula(false, 44100, 5000), _vm(vm), _id(0) {
}
MusicPlayer::~MusicPlayer() {
+ stop();
}
bool MusicPlayer::load(int id) {
- Resources *res = Resources::instance();
-
- Common::ScopedPtr<Common::SeekableReadStream> stream(res->mmm.getStream(id));
+ debugC(0, kDebugMusic, "MusicPlayer::load(%d)", id);
+ Common::ScopedPtr<Common::SeekableReadStream> stream(_vm->res->mmm.getStream(id));
if (!stream)
return false;
char header[4];
stream->read(header, 4);
- //check header?
+ // check header?
Common::StackLock lock(_mutex);
// Load the samples
sampleCount = stream->readByte();
- debug(0, "sampleCount = %d", sampleCount);
+ debugC(0, kDebugMusic, "sampleCount = %d", sampleCount);
for (byte currSample = 0; currSample < sampleCount; currSample++) {
byte sample = stream->readByte();
// Load the sample data
- byte sampleResource = ((sample >> 4) & 0x0F) * 10 + (sample & 0x0F);
- debug(0, "currSample = %d, sample = 0x%02x, resource: %d", currSample, sample, sampleResource);
- uint32 sampleSize = res->sam_mmm.getSize(sampleResource);
+ byte sampleResource = ((sample >> 4) & 0x0f) * 10 + (sample & 0x0f);
+ debugC(0, kDebugMusic, "currSample = %d, sample = 0x%02x, resource: %d", currSample, sample, sampleResource);
+ uint32 sampleSize = _vm->res->sam_mmm.getSize(sampleResource);
if (sampleSize == 0) {
warning("load: invalid sample %d (0x%02x)", sample, sample);
_samples[sample].clear();
@@ -71,7 +73,7 @@ bool MusicPlayer::load(int id) {
}
_samples[sample].resize(sampleSize);
- res->sam_mmm.read(sampleResource, _samples[sample].data, sampleSize);
+ _vm->res->sam_mmm.read(sampleResource, _samples[sample].data, sampleSize);
}
// Load the music data
@@ -87,17 +89,17 @@ bool MusicPlayer::load(int id) {
row.channels[1].note = stream->readByte();
row.channels[2].note = stream->readByte();
_rows.push_back(row);
- } else if ((cmd & 0xF0) == 0x50) {
+ } else if ((cmd & 0xf0) == 0x50) {
byte sample = stream->readByte();
- //debug(1, "%02x: set sample %02x", cmd, sample);
- row.channels[(cmd & 0x0F) - 1].sample = sample;
- } else if ((cmd & 0xF0) == 0x40) {
+ debugC(1, kDebugMusic, "%02x: set sample %02x", cmd, sample);
+ row.channels[(cmd & 0x0f) - 1].sample = sample;
+ } else if ((cmd & 0xf0) == 0x40) {
byte vol = stream->readByte();
- //debug(1, "%02x: set volume %02x -> %02x", cmd, row.channels[(cmd & 0x0F) - 1].volume, vol);
- //channel volume 0x40 * music volume 0x40 mixed with high bytes
- row.channels[(cmd & 0x0F) - 1].volume = vol * 16;
+ debugC(1, kDebugMusic, "%02x: set volume %02x -> %02x", cmd, row.channels[(cmd & 0x0f) - 1].volume, vol);
+ // channel volume 0x40 * music volume 0x40 mixed with high bytes
+ row.channels[(cmd & 0x0f) - 1].volume = vol * 16;
} else {
- debug(0, "unhandled music command %02x", cmd);
+ debugC(0, kDebugMusic, "unhandled music command %02x", cmd);
}
}
_currRow = 0;
@@ -124,13 +126,13 @@ void MusicPlayer::interrupt() {
for (int chn = 0; chn < 3; ++chn) {
setChannelVolume(chn, row->channels[chn].volume);
- //debug(0, "row->channels[%d].volume = %d", chn, row->channels[chn].volume);
+ debugC(2, kDebugMusic, "row->channels[%d].volume = %d", chn, row->channels[chn].volume);
byte sample = (row->channels[chn].sample);
if (row->channels[chn].note != 0 && sample != 0) {
- //debug(0, "row->channels[%d].note = %d", chn, row->channels[chn].note);
- //debug(0, "row->channels[%d].sample = %d", chn, row->channels[chn].sample);
+ debugC(2, kDebugMusic, "row->channels[%d].note = %d", chn, row->channels[chn].note);
+ debugC(2, kDebugMusic, "row->channels[%d].sample = %d", chn, row->channels[chn].sample);
byte note = row->channels[chn].note;
if (_samples[sample].size == 0) {
@@ -139,11 +141,11 @@ void MusicPlayer::interrupt() {
}
setChannelData(chn, (const int8 *)_samples[sample].data, NULL, _samples[sample].size, 0);
- setChannelPeriod(chn, noteToPeriod[((note >> 4) & 0x0F) - 1][(note & 0x0F)]);
+ setChannelPeriod(chn, noteToPeriod[((note >> 4) & 0x0f) - 1][(note & 0x0f)]);
}
}
- //debug(0, "------------------------------------------------");
+ debugC(2, kDebugMusic, "------------------------------------------------");
++_currRow;
}
diff --git a/engines/teenagent/music.h b/engines/teenagent/music.h
index 22b4fa5e8e..408436cf3a 100644
--- a/engines/teenagent/music.h
+++ b/engines/teenagent/music.h
@@ -28,10 +28,11 @@
namespace TeenAgent {
+class TeenAgentEngine;
+
class MusicPlayer : public Audio::Paula {
public:
-
- MusicPlayer();
+ MusicPlayer(TeenAgentEngine *vm);
~MusicPlayer();
bool load(int id);
@@ -41,6 +42,8 @@ public:
void stop();
private:
+ TeenAgentEngine *_vm;
+
int _id;
struct Row {
diff --git a/engines/teenagent/objects.cpp b/engines/teenagent/objects.cpp
index 748f342d54..5dad9ab99d 100644
--- a/engines/teenagent/objects.cpp
+++ b/engines/teenagent/objects.cpp
@@ -21,8 +21,10 @@
#include "common/debug.h"
#include "common/memstream.h"
+
#include "teenagent/objects.h"
#include "teenagent/resources.h"
+#include "teenagent/teenagent.h"
namespace TeenAgent {
@@ -51,7 +53,6 @@ void Rect::render(Graphics::Surface *surface, uint8 color) const {
surface->vLine(right, bottom, top, color);
}
-
void Object::load(byte *src) {
_base = src;
@@ -59,39 +60,39 @@ void Object::load(byte *src) {
rect.load(src);
src += 8;
- actor_rect.load(src);
+ actorRect.load(src);
src += 8;
- actor_orientation = *src++;
+ actorOrientation = *src++;
enabled = *src++;
name = (const char *)src;
- description = parse_description((const char *)src);
+ description = parseDescription((const char *)src);
}
void Object::save() const {
assert(_base != NULL);
rect.save();
- actor_rect.save();
- _base[17] = actor_orientation;
+ actorRect.save();
+ _base[17] = actorOrientation;
_base[18] = enabled;
}
-void Object::setName(const Common::String &new_name) {
+void Object::setName(const Common::String &newName) {
assert(_base != 0);
- strcpy((char *)(_base + 19), new_name.c_str());
- name = new_name;
+ strcpy((char *)(_base + 19), newName.c_str());
+ name = newName;
}
void Object::dump(int level) const {
- debug(level, "object: %u %u [%u,%u,%u,%u], actor: [%u,%u,%u,%u], orientation: %u, name: %s", id, enabled,
+ debugC(level, kDebugObject, "object: %u %u [%u,%u,%u,%u], actor: [%u,%u,%u,%u], orientation: %u, name: %s", id, enabled,
rect.left, rect.top, rect.right, rect.bottom,
- actor_rect.left, actor_rect.top, actor_rect.right, actor_rect.bottom,
- actor_orientation, name.c_str()
+ actorRect.left, actorRect.top, actorRect.right, actorRect.bottom,
+ actorOrientation, name.c_str()
);
}
-Common::String Object::parse_description(const char *name) {
+Common::String Object::parseDescription(const char *name) {
const char *desc = name + strlen(name) + 1;
if (*desc == 0)
return Common::String();
@@ -101,7 +102,7 @@ Common::String Object::parse_description(const char *name) {
while (*desc != 1 && *desc != 0) {
Common::String line;
while (*desc != 1 && *desc != 0) {
- //debug(0, "%02x ", *desc);
+ debugC(2, kDebugObject, "%02x ", *desc);
line += *desc++;
}
@@ -115,7 +116,7 @@ Common::String Object::parse_description(const char *name) {
if (!result.empty())
result.deleteLastChar();
else
- result = "Cool.";
+ result = "Cool."; // FIXME - Use dsAddr_coolMsg ?
return result;
}
@@ -124,31 +125,31 @@ void InventoryObject::load(byte *src) {
id = *src++;
animated = *src++;
name = (const char *)src;
- description = Object::parse_description((const char *)src);
+ description = Object::parseDescription((const char *)src);
}
void UseHotspot::load(byte *src) {
Common::MemoryReadStream in(src, 9);
- inventory_id = in.readByte();
- object_id = in.readByte();
+ inventoryId = in.readByte();
+ objectId = in.readByte();
orientation = in.readByte();
- actor_x = in.readUint16LE();
- actor_y = in.readUint16LE();
+ actorX = in.readUint16LE();
+ actorY = in.readUint16LE();
callback = in.readUint16LE();
}
void UseHotspot::dump(int level) const {
- debug(level,
- "hotspot: inv_id: %02x, obj_id: %02x, orientation?: %02x, actor position: (%d,%d), callback: %04x",
- inventory_id, object_id, orientation, actor_x, actor_y, callback
+ debugC(level, kDebugObject,
+ "hotspot: invId: %02x, objId: %02x, orientation: %02x, actor position: (%d,%d), callback: %04x",
+ inventoryId, objectId, orientation, actorX, actorY, callback
);
}
void Walkbox::dump(int level) const {
- debug(level, "walkbox %02x %02x [%d, %d, %d, %d] top: %u, right: %u, bottom: %u, left: %u",
+ debugC(level, kDebugObject, "walkbox %02x %02x [%d, %d, %d, %d] top: %u, right: %u, bottom: %u, left: %u",
type, orientation,
rect.left, rect.top, rect.right, rect.bottom,
- side_hint[0], side_hint[1], side_hint[2], side_hint[3]);
+ sideHint[0], sideHint[1], sideHint[2], sideHint[3]);
}
void Walkbox::load(byte *src) {
@@ -159,7 +160,7 @@ void Walkbox::load(byte *src) {
rect.load(src);
src += 8;
for (byte i = 0; i < 4; ++i)
- side_hint[i] = *src++;
+ sideHint[i] = *src++;
}
void Walkbox::save() const {
diff --git a/engines/teenagent/objects.h b/engines/teenagent/objects.h
index 555287fc56..6e7955766f 100644
--- a/engines/teenagent/objects.h
+++ b/engines/teenagent/objects.h
@@ -26,6 +26,8 @@
#include "common/rect.h"
#include "graphics/surface.h"
+#include "teenagent/teenagent.h"
+
namespace TeenAgent {
enum {kActorUp = 1, kActorRight = 2, kActorDown = 3, kActorLeft = 4 };
@@ -46,13 +48,13 @@ struct Rect {
}
inline bool valid() const {
- return left >= 0 && left < 320 && right >= 0 && right < 320 && top >= 0 && top < 200 && bottom >= 0 && bottom < 200;
+ return left >= 0 && left < kScreenWidth && right >= 0 && right < kScreenWidth && top >= 0 && top < kScreenHeight && bottom >= 0 && bottom < kScreenHeight;
}
void render(Graphics::Surface *surface, uint8 color) const;
void dump(int level = 0) const {
- debug(level, "rect[%u, %u, %u, %u]", left, top, right, bottom);
+ debugC(level, kDebugObject, "rect[%u, %u, %u, %u]", left, top, right, bottom);
}
inline void clear() {
@@ -154,22 +156,21 @@ protected:
};
struct Object {
-
byte id; //0
Rect rect; //1
- Rect actor_rect; //9
- byte actor_orientation; //17
+ Rect actorRect; //9
+ byte actorOrientation; //17
byte enabled; //18
//19
Common::String name, description;
Object(): _base(NULL) {}
void dump(int level = 0) const;
- void setName(const Common::String &name);
+ void setName(const Common::String &newName);
void load(byte *addr);
void save() const;
- static Common::String parse_description(const char *name);
+ static Common::String parseDescription(const char *name);
protected:
byte *_base;
@@ -188,10 +189,10 @@ protected:
};
struct UseHotspot {
- byte inventory_id;
- byte object_id;
+ byte inventoryId;
+ byte objectId;
byte orientation;
- uint16 actor_x, actor_y;
+ uint16 actorX, actorY;
uint16 callback;
void load(byte *src);
void dump(int level = 0) const;
@@ -201,7 +202,7 @@ struct Walkbox {
byte type;
byte orientation;
Rect rect;
- byte side_hint[4];
+ byte sideHint[4];
Walkbox() : _base(NULL) {}
void dump(int level = 0) const;
diff --git a/engines/teenagent/pack.cpp b/engines/teenagent/pack.cpp
index 5302e2eceb..2e6c913a72 100644
--- a/engines/teenagent/pack.cpp
+++ b/engines/teenagent/pack.cpp
@@ -20,6 +20,8 @@
*/
#include "teenagent/pack.h"
+#include "teenagent/teenagent.h"
+
#include "common/util.h"
#include "common/debug.h"
#include "common/memstream.h"
@@ -44,7 +46,7 @@ bool FilePack::open(const Common::String &filename) {
return false;
_fileCount = file.readUint32LE();
- debug(0, "opened %s, found %u entries", filename.c_str(), _fileCount);
+ debugC(0, kDebugPack, "opened %s, found %u entries", filename.c_str(), _fileCount);
offsets = new uint32[_fileCount + 1];
for (uint32 i = 0; i <= _fileCount; ++i) {
offsets[i] = file.readUint32LE();
@@ -65,18 +67,17 @@ uint32 FilePack::read(uint32 id, byte *dst, uint32 size) const {
file.seek(offsets[id - 1]);
uint32 rsize = offsets[id] - offsets[id - 1];
uint32 r = file.read(dst, MIN(rsize, size));
- //debug(0, "read(%u, %u) = %u", id, size, r);
+ debugC(0, kDebugPack, "read(%u, %u) = %u", id, size, r);
return r;
}
Common::SeekableReadStream *FilePack::getStream(uint32 id) const {
if (id < 1 || id > _fileCount)
return NULL;
- //debug(0, "stream: %04x-%04x", offsets[id - 1], offsets[id]);
+ debugC(0, kDebugPack, "stream: %04x-%04x", offsets[id - 1], offsets[id]);
return new Common::SeekableSubReadStream(&file, offsets[id - 1], offsets[id]);
}
-
TransientFilePack::TransientFilePack() : offsets(0) {}
TransientFilePack::~TransientFilePack() {
@@ -97,7 +98,7 @@ bool TransientFilePack::open(const Common::String &filename) {
return false;
_fileCount = file.readUint32LE();
- debug(0, "opened %s, found %u entries", filename.c_str(), _fileCount);
+ debugC(0, kDebugPack, "opened %s, found %u entries", filename.c_str(), _fileCount);
offsets = new uint32[_fileCount + 1];
for (uint32 i = 0; i <= _fileCount; ++i) {
offsets[i] = file.readUint32LE();
@@ -124,14 +125,14 @@ uint32 TransientFilePack::read(uint32 id, byte *dst, uint32 size) const {
uint32 rsize = offsets[id] - offsets[id - 1];
uint32 r = file.read(dst, MIN(rsize, size));
file.close();
- //debug(0, "read(%u, %u) = %u", id, size, r);
+ debugC(0, kDebugPack, "read(%u, %u) = %u", id, size, r);
return r;
}
Common::SeekableReadStream *TransientFilePack::getStream(uint32 id) const {
if (id < 1 || id > _fileCount)
return NULL;
- //debug(0, "stream: %04x-%04x", offsets[id - 1], offsets[id]);
+ debugC(0, kDebugPack, "stream: %04x-%04x", offsets[id - 1], offsets[id]);
Common::File file;
if (!file.open(_filename))
return NULL;
@@ -146,7 +147,6 @@ Common::SeekableReadStream *TransientFilePack::getStream(uint32 id) const {
return new Common::MemoryReadStream(ptr, r, DisposeAfterUse::YES);
}
-
void MemoryPack::close() {
chunks.clear();
}
@@ -157,7 +157,7 @@ bool MemoryPack::open(const Common::String &filename) {
return false;
uint32 count = file.readUint32LE();
- debug(0, "opened %s, found %u entries [memory]", filename.c_str(), count);
+ debugC(0, kDebugPack, "opened %s, found %u entries [memory]", filename.c_str(), count);
for (uint32 i = 0; i < count; ++i) {
uint32 offset = file.readUint32LE();
int32 pos = file.pos();
@@ -199,5 +199,4 @@ Common::SeekableReadStream *MemoryPack::getStream(uint32 id) const {
return new Common::MemoryReadStream(c.data, c.size, DisposeAfterUse::NO);
}
-
} // End of namespace TeenAgent
diff --git a/engines/teenagent/resources.cpp b/engines/teenagent/resources.cpp
index dff58f98e2..442d0abf16 100644
--- a/engines/teenagent/resources.cpp
+++ b/engines/teenagent/resources.cpp
@@ -27,14 +27,10 @@
namespace TeenAgent {
-Resources::Resources() {}
-
-Resources *Resources::instance() {
- static Resources i;
- return &i;
+Resources::Resources() {
}
-void Resources::deinit() {
+Resources::~Resources() {
off.close();
on.close();
ons.close();
@@ -61,6 +57,36 @@ quick note on varia resources:
11: quit shareware
*/
+#define CSEG_SIZE 46000 // 0xb3b0
+#define DSEG_SIZE 59280 // 0xe790
+#define ESEG_SIZE 35810 // 0x8be2
+
+void Resources::precomputeDialogOffsets() {
+ dialogOffsets.push_back(0);
+ int n = 0;
+ uint8 current, last = 0xff;
+ for (uint i = 0; i < eseg.size(); i++) {
+ current = eseg.get_byte(i);
+
+ if (n == 4) {
+ dialogOffsets.push_back(i);
+ n = 0;
+ }
+
+ if (current != 0x00 && last == 0x00)
+ n = 0;
+
+ if (current == 0x00)
+ n++;
+
+ last = current;
+ }
+
+ debug(1, "Resources::precomputeDialogOffsets() - Found %d dialogs", dialogOffsets.size());
+ for (uint i = 0; i < dialogOffsets.size(); i++)
+ debug(1, "\tDialog #%d: Offset 0x%04x", i, dialogOffsets[i]);
+}
+
bool Resources::loadArchives(const ADGameDescription *gd) {
Common::File *dat_file = new Common::File();
if (!dat_file->open("teenagent.dat")) {
@@ -93,18 +119,17 @@ bool Resources::loadArchives(const ADGameDescription *gd) {
}
#endif
- cseg.read(dat, 0xb3b0);
- dseg.read(dat, 0xe790);
- eseg.read(dat, 0x8be2);
+ dat->skip(CSEG_SIZE);
+ dseg.read(dat, DSEG_SIZE);
+ eseg.read(dat, ESEG_SIZE);
delete dat;
+ precomputeDialogOffsets();
+
FilePack varia;
varia.open("varia.res");
- font7.load(varia, 7);
- font7.width_pack = 1;
- font7.height = 11;
- font8.load(varia, 8);
- font8.height = 31;
+ font7.load(varia, 7, 11, 1);
+ font8.load(varia, 8, 31, 0);
varia.close();
off.open("off.res");
@@ -150,13 +175,13 @@ Common::SeekableReadStream *Resources::loadLan000(uint32 id) const {
switch (id) {
case 81:
- if (dseg.get_byte(0xDBAD))
+ if (dseg.get_byte(dsAddr_dogHasBoneFlag))
return lan500.getStream(160);
break;
case 137:
- if (dseg.get_byte(0xDBC5) == 1) {
- if (dseg.get_byte(0xDBC6) == 1)
+ if (dseg.get_byte(dsAddr_mansionTVOnFlag) == 1) {
+ if (dseg.get_byte(dsAddr_mansionVCRPlayingTapeFlag) == 1)
return lan500.getStream(203);
else
return lan500.getStream(202);
@@ -164,31 +189,31 @@ Common::SeekableReadStream *Resources::loadLan000(uint32 id) const {
break;
case 25:
- if (dseg.get_byte(0xDBDF) == 2) {
+ if (dseg.get_byte(dsAddr_FirstActTrialState) == 2) {
return lan500.getStream(332);
}
break;
case 37:
- if (dseg.get_byte(0xdbe2) == 1) {
+ if (dseg.get_byte(dsAddr_act1GuardState) == 1) {
return lan500.getStream(351);
- } else if (dseg.get_byte(0xdbe2) == 2) {
+ } else if (dseg.get_byte(dsAddr_act1GuardState) == 2) {
return lan500.getStream(364);
}
break;
case 29:
- if (dseg.get_byte(0xDBE7) == 1) {
+ if (dseg.get_byte(dsAddr_birdOnBarRadioAntennaFlag) == 1) {
return lan500.getStream(380);
}
case 30:
- if (dseg.get_byte(0xDBE7) == 1) {
+ if (dseg.get_byte(dsAddr_birdOnBarRadioAntennaFlag) == 1) {
return lan500.getStream(381);
}
case 42:
- if (dseg.get_byte(0xDBEC) == 1) {
+ if (dseg.get_byte(dsAddr_johnNotyOutsideMansionDoorFlag) == 1) {
return lan500.getStream(400);
}
}
diff --git a/engines/teenagent/resources.h b/engines/teenagent/resources.h
index 5c08a46489..7aae2f9ec8 100644
--- a/engines/teenagent/resources.h
+++ b/engines/teenagent/resources.h
@@ -31,18 +31,1144 @@ struct ADGameDescription;
namespace TeenAgent {
+// Code Segment Addresses (Read Only)
+// Intro function : 0x024c
+const uint16 csAddr_intro = 0x024c;
+// Pole Climb Fail function : 0x4173
+const uint16 csAddr_poleClimbFail = 0x4173;
+// Move Ego (Mark) To Suspicious Position function : 0x505c
+const uint16 csAddr_egoSuspiciousPosition = 0x505c;
+// Guard Scare Timeout function : 0x516d
+const uint16 csAddr_guardScareTimeout = 0x516d;
+// Guard Drinking function : 0x5189
+const uint16 csAddr_guardDrinking = 0x5189;
+// Move Ego (Mark) To Default Position function : 0x557e
+const uint16 csAddr_egoDefaultPosition = 0x557e;
+// Cave NOP function : 0x599b
+const uint16 csAddr_caveNOP = 0x599b;
+// Enter Cave function : 0x5a21
+const uint16 csAddr_enterCave = 0x5a21;
+// Ego (Mark) Scared By Spider function : 0x60b5
+const uint16 csAddr_egoScaredBySpider = 0x60b5;
+// Move to Ladder and Leave Cellar function : 0x60d9
+const uint16 csAddr_moveToLadderAndLeaveCellar = 0x60d9;
+// Leave Cellar function : 0x612b
+const uint16 csAddr_leaveCellar = 0x612b;
+// Too Dark function : 0x61fe
+const uint16 csAddr_TooDark = 0x61fe;
+// Move Ego (Mark) To Bottom-Right or Turn function : 0x6849
+const uint16 csAddr_egoBottomRightTurn = 0x6849;
+// Checking Drawers function : 0x68e6
+const uint16 csAddr_checkingDrawers = 0x68e6;
+// Drawer Open Message function : 0x6b86
+const uint16 csAddr_DrawerOpenMessage = 0x6b86;
+// Is Cook Gone function : 0x70e0
+const uint16 csAddr_isCookGone = 0x70e0;
+// Giving Flower to Old Lady function : 0x88de
+const uint16 csAddr_givingFlowerToOldLady = 0x88de;
+// Give Another Flower to Old Lady function : 0x890b
+const uint16 csAddr_giveAnotherFlowerToOldLady = 0x890b;
+// Giving Flower to Anne function : 0x8942
+const uint16 csAddr_givingFlowerToAnne = 0x8942;
+// Give Another Flower to Anne function : 0x89aa
+const uint16 csAddr_giveAnotherFlowerToAnne = 0x89aa;
+// Putting Rock in Hole function : 0x8d57
+const uint16 csAddr_putRockInHole = 0x8d57;
+// Mouse Out Of Hole Timeout function : 0x8d79
+const uint16 csAddr_mouseOutOfHoleTimeout = 0x8d79;
+// Robot Safe (Mike) Already Unlocked Check function : 0x9166
+const uint16 csAddr_robotSafeAlreadyUnlockedCheck = 0x9166;
+// Robot Safe (Mike) Unlock Check function : 0x9175
+const uint16 csAddr_robotSafeUnlockCheck = 0x9175;
+// Open Full Toolbox function : 0x98fa
+const uint16 csAddr_openFullToolbox = 0x98fa;
+// Open Half Empty Toolbox function : 0x9910
+const uint16 csAddr_openHalfEmptyToolbox = 0x9910;
+// Use Diving Equipment function : 0x9921
+const uint16 csAddr_useDivingEquipment = 0x9921;
+// Successfully Got Anchor function : 0x99e0
+const uint16 csAddr_gotAnchor = 0x99e0;
+// No Anchor Timeout function : 0x9a1d
+const uint16 csAddr_noAnchorTimeout = 0x9a1d;
+// Get Out of Lake function : 0x9a7a
+const uint16 csAddr_getOutOfLake = 0x9a7a;
+// Dig Under Mansion Wall function : 0x9aca
+const uint16 csAddr_digMansionWall = 0x9aca;
+// Too Dark Here function : 0x9c66
+const uint16 csAddr_tooDarkHere = 0x9c66;
+// Examine Banknote function : 0x9c6d
+const uint16 csAddr_examineBanknote = 0x9c6d;
+// Use Time Pills function : 0x9c79
+const uint16 csAddr_useTimePills = 0x9c79;
+// Mansion Intrusion Attempt function : 0x9d45
+const uint16 csAddr_mansionIntrusionAttempt = 0x9d45;
+// Second Mansion Intrusion function : 0x9d90
+const uint16 csAddr_secondMansionIntrusion = 0x9d90;
+// Third Mansion Intrusion function : 0x9de5
+const uint16 csAddr_thirdMansionIntrusion = 0x9de5;
+// Fourth Mansion Intrusion function : 0x9e54
+const uint16 csAddr_fourthMansionIntrusion = 0x9e54;
+// Fifth Mansion Intrusion function : 0x9ec3
+const uint16 csAddr_fifthMansionIntrusion = 0x9ec3;
+// Sixth Mansion Intrusion function : 0x9f3e
+const uint16 csAddr_sixthMansionIntrusion = 0x9f3e;
+// Display Message function : 0xa055
+const uint16 csAddr_displayMsg = 0xa055;
+// Reject Message function : 0xa4d6
+const uint16 csAddr_rejectMsg = 0xa4d6;
+
+// Data Segment Addresses
+// Timed Callback State Variable : 0x0000
+const uint16 dsAddr_timedCallbackState = 0x0000; // 1 byte
+
+// Cursor Graphic 8*12px : 0x00da to 0x0139 (Read Only)
+const uint16 dsAddr_cursor = 0x00da;
+
+// Reject Message Address Pointers : (4 * 2-byte) = 0x339e to 0x33a5
+const uint16 dsAddr_rejectMsgPtr = 0x339e;
+// Reject Message #0 : 0x33a6 to 0x33c9
+const uint16 dsAddr_rejectMsg0 = 0x33a6; // "I have no idea what to do with it"
+// Reject Message #1 : 0x33ca to 0x33f5
+const uint16 dsAddr_rejectMsg1 = 0x33ca; // "I can't imagine what I could do with this"
+// Reject Message #2 : 0x33f6 to 0x3425
+const uint16 dsAddr_rejectMsg2 = 0x33f6; // "I can't figure out what I should do with this"
+// Reject Message #3 : 0x3426 to 0x344f
+const uint16 dsAddr_rejectMsg3 = 0x3426; // "I can't find any reason to mess with it"
+// Cool Message : 0x3450 to 0x3456
+const uint16 dsAddr_coolMsg = 0x3450; // "Cool."
+// Object Usage Error Message : 0x3457 to 0x3467
+const uint16 dsAddr_objErrorMsg = 0x3457; // "That's no good"
+// Car Jack Message : 0x3468 to 0x348f
+const uint16 dsAddr_carJackMsg = 0x3468; // "Wow! There's a car jack inside! Great!"
+// Spanner Message : 0x3490 to 0x34c6
+const uint16 dsAddr_spannerMsg = 0x3490; // "There's something else inside the toolbox! A spanner!"
+// Last Chance Message : 0x34c7 to 0x34d4
+const uint16 dsAddr_lastChanceMsg = 0x34c7; // "Last chance?"
+// Give Up Message : 0x34d5 to 0x34e0
+const uint16 dsAddr_giveUpMsg = 0x34d5; // "I give up"
+// Avoid Bees Message : 0x34e1 to 0x351e
+const uint16 dsAddr_avoidBeesMsg = 0x34e1; // "I'm going to stay at least five meters away from these bees!"
+// Boat Empty Message : 0x351f to 0x3541
+const uint16 dsAddr_boatEmptyMsg = 0x351f; // "There's nothing else in the boat"
+// Too Hard Wood Message : 0x3542 to 0x3562
+const uint16 dsAddr_tooHardWoodMsg = 0x3542; // "This wood is too hard to break"
+// Boo Message : 0x3563 to 0x3569
+const uint16 dsAddr_BooMsg = 0x3563; // "Booo!"
+// Dont Push Luck Message : 0x356a to 0x358f
+const uint16 dsAddr_dontPushLuckMsg = 0x356a; // "I don't think I should push my luck"
+// Ordinary Haystack Message : 0x3590 to 0x35b1
+const uint16 dsAddr_ordinaryHaystackMsg = 0x3590; // "Just an ordinary hay stack. Now."
+// Needle Haystack Message : 0x35b2 to 0x35e7
+const uint16 dsAddr_needleHaystackMsg = 0x35b2; // "And they say you can't find a needle in a haystack"
+// No Potatoes Message : 0x35e8 to 0x3604
+const uint16 dsAddr_noPotatoMsg = 0x35e8; // "There are no more potatoes"
+// Trousers Message : 0x3605 to 0x363e
+const uint16 dsAddr_trousersMsg = 0x3605; // "Good I always asked mum for trousers with BIG pockets"
+// Life Is Brutal Message : 0x363f to 0x364f
+const uint16 dsAddr_lifeIsBrutalMsg = 0x363f; // "Life is brutal"
+// Life Brutal Message : 0x3650 to 0x3667
+const uint16 dsAddr_lifeBrutalMsg = 0x3650; // "Life is really brutal"
+// Tickled Message : 0x3668 to 0x367e
+const uint16 dsAddr_tickledMsg = 0x3668; // "Something tickled me!"
+// Its Gone Message : 0x367f to 0x3693
+const uint16 dsAddr_itsGoneMsg = 0x367f; // "At least it's gone"
+// Monsters Message : 0x3694 to 0x36c1
+const uint16 dsAddr_monstersMsg = 0x3694; // "Who knows what monsters live in there"
+// No Hands Message : 0x36c2 to 0x370e
+const uint16 dsAddr_noHandsMsg = 0x36c2; // "I'd better not put my hands in there..."
+// Totally Empty Message : 0x370f to 0x372d
+const uint16 dsAddr_totalEmptyMsg = 0x370f; // "I can see it's totally empty"
+// One Small Step Message : 0x372e to 0x3765
+const uint16 dsAddr_oneSmallStepMsg = 0x372e; // "One small step for man, one big pain in the head"
+// No Chance Message : 0x3766 to 0x378f
+const uint16 dsAddr_noChanceMsg = 0x3766; // "I won't take my chances a second time"
+// Dinosaur Bone Message : 0x3790 to 0x37b7
+const uint16 dsAddr_dinoBoneMsg = 0x3790; // "I really hope this is DINOSAUR bone"
+// Wall Shaken Message : 0x37b8 to 0x37e9
+const uint16 dsAddr_wallShakenMsg = 0x37b8; // "Wow! This must have shaken all the nearby walls!"
+// Kinda Dark Message : 0x37ea to 0x3800
+const uint16 dsAddr_kindaDarkMsg = 0x37ea; // "It's kinda dark here"
+// Not in Dark Message : 0x3801 to 0x3831
+const uint16 dsAddr_notInDarkMsg = 0x3801; // "I'm not going to wander here in the dark again"
+// Shut Valve Message : 0x3832 to 0x387b
+const uint16 dsAddr_shutValveMsg = 0x3832; // "Shutting the valve shook the dirt from the wall..."
+// Need Sunglasses Message : 0x387c to 0x38a6
+const uint16 dsAddr_needSunglassesMsg = 0x387c; // "Sorry buddy, but I need your sunglasses"
+// Not Best Place Message : 0x38a7 to 0x38cd
+const uint16 dsAddr_notBestPlaceMsg = 0x38a7; // "It's not the best place for diving"
+// Not Here Message : 0x38ce to 0x38da
+const uint16 dsAddr_notHereMsg = 0x38ce; // "Not here"
+// Can't Talk Underwater Message : 0x38db to 0x38fe
+const uint16 dsAddr_cantTalkUnderwaterMsg = 0x38db; // "I really can't talk underwater!"
+// Not Swimming There Message : 0x38ff to 0x3931
+const uint16 dsAddr_notSwimmingThereMsg = 0x38ff; // "I don't think swimming there is worth the effort"
+// Too Little Air Message : 0x3932 to 0x3988
+const uint16 dsAddr_tooLittleAirMsg = 0x3932; // "If I want to get this anchor I have to swim there when I have more air in my lungs"
+// Hooked Anchor Message : 0x3989 to 0x39ad
+const uint16 dsAddr_hookedAnchorMsg = 0x3989; // "I was really hooked on this anchor!"
+// Seaweed Message : 0x39ae to 0x39f5
+const uint16 dsAddr_seaweedMsg = 0x39ae; // "This seaweed is just like the flowers I gave mum on her last birthday"
+// Fish Boat Message : 0x39f6 to 0x3a27
+const uint16 dsAddr_fishBoatMsg = 0x39f6; // "I wonder what fish do inside this boat at night"
+// Fish Something Message : 0x3a28 to 0x3a59
+const uint16 dsAddr_fishSomethingMsg = 0x3a28; // "I think I have to fish out something down there"
+// Fish Don't Worry Message : 0x3a5a to 0x3a84
+const uint16 dsAddr_fishDontWorryMsg = 0x3a5a; // "At least fish don't worry about the rain"
+// Not Red Herring Message : 0x3a85 to 0x3ab6
+const uint16 dsAddr_notRedHerringMsg = 0x3a85; // "I hope all this fish stuff is not a red herring"
+// Nice Down Message : 0x3ab7 to 0x3acd
+const uint16 dsAddr_niceDownMsg = 0x3ab7; // "It's nice down there"
+// Hey Let Go Message : 0x3ace to 0x3ae5
+const uint16 dsAddr_heyLetGoMsg = 0x3ace; // "Hey, let go, will ya?!"
+// Aaahhh Message : 0x3ae6 to 0x3afc
+const uint16 dsAddr_aaahhhMsg = 0x3ae6; // "Aaaaaaaaaaaaahhh!"
+// Oops Message : 0x3afd to 0x3b03
+const uint16 dsAddr_oopsMsg = 0x3afd; // "Oops"
+// Found Food Message : 0x3b04 to 0x3b2e
+const uint16 dsAddr_foundFoodMsg = 0x3b04; // "People leave food in unbelievable places"
+// Come Here Message : 0x3b2f to 0x3b58
+const uint16 dsAddr_comeHereMsg = 0x3b2f; // "Come here, I've got something for you"
+// Cant Catch Message : 0x3b59 to 0x3b6b
+const uint16 dsAddr_cantCatchMsg = 0x3b59; // "I can't catch it!"
+// Trapped Mouse Message : 0x3b6c to 0x3b82
+const uint16 dsAddr_trappedMouseMsg = 0x3b6c; // "The mouse is trapped!"
+// Yikes Message : 0x3b83 to 0x3b8a
+const uint16 dsAddr_yikesMsg = 0x3b83; // "Yikes!"
+// Mouse Nerve Message : 0x3b8b to 0x3bab
+const uint16 dsAddr_mouseNerveMsg = 0x3b8b; // "Boy, this mouse has some nerve!"
+// Drawers Empty Message : 0x3bac to 0x3bd1
+const uint16 dsAddr_drawersEmptyMsg = 0x3bac; // "There's nothing else in the drawers"
+// Rid Bush Message 0x3bd2 to 0x3bf5
+const uint16 dsAddr_ridBushMsg = 0x3bd2; // "I must get rid of this bush first"
+// Mouse Gone Message : 0x3bf6 to 0x3c0a
+const uint16 dsAddr_mouseGoneMsg = 0x3bf6; // "The mouse has gone!"
+// Nonsense Message : 0x3c0b to 0x3c15
+const uint16 dsAddr_nonsenseMsg = 0x3c0b; // "Nonsense"
+// Good Doggy Message : 0x3c16 to 0x3c30
+const uint16 dsAddr_goodDoggyMsg = 0x3c16; // "I understand. Good doggy"
+// Here Boy Message : 0x3c31 to 0x3c3c
+const uint16 dsAddr_hereBoyMsg = 0x3c31; // "Here, boy"
+// Friends Now Message : 0x3c3d to 0x3c57
+const uint16 dsAddr_friendsNowMsg = 0x3c3d; // "I hope we're friends now"
+// Not Think Right Place Message : 0x3c58 to 0x3c7f
+const uint16 dsAddr_notThinkRightPlaceMsg = 0x3c58; // "I don't think this is the right place"
+// Cutscene Message A : 0x3c80 to 0x3c99
+const uint16 dsAddr_cutsceneMsgA = 0x3c80; // "Hundred moments later"
+// Cutscene Message B : 0x3c9a to 0x3cbb
+const uint16 dsAddr_cutsceneMsgB = 0x3c9a; // "Another hundred moments later"
+// Found Crude Oil Message : 0x3cbc to 0x3ce9
+const uint16 dsAddr_foundCrudeOilMsg = 0x3cbc; // "At least I found crude oil and I'll be rich"
+// My Life Message : 0x3cea to 0x3cfa
+const uint16 dsAddr_myLifeMsg = 0x3cea; // "That's my life"
+// Confusion Message : 0x3cfb to 0x3d00
+const uint16 dsAddr_ConfusionMsg = 0x3cfb; // "!?&!"
+// Grandpa Promise Message : 0x3d01 to 0x3d1f
+const uint16 dsAddr_grandpaPromiseMsg = 0x3d01; // "But grandpa, you promised!"
+// Oh Lets Go Message : 0x3d20 to 0x3d39
+const uint16 dsAddr_ohLetsGoMsg = 0x3d20; // "Oh all right. Let's go"
+// Bye Message : 0x3d3a to 0x3d3f
+const uint16 dsAddr_byeMsg = 0x3d3a; // "Bye."
+// No Need Message : 0x3d40 to 0x3d58
+const uint16 dsAddr_noNeedMsg = 0x3d40; // "No need to do it again"
+// Girl Talk Message : 0x3d59 to 0x3d85
+const uint16 dsAddr_girlTalkMsg = 0x3d59; // "I really don't know how to talk to girls"
+// Dont Work Purpose Message : 0x3d86 to 0x3dae
+const uint16 dsAddr_dontWorkPurposeMsg = 0x3d86; // "I usually don't work without a purpose"
+// Nut Real Message : 0x3daf to 0x3dc5
+const uint16 dsAddr_nutRealMsg = 0x3daf; // "Only the nut is real"
+// Hen Fly Message : 0x3dc6 to 0x3df3
+const uint16 dsAddr_henFlyMsg = 0x3dc6; // "I wonder if hens can fly. Come here, baby"
+// First Test Fail Message : 0x3df4 to 0x3e07
+const uint16 dsAddr_firstTestFailMsg = 0x3df4; // "First test failed"
+// Rid Frustations Message : 0x3e08 to 3e30
+const uint16 dsAddr_ridFrustationsMsg = 0x3e08; // "I'd already got rid of my frustrations"
+// Road Nowhere Message : 0x3e31 to 0x3e4e
+const uint16 dsAddr_roadNowhereMsg = 0x3e31; // "Nah. It's a road to nowhere"
+// Open Boot Message 0x3e4f to 0x3e62
+const uint16 dsAddr_openBootMsg = 0x3e4f; // "It opens the boot"
+// Shut Tight Message : 0x3e63 to 0x3e74
+const uint16 dsAddr_shutTightMsg = 0x3e63; // "It's shut tight"
+// Boot Empty Message : 0x3e75 to 0x3e97
+const uint16 dsAddr_bootEmptyMsg = 0x3e75; // "There's nothing else in the boot"
+// Clothes Dry Message : 0x3e98 to 0x3eb1
+const uint16 dsAddr_clothesDryMsg = 0x3e98; // "The clothes are dry now."
+// Crow Kill Message : 0x3eb2 to 0x3ed5
+const uint16 dsAddr_crowKillMsg = 0x3eb2; // "I'm sure these crows will kill me"
+// Get Rid Of Guard First Message : 0x3ed6 to 0x3f29
+const uint16 dsAddr_getRidOfGuardFirstMsg = 0x3ed6; // "If I want to get inside I must get rid of this guard first..."
+// Wall Too Smooth Message : 0x3f2a to 0x3f53
+const uint16 dsAddr_wallTooSmoothMsg = 0x3f2a; // "The wall surface is too smooth to climb"
+// Too Much Resin To Climb Message : 0x3f54 to 0x3f84
+const uint16 dsAddr_tooMuchResinToClimbMsg = 0x3f54; // "I could climb it if there wasn't so much resin"
+// Only Green Rect Message : 0x3f85 to 0x3feb
+const uint16 dsAddr_onlyGreenRectMsg = 0x3f85; // "The only green stuff that I like is that rectangular piece of paper with..."
+// Don't Wanna Touch Hedgehog Message : 0x3fec to 0x402d
+const uint16 dsAddr_dontWannaTouchHedgehogMsg = 0x3fec; // "I don't wanna touch it. Its spines could hurt my delicate hands"
+// Not Hungry Message : 0x402e to 0x4046
+const uint16 dsAddr_notHungryMsg = 0x402e; // "Thanks, I'm not hungry"
+// No Long Hands Message : 0x4047 to 0x406c
+const uint16 dsAddr_noLongHandsMsg = 0x4047; // "I really don't have such long hands"
+// Too Far To Swim Message : 0x406d to 0x4089
+const uint16 dsAddr_tooFarToSwimMsg = 0x406d; // "It's too far to swim there"
+// Echo Message : 0x408a to 0x4090
+const uint16 dsAddr_echoMsg = 0x408a; // "Echo!"
+// Loud Echo Message : 0x4091 to 0x4097
+const uint16 dsAddr_loudEchoMsg = 0x4091; // "ECHO!"
+// Who There Message : 0x4098 to 0x40a6
+const uint16 dsAddr_whoThereMsg = 0x4098; // "Who's there?!"
+// Loud Who There Message : 0x40a7 to 0x40b5
+const uint16 dsAddr_loudWhoThereMsg = 0x40a7; // "WHO'S THERE?!"
+// Dont Copy Message : 0x40b6 to 0x40cd
+const uint16 dsAddr_dontCopyMsg = 0x40b6; // "DON'T COPY ME!"
+// Loud Dont Copy Message : 0x40ce to 0x40e7
+const uint16 dsAddr_loudDontCopyMsg = 0x40ce; // "DON'T COPY ME!!!"
+// Throw Rock Message : 0x40e8 to 0x410e
+const uint16 dsAddr_throwRockMsg = 0x40e8; // "OR I WILL THROW A ROCK DOWN THERE!"
+// Or I Will Message : 0x410f to 0x411c
+const uint16 dsAddr_orIWillMsg = 0x410f; // "OR I WILL"
+// Still There Message : 0x411d to 0x4132
+const uint16 dsAddr_stillThereMsg = 0x411d; // "Are you still there?"
+// No Bucket Message : 0x4133 to 0x4163
+const uint16 dsAddr_noBucketMsg = 0x4133; // "It's not a barrel-organ. And there's no bucket."
+// Dont Need To Open Message : 0x4164 to 0x417d
+const uint16 dsAddr_dontNeedToOpenMsg = 0x4164; // "I don't need to open it"
+// Hmm Grass Message : 0x417e to 41b0
+const uint16 dsAddr_hmmGrassMsg = 0x417e; // "Hmmm. Grass..."
+// Find Nut Message : 0x41b1 to 0x41ee
+const uint16 dsAddr_findNutMsg = 0x41b1; // "I won't find the nut just like that. The grass is too dense"
+// Not Horny Message : 0x41ef to 0x41fe
+const uint16 dsAddr_notHornyMsg = 0x41ef; // "I'm not horny"
+// Can't Jump So High Message : 0x41ff to 0x423e
+const uint16 dsAddr_CantJumpMsg = 0x41ff; // "No way I can jump so high, cause, err, white men can't jump"
+// Don't Need It Message : 0x423f to 0x4250
+const uint16 dsAddr_dontNeedItMsg = 0x423f; // "I don't need it"
+// Not Santa Claus Message : 0x4251 to 0x4266
+const uint16 dsAddr_notSantaClausMsg = 0x4251; // "I'm not Santa Claus"
+// No Plastic Imitations Message : 0x4267 to 0x4288
+const uint16 dsAddr_noPlasticImitationsMsg = 0x4267; // "I don't need plastic imitations"
+// Too Fragile Message : 0x4289 to 0x42ab
+const uint16 dsAddr_tooFragileMsg = 0x4289; // "It's too fragile to carry around"
+// Keep It Open Message : 0x42ac to 0x42c6
+const uint16 dsAddr_keepItOpenMsg = 0x42ac; // "I'd like to keep it open"
+// Not Taking Socks Message : 0x42c7 to 0x4305
+const uint16 dsAddr_notTakingSocksMsg = 0x42c7; // "I really don't want to walk around with someone else's socks"
+// Not Tired Message : 0x4306 to 0x431d
+const uint16 dsAddr_notTiredMsg = 0x4306; // "Thanks, I'm not tired"
+// Too Big Message : 0x431e to 0x434d
+const uint16 dsAddr_tooBigMsg = 0x431e; // "It's too big and I doubt if I'll ever need it"
+// No Secret Passage Message : 0x434e to 0x437f
+const uint16 dsAddr_noSecretPassageMsg = 0x434e; // "I don't think there's any secret passage inside"
+// No Fruit Message : 0x4380 to 0x43ab
+const uint16 dsAddr_noFruitMsg = 0x4380; // "There are no more interesting fruits here"
+// Jug Me Message : 0x43ac to 0x43cd
+const uint16 dsAddr_jugMeMsg = 0x43ac; // "They can jug me if I steal this"
+// Leave Flowers Alone Message : 0x43ce to 0x4411
+const uint16 dsAddr_leaveFlowersAloneMsg = 0x43ce; // "I'd better leave it. Women are really oversensitive about flowers."
+// Mirror Mirror Message : 0x4412 to 0x444e
+const uint16 dsAddr_mirrorMirrorMsg = 0x4412; // "Mirror, Mirror on the wall...."
+// Think Too Long Message : 0x444f to 0x446a
+const uint16 dsAddr_thinkTooLongMsg = 0x444f; // "Hey, don't think too long"
+// Hint Male Message : 0x446b to 0x4491
+const uint16 dsAddr_HintMaleMsg = 0x446b; // "A hint: Someone in this room, a male"
+// OK Wait Message : 0x4492 to 0x44a6
+const uint16 dsAddr_okWaitMsg = 0x4492; // "OK, take your time"
+// Busy Thinking Message : 0x44a7 to 0x44d5
+const uint16 dsAddr_busyThinkingMsg = 0x44a7; // "I'd better not interrupt it's thought process"
+// No Dentists Message : 0x44d6 to 0x450d
+const uint16 dsAddr_noDentistsMsg = 0x44d6; // "I don't want to have anything in common with dentists"
+// Too Heavy Message : 0x450e to 0x4531
+const uint16 dsAddr_tooHeavyMsg = 0x450e; // "It's too heavy. Not that I'm wimp"
+// What Got Message : 0x4532 to 0x4554
+const uint16 dsAddr_whatGotMsg = 0x4532; // "Let's look what we've got here"
+// Strawberry Jam Message : 0x4555 to 0x4567
+const uint16 dsAddr_strawberryJamMsg = 0x4555; // "Strawberry jam"
+// Gooseberry Jam Message : 0x4568 to 0x457a
+const uint16 dsAddr_gooseberryJamMsg = 0x4568; // "Gooseberry jam"
+// Blackberry Jam Message : 0x457b to 0x458d
+const uint16 dsAddr_blackberryJamMsg = 0x457b; // "Blackberry jam"
+// Bilberry Jam Message : 0x458e to 0x459e
+const uint16 dsAddr_bilberryJamMsg = 0x458e; // "Bilberry jam"
+// Get Me Out Jam Message : 0x459f to 0x45b7
+const uint16 dsAddr_getMeOutJamMsg = 0x459f; // "Get me out of this jam!"
+// Rosemary Jam Message : 0x45b8 to 0x45d9
+const uint16 dsAddr_rosemaryJamMsg = 0x45b8; // "Oh, and there is Rosemary jam"
+// Know Rosemary Message : 0x45da to 0x4602
+const uint16 dsAddr_knowRosemaryMsg = 0x45da; // "I used to know someone called Rosemary"
+// Unwanted Jams Message : 0x4603 to 0x461c
+const uint16 dsAddr_unwantedJamsMsg = 0x4603; // "I don't want those jams"
+// Too Dark Message : 0x461d to 0x463b
+const uint16 dsAddr_TooDarkMsg = 0x461d; // "It's too dark to see clearly"
+// Yeow Message : 0x463c to 0x4649
+const uint16 dsAddr_yeowMsg = 0x463c; // "YEEEOOOWWWW!"
+// Yawn Message : 0x464a to 0x4651
+const uint16 dsAddr_yawnMsg = 0x464a; // "(yawn)"
+// Laughter Message : 0x4652 to 0x465d
+const uint16 dsAddr_laughterMsg = 0x4652; // "(laughter)"
+// No Hands Sharp Thorns Message : 0x465e to 0x46a0
+const uint16 dsAddr_noHandsSharpThornsMsg = 0x465e; // "I can't remove it with my hands. these thorns look really sharp"
+// No Chainsaw Fuel Message : 0x46a1 to 0x46c2
+const uint16 dsAddr_noChainsawFuelMsg = 0x46a1; // "There's no fuel in the chainsaw"
+// Thorns Too Thin Message : 0x46c3 to 0x46f6
+const uint16 dsAddr_thornsTooThinMsg = 0x46c3; // "Thorns are too thin, the chainsaw is useless here"
+// Rock Walking Gee Message : 0x46f7 to 0x473c
+const uint16 dsAddr_rockWalkingGeeMsg = 0x46f7; // "Yeah, great idea. Let's take this rock and walk around a bit. Gee..."
+// Butterfly Message : 0x473d to 0x477a
+const uint16 dsAddr_butterflyMsg = 0x473d; // "I'd better leave them alone, they make this place beautiful"
+// Not Sure If Alive Message : 0x477b to 0x4797
+const uint16 dsAddr_notSureIfAliveMsg = 0x477b; // "I'm not sure if it's alive"
+
+// FIXME - Unknown where this is used.. Talking to SOMETHING...
+// Unknown Language Message : 0x4798 to 0x47be
+const uint16 dsAddr_unknownLanguageMsg = 0x4798; // "I don't know what language it speaks"
+
+// Hole Too Narrow Message : 0x47bf to 0x47e6
+const uint16 dsAddr_holeTooNarrowMsg = 0x47bf; // "The hole is too narrow to fit my hand"
+// Bird Attack Message : 0x47e7 to 0x4807
+const uint16 dsAddr_birdAttackMsg = 0x47e7; // "Hey You! Wake up! Bird attack!"
+// No Search Warrant Message : 0x4808 to 0x4827
+const uint16 dsAddr_noSearchWarrantMsg = 0x4808; // "I don't have a search-warrant"
+// Uninteresting Haystack Message : 0x4828 to 0x485f
+const uint16 dsAddr_uninterestingHaystackMsg = 0x4828; // "I don't see anything interesting about this haystack"
+// More Complicated Message : 0x4860 to 0x4881
+const uint16 dsAddr_moreComplicatedMsg = 0x4860; // "It's more complicated than that"
+// Nut Rake Message : 0x4882 to 0x48be
+const uint16 dsAddr_nutRakeMsg = 0x4882; // "It's pointless, the nut will slip between the rake's teeth"
+// Paddle Broken Message : 0x48bf to 0x48d5
+const uint16 dsAddr_paddleBrokenMsg = 0x48bf; // "The paddle is BROKEN"
+// Branch Not Paddle Message : 0x48d6 to 0x4912
+const uint16 dsAddr_branchNotPaddleMsg = 0x48d6; // "This branch is not a paddle. It doesn't even look like one"
+// Try Somewhere Else Message : 0x4913 to 0x495b
+const uint16 dsAddr_trySomewhereElseMsg = 0x4913; // "I'd better try somewhere else - I suppose this side is heavily guarded"
+// Sharpen Not Pulverize Message : 0x495c to 0x4983
+const uint16 dsAddr_sharpenNotPulverizeMsg = 0x495c; // "I needed to sharpen it, not pulverize"
+// Can't Do Anything Too Dark Message : 0x4984 to 0x49ad
+const uint16 dsAddr_cantDoTooDarkMsg = 0x4984; // "I can't do anything here, it's too dark"
+// Bribe Message : 0x49ae to 0x49d0
+const uint16 dsAddr_BribeMsg = 0x49ae; // "Here, let's make your pocket fat."
+// Bank Note Message : 0x49d1 to 0x4a28
+const uint16 dsAddr_bankNoteMsg = 0x49d1; // "It's a note from some bank..."
+// Show Her Money Message : 0x4a29 to 0x4a5a
+const uint16 dsAddr_showHerMoneyMsg = 0x4a29; // "If I just show her the money, she might take it"
+// Hundred Bucks Message : 0x4a5b to 0x4a6e
+const uint16 dsAddr_hundredBucksMsg = 0x4a5b; // "A hundred bucks!!!"
+// Want Blood Message : 0x4a6f to 0x4a7d
+const uint16 dsAddr_wantBloodMsg = 0x4a6f; // "I want Blood!"
+// Dont Leave Mansion Message : 0x4a7e to 0x4aaf
+const uint16 dsAddr_dontLeaveMansionMsg = 0x4a7e; // "I don't want to leave the mansion, I want blood!"
+// Wimp Message : 0x4ab0 to 0x4acc
+const uint16 dsAddr_WimpMsg = 0x4ab0; // "I'm a pathetic little wimp"
+// Strange Drawer Message : 0x4acd to 0x4b0c
+const uint16 dsAddr_strangeDrawerMsg = 0x4acd; // "Strange, but the drawer is stuck if the next drawer is open"
+// Not Ordinary Drawers Message : 0x4b0d to 0x4b38
+const uint16 dsAddr_notOrdinaryDrawersMsg = 0x4b0d; // "Maybe these are not just ordinary drawers!"
+// Drawer Open Message : 0x4b39 to 0x4b6b
+const uint16 dsAddr_drawerOpenMsg = 0x4b39; // "I cannot open the drawer if the next one is open!"
+// Blue Interior Message 0x4b6c to 0x4b86
+const uint16 dsAddr_blueInteriorMsg = 0x4b6c; // "It's got a blue interior"
+// Red Interior Message : 0x4b87 to 0x4ba0
+const uint16 dsAddr_redInteriorMsg = 0x4b87; // "It's got a red interior"
+// Grey Interior Message : 0x4ba1 to 0x4bbb
+const uint16 dsAddr_greyInteriorMsg = 0x4ba1; // "It's got a grey interior"
+// Green Interior Message : 0x4bbc to 0x4bd7
+const uint16 dsAddr_greenInteriorMsg = 0x4bbc; // "It's got a green interior"
+// Brown Interior Message : 0x4bd8 to 0x4bf3
+const uint16 dsAddr_brownInteriorMsg = 0x4bd8; // "It's got a brown interior"
+// Pink Interior Message : 0x4bf4 to 0x4c0e
+const uint16 dsAddr_pinkInteriorMsg = 0x4bf4; // "It's got a pink interior"
+// Dictaphone Inside Message : 0x4c0f to 0x4c31
+const uint16 dsAddr_dictaphoneInsideMsg = 0x4c0f; // "Wow! There's a dictaphone inside!"
+// Found Polaroid Message : 0x4c32 to 0x4c60
+const uint16 dsAddr_foundPolaroidMsg = 0x4c32; // "There's a polaroid inside! I might need that"
+// Book Held Message : 0x4c61 to 0x4c83
+const uint16 dsAddr_bookHeldMsg = 0x4c61; // "Something's got hold of the book!"
+// Secret Compartment Message : 0x4c84 to 0x4c9f
+const uint16 dsAddr_secretCompartmentMsg = 0x4c84; // "Wow! A secret compartment!"
+// Dont Mess Message : 0x4ca0 to 0x4cc6
+const uint16 dsAddr_dontMessMsg = 0x4ca0; // "I don't need to mess with it anymore"
+// Full Automatic Message : 0x4cc7 to 0x4cd8
+const uint16 dsAddr_fullAutomaticMsg = 0x4cc7; // "Fully Automatic"
+// No More Sheets Message : 0x4cd9 to 0x4d01
+const uint16 dsAddr_noMoreSheetsMsg = 0x4cd9; // "Right now I don't need any more sheets"
+// No Deprave Message : 0x4d02 to 0x4d29
+const uint16 dsAddr_noDepraveMsg = 0x4d02; // "Nah, I don't want to deprave the kids"
+// No Read Again Message : 0x4d2a to 0x4d5a
+const uint16 dsAddr_noReadAgainMsg = 0x4d2a; // "I don't want to read it again. I might like it."
+// TV Off Message : 0x4d5b to 0x4d7f
+const uint16 dsAddr_tvOffMsg = 0x4d5b; // "I just realised that the TV is off"
+// Not Happen Message : 0x4d80 to 0x4d92
+const uint16 dsAddr_NotHappenMsg = 0x4d80; // "Nothing happened"
+// Tape Started Message : 0x4d93 to 0x4da5
+const uint16 dsAddr_tapeStartedMsg = 0x4d93; // "The tape started!"
+// Much Better Message : 0x4da6 to 0x4dba
+const uint16 dsAddr_muchBetterMsg = 0x4da6; // "That's much better"
+// No Sleep Message : 0x4dbb to 0x4dd2
+const uint16 dsAddr_noSleepMsg = 0x4dbb; // "I don't want to sleep"
+// Just Cork Message : 0x4dd3 to 0x4de5
+const uint16 dsAddr_justCorkMsg = 0x4dd3; // "It's just a cork"
+// Enough Photos Message : 0x4de6 to 0x4e04
+const uint16 dsAddr_enoughPhotosMsg = 0x4de6; // "I don't need any more photos"
+// Record Scare Message : 0x4e05 to 0x4e31
+const uint16 dsAddr_recordScareMsg = 0x4e05; // "Yeah, I can record this and scare the cats"
+// Already Recorded Message : 0x4e32 to 0x4e57
+const uint16 dsAddr_alreadyRecordedMsg = 0x4e32; // "I already recorded what I wanted to"
+// Can't Record No Batteries Message : 0x4e58 to 0x4e8d
+const uint16 dsAddr_cantRecordNoBatteriesMsg = 0x4e58; // "I can't record anything until I find some batteries"
+
+// FIXME - Not sure how to get this message. Dictaphone with no batteries somewhere? Radio?
+// No Batteries No Fun Message : 0x4e8e to 0x4ea4
+const uint16 dsAddr_NoBatteriesNoFunMsg = 0x4e8e; // "No batteries, no fun"
+
+// Not Right Moment Message : 0x4ea5 to 0x4ecd
+const uint16 dsAddr_notRightMomentMsg = 0x4ea5; // "I don't think this is the right moment"
+// Cook Around Message : 0x4ece to 0x4ef9
+const uint16 dsAddr_cookAroundMsg = 0x4ece; // "I can't do anything with this cook around"
+// Same Bottle Message : 0x4efa to 0x4f3c
+const uint16 dsAddr_sameBottleMsg = 0x4efa; // "The bottle's the same, but I doubt if it's enough to fool anyone"
+// Break Flatten Message : 0x4f3d to 0x4f68
+const uint16 dsAddr_breakFlattenMsg = 0x4f3d; // "I wanted to break it, not to flatten it!"
+// What Inside Message : 0x4f69 to 0x4f9a
+const uint16 dsAddr_whatInsideMsg = 0x4f69; // "I was always curious what's inside these things"
+// Rest Useless Message : 0x4f9b to 0x4fb0
+const uint16 dsAddr_restUselessMsg = 0x4f9b; // "The rest is useless"
+// Two Batteries Message : 0x4fb1 to 0x4fca
+const uint16 dsAddr_twoBatteriesMsg = 0x4fb1; // "Wow! Two 1.5V batteries!"
+// One Taken Message : 0x4fcb to 0x4fe1
+const uint16 dsAddr_oneTakenMsg = 0x4fcb; // "This one's taken, OK?"
+// Slight Mad Message : 0x4fe2 to 0x5009
+const uint16 dsAddr_slightMadMsg = 0x4fe2; // "It finally happened. I'm slightly mad"
+// Paper Burnt Message : 0x500a to 0x502a
+const uint16 dsAddr_paperBurntMsg = 0x500a; // "The paper burnt out completely!"
+// Burn Baby Message : 0x502b to 0x503d
+const uint16 dsAddr_burnBabyMsg = 0x502b; // "Burn, baby, burn!"
+// Voila Message : 0x503e to 0x5045
+const uint16 dsAddr_voilaMsg = 0x503e; // "Voila"
+// Too Hot Message : 0x5046 to 0x505d
+const uint16 dsAddr_tooHotMsg = 0x5046; // "It's too hot to touch!"
+// Frozen Shelf Message : 0x505e to 0x5081
+const uint16 dsAddr_frozenShelfMsg = 0x505e; // "It has frozen hard onto the shelf!"
+// Yummy Message : 0x5082 to 0x5089
+const uint16 dsAddr_yummyMsg = 0x5082; // "Yummy"
+// Dislike Veal Message : 0x508a to 0x50a5
+const uint16 dsAddr_dislikeVealMsg = 0x508a; // "I never liked veal anyway"
+// No Reason Message : 0x50a6 to 0x50c2
+const uint16 dsAddr_noReasonMsg = 0x50a6; // "There's no reason to do it"
+// Fooled Once Message : 0x50c3 to 0x50e0
+const uint16 dsAddr_fooledOnceMsg = 0x50c3; // "I'd already fooled him once"
+// Mike Voice Test Message : 0x50e1 to 0x5100
+const uint16 dsAddr_mikeVoiceTestMsg = 0x50e1; // "Mike, activate the voice test"
+// Not My Voice Message : 0x5101 to 0x5123
+const uint16 dsAddr_notMyVoiceMsg = 0x5101; // "I won't cheat Mike with MY voice"
+// Singing Message : 0x5124 to 0x5137
+const uint16 dsAddr_singingMsg = 0x5124; // "siiiiinging!"
+// Mike Scent Test Message : 0x5138 to 0x5160
+const uint16 dsAddr_mikeScentTestMsg = 0x5138; // "Mike, let's get on with the scent test"
+// Mike View Test Message : 0x5161 to 0x517a
+const uint16 dsAddr_mikeViewTestMsg = 0x5161; // "Mike, run the view test"
+// Cutscene Message #0 : 0x517b to 0x51a6
+const uint16 dsAddr_cutsceneMsg0 = 0x517b; // "A secret diary of ..."
+// Cant Hide Message : 0x51a7 to 0x51ba
+const uint16 dsAddr_cantHideMsg = 0x51a7; // "I can't hide here!"
+// John Outside Message : 0x51bb to 0x51e6
+const uint16 dsAddr_johnOutsideMsg = 0x51bb; // "There's John Noty outside! I can't go out!"
+// Was Close Message : 0x51e7 to 0x51f7
+const uint16 dsAddr_wasCloseMsg = 0x51e7; // "That was close"
+// Cork In Hole Message : 0x51f8 to 0x5217
+const uint16 dsAddr_corkInHoleMsg = 0x51f8; // "The cork is stuck in the hole"
+// Fits Perfect Message : 0x5218 to 0x522b
+const uint16 dsAddr_fitsPerfectMsg = 0x5218; // "It fits perfectly!"
+// Enough Water Message : 0x522c to 0x524e
+const uint16 dsAddr_enoughWaterMsg = 0x522c; // "There's enough water in the sink"
+// No Hot Water Message : 0x524f to 0x5271
+const uint16 dsAddr_noHotWaterMsg = 0x524f; // "There's no hot water in the sink"
+// Label Off Message : 0x5272 to 0x528a
+const uint16 dsAddr_labelOffMsg = 0x5272; // "The label has come off!"
+// Cork Too Small Message : 0x528b to 0x52a8
+const uint16 dsAddr_corkTooSmallMsg = 0x528b; // "The cork is a bit too small"
+// Not Try Now Message : 0x52a9 to 0x52ca
+const uint16 dsAddr_notTryNowMsg = 0x52a9; // "There's no need to try them now"
+// No Salad Message : 0x52cb to 0x52f5
+const uint16 dsAddr_noSaladMsg = 0x52cb; // "I don't want to turn myself into a salad"
+// Nah Message : 0x52f6 to 0x52fd
+const uint16 dsAddr_nahMsg = 0x52f6; // "Nah"
+// Vent First Message : 0x52fe to 0x5325
+const uint16 dsAddr_ventFirstMsg = 0x52fe; // "I'd better stop this ventilator first"
+// Catch John First Message : 0x5326 to 0x5348
+const uint16 dsAddr_catchJohnFirstMsg = 0x5326; // "I'd better catch John Noty first"
+// Only Chilli Message : 0x5349 to 0x5371
+const uint16 dsAddr_onlyChilliMsg = 0x5349; // "Good this red stuff is only a chilli"
+// Water Hot Message : 0x5372 to 0x538c
+const uint16 dsAddr_waterHotMsg = 0x5372; // "The water looks very hot"
+// Sink Full Message : 0x538d to 0x53ac
+const uint16 dsAddr_sinkFullMsg = 0x538d; // "The sink is full of hot water"
+// No Sock Store Message : 0x53ad to 0x53dc
+const uint16 dsAddr_noSockStoreMsg = 0x53ad; // "I don't have anything to store these socks in"
+// Show Papers Message : 0x53dd to 0x53f1
+const uint16 dsAddr_showPapersMsg = 0x53dd; // "Here are my papers"
+// Got Permission Message : 0x53f2 to 0x5410
+const uint16 dsAddr_gotPermissionMsg = 0x53f2; // "I already got the permission"
+// Saving Fine Message : 0x5411 to 0x5462
+const uint16 dsAddr_SavingFineMsg = 0x5411; // "Saving is a very fine thing..."
+// Love Captain Message : 0x5463 to 0x5474
+const uint16 dsAddr_loveCaptainMsg = 0x5463; // "I love captain"
+// Soccer Rulz Message : 0x5475 to 0x5483
+const uint16 dsAddr_soccerRulzMsg = 0x5475; // "Soccer rulz"
+// Tree Cut Message : 0x5484 to 0x54c3
+const uint16 dsAddr_treeCutMsg = 0x5484; // "Don't cut the trees..."
+// Visa Accepted Message : 0x54c4 to 0x54d4
+const uint16 dsAddr_visaAcceptedMsg = 0x54c4; // "VISA Accepted"
+// Other Graffiti Message : 0x54d5 to 0x54f6
+const uint16 dsAddr_otherGraffitiMsg = 0x54d5; // "The rest of graffiti is obscene"
+// First Trial Message : 0x54f7 to 0x5510
+const uint16 dsAddr_firstTrialMsg = 0x54f7; // "Sir, I'm Mark. A rookie"
+// Locked Message : 0x5511 to 0x551e
+const uint16 dsAddr_lockedMsg = 0x5511; // "It's Locked!"
+// Thanks Message : 0x551f to 0x5527
+const uint16 dsAddr_ThanksMsg = 0x551f; // "Thanks."
+// Unknown Usage Message : 0x5528 to 0x555c
+const uint16 dsAddr_unkUsageMsg = 0x5528; // "I don't have any idea what to do with it right now"
+// Idea Message : 0x555d to 0x5576
+const uint16 dsAddr_ideaMsg = 0x555d; // "That gives me an idea"
+// Check Works Message : 0x5577 to 0x5599
+const uint16 dsAddr_checkWorksMsg = 0x5577; // "Now I got to check if it works"
+// Time To Call Message : 0x559a to 0x55bf
+const uint16 dsAddr_timeToCallMsg = 0x559a; // "I think it is time to call captain"
+// Meal Finished Message : 0x55c0 to 0x55da
+const uint16 dsAddr_mealFinishedMsg = 0x55c0; // "Hey! I finished my meal."
+// Bowl Welded Message : 0x55db to 0x55fe
+const uint16 dsAddr_bowlWeldedMsg = 0x55db; // "Wow. He got welded to the bowl"
+// Gotcha Message : 0x55ff to 0x5607
+const uint16 dsAddr_gotchaMsg = 0x55ff; // "Gotcha"
+// No Pocket Message : 0x5608 to 0x5631
+const uint16 dsAddr_noPocketMsg = 0x5608; // "I don't want to touch his pockets again."
+// Does Not Work Message : 0x5632 to 0x5645
+const uint16 dsAddr_doesNotWorkMsg = 0x5632; // "That doesn't work"
+// Message : 0x5646 to 0x5655
+const uint16 dsAddr_fnMsg1 = 0x5646; // "Piece of cake"
+// Message : 0x5656 to 0x5679
+const uint16 dsAddr_fnMsg2 = 0x5656; // "And how am I supposed to get back?"
+// Message : 0x567a to 0x5681
+const uint16 dsAddr_fnMsg3 = 0x567a; // "Great"
+// Message : 0x5682 to 0x5695
+const uint16 dsAddr_fnMsg4 = 0x5682; // "Oh, yeah, right"
+// Pull Object Message #1 : 0x5696 to 0x56ab
+const uint16 dsAddr_pullObjMsg1 = 0x5696; // "I can't pull it out"
+// Dont Want To Touch Message : 0x56ac to 0x56d9
+const uint16 dsAddr_dontWantToTouchMsg = 0x56ac; // "I don't want to touch it - I might get hurt"
+// Fence Blocks Message : 0x56da to 0x56f6
+const uint16 dsAddr_fenceBlocksMsg = 0x56da; // "The fence blocks the way"
+// Not Want To Sleep Message : 0x56f7 to 0x570e
+const uint16 dsAddr_notWantToSleepMsg = 0x56f7; // "I don't want to sleep"
+// Pull Object Message #2 : 0x570f to 0x5721
+const uint16 dsAddr_pullObjMsg2 = 0x570f; // "I can't reach it"
+// Hello Question Message : 0x5722 to 0x5729
+const uint16 dsAddr_helloQMsg = 0x5722; // "Hello?"
+// Totally Addicted Message : 0x572a to 0x5741
+const uint16 dsAddr_totallyAddictedMsg = 0x572a; // "He's totally addicted"
+// What About Message : 0x5742 to 0x5756
+const uint16 dsAddr_whatAboutMsg = 0x5742; // "What about a new"
+// Hot Off Message : 0x5757 to 0x576f
+const uint16 dsAddr_hotOffMsg = 0x5757; // "hot off the press"
+// Full Color Message : 0x5770 to 0x5781
+const uint16 dsAddr_fullColorMsg = 0x5770; // "full-color"
+// Special Edition Message : 0x5782 to 0x5798
+const uint16 dsAddr_specialEdMsg = 0x5782; // "special edition"
+// Soldier News Message : 0x5799 to 0x57b1
+const uint16 dsAddr_soldierNewsMsg = 0x5799; // "of Soldier News?!"
+// Pole Climb Done Message : 0x57b2 to 0x57bf
+const uint16 dsAddr_poleClimbDoneMsg = 0x57b2; // "Never Again!"
+// Vac Message : 0x57c0 to 0x57de
+const uint16 dsAddr_vacMsg = 0x57c0; // "What am I? A vacuum cleaner?!"
+// Cutscene Message #1 : 0x57df to 0x5809
+const uint16 dsAddr_cutsceneMsg1 = 0x57df; // "sixty seven rude words later"
+// Cutscene Message #2 : 0x580a to 0x5826
+const uint16 dsAddr_cutsceneMsg2 = 0x580a; // "Meanwhile in the mansion"
+// Now Open Message : 0x5827 to 0x5836
+const uint16 dsAddr_nowOpenMsg = 0x5827; // "Now it's open"
+// Cmon Baby Message : 0x5837 to 0x5854
+const uint16 dsAddr_cmonBabyMsg = 0x5837; // "C'mon baby, it's all yours!"
+// Talk Not Now Message : 0x5855 to 0x5882
+const uint16 dsAddr_talkNotNowMsg = 0x5855; // "I've got no reason to talk to him right now."
+// Yeah Right Message : 0x5883 to 0x5893
+const uint16 dsAddr_yeahRightMsg = 0x5883; // "Yeah right!"
+// Barman Too Close Message : 0x5894 to 0x58af
+const uint16 dsAddr_barmanTooCloseMsg = 0x5894; // "The barman is too close"
+// Yuck Message : 0x58b0 to 0x58b6
+const uint16 dsAddr_yuckMsg = 0x58b0; // "Yuck!"
+// Prefer Water Message : 0x58b7 to 0x58c7
+const uint16 dsAddr_preferWaterMsg = 0x58b7; // "I prefer water"
+// Too Weak To Climb Message : 0x58c8 to 0x58e2
+const uint16 dsAddr_tooWeakToClimbMsg = 0x58c8; // "I'm too weak to climb it"
+// Spring Prick Message : 0x58e3 to 0x5904
+const uint16 dsAddr_springPrickMsg = 0x58e3; // "The springs would prick my back"
+// Food Alive Message : 0x5905 to 0x592e
+const uint16 dsAddr_foodAliveMsg = 0x5905; // "No, thanks. This food seems still alive"
+// Door Closed Message : 0x592f to 0x5954
+const uint16 dsAddr_doorClosedMsg = 0x592f; // "The door is closed. What a surprise."
+// Empty Message : 0x5955 to 0x5961
+const uint16 dsAddr_emptyMsg = 0x5955; // "It's Empty"
+// Geography Class Message : 0x5962 to 0x599c
+const uint16 dsAddr_geographyClassMsg = 0x5962; // "I should have paid more attention in geography classes."
+// Don't Need Mess Message : 0x599d to 0x59b5
+const uint16 dsAddr_dontNeedMessMsg = 0x599d; // "I don't need this mess"
+// Seen Softer Rocks Message : 0x59b6 to 0x59da
+const uint16 dsAddr_seenSofterRocksMsg = 0x59b6; // "Thanks, but I've seen softer rocks"
+// Too Blunt Message : 0x59db to 0x5a00
+const uint16 dsAddr_tooBluntMsg = 0x59db; // "They are too blunt to be of any use"
+// Useless Models Message : 0x5a01 to 0x5a1f
+const uint16 dsAddr_uselessModelsMsg = 0x5a01; // "What's the use of the models?"
+// Barman Will Notice Message : 0x5a20 to 0x5a50
+const uint16 dsAddr_barmanWillNoticeMsg = 0x5a20; // "The barman will surely notice its disappearing"
+// Too Much To Drink Message : 0x5a51 to 0x5a95
+const uint16 dsAddr_tooMuchToDrinkMsg = 0x5a51; // "It'd take too much time to drink it..."
+// 0x5a96 to 0x5a97 : 2 extra null bytes (padding?)
+// Not Thief Message : 0x5a98 to 0x5ac5
+const uint16 dsAddr_notThiefMsg = 0x5a98; // "I'm not a thief. And it's empty, by the way."
+// Too Many To Search Message : 0x5ac6 to 0x5aec
+const uint16 dsAddr_tooManyToSearchMsg = 0x5ac6; // "There are too many of them to search"
+// Captain Would Not Fit Message : 0x5aed to 0x5b26
+const uint16 dsAddr_captainWouldNotFitMsg = 0x5aed; // "Captain surely wouldn't fit them. I must look elsewhere"
+// Chickening Never Message : 0x5b27 to 0x5b3e
+const uint16 dsAddr_chickenNeverMsg = 0x5b27; // "Chickening? Me? Never!"
+// Can't Open It Message : 0x5b3f to 0x5b50
+const uint16 dsAddr_cantOpenItMsg = 0x5b3f; // "I can't open it"
+// Don't Need Them Message : 0x5b51 to 0x5b64
+const uint16 dsAddr_dontNeedThemMsg = 0x5b51; // "I don't need them"
+// Peeping Tom Message : 0x5b65 to 0x5b7f
+const uint16 dsAddr_peepingTomMsg = 0x5b65; // "What am I? A Peeping Tom?"
+// Big Pockets Message : 0x5b80 to 0x5baa
+const uint16 dsAddr_bigPocketsMsg = 0x5b80; // "I have big pockets, but there are limits"
+// Trouble With Stairs Message : 0x5bab to 0x5be6
+const uint16 dsAddr_troubleWithStairsMsg = 0x5bab; // "If I put it on I might have trouble walking up the stairs"
+// 9 Lives To Read Message : 0x5be7 to 0x5c0a
+const uint16 dsAddr_9LivesToReadMsg = 0x5be7; // "I'd need 9 lives to read them all"
+// Thanks Not Tired Message : 0x5c0b to 0x5c25
+const uint16 dsAddr_thanksNotTiredMsg = 0x5c0b; // "Thanks, I'm not so tired"
+// No Need To Turn On Message : 0x5c26 to 0x5c45
+const uint16 dsAddr_noNeedToTurnOnMsg = 0x5c26; // "There's no need to turn it on"
+// Won't Bear Weight Message : 0x5c46 to 0x5c5f
+const uint16 dsAddr_wontBearWeightMsg = 0x5c46; // "It won't bear my weight"
+// Never Learnt Message : 0x5c60 to 0x5c81
+const uint16 dsAddr_neverLearntMsg = 0x5c60; // "I never learnt to how use one"
+// So Sharp Message : 0x5c82 to 0x5cab
+const uint16 dsAddr_soSharpMsg = 0x5c82; // "They're so sharp they'd rip my trousers!"
+// Cognac Message : 0x5cac to 0x5cda
+const uint16 dsAddr_cognacMsg = 0x5cac; // "Pfui! The cognac really didn't do any good"
+// No Time For Pleasures Message : 0x5cdb to 0x5cfc
+const uint16 dsAddr_noTimeForPleasuresMsg = 0x5cdb; // "I don't have time for pleasures"
+// Not Socks With Bare Hands Message : 0x5cfd to 0x5d2b
+const uint16 dsAddr_notSocksWithBareHandsMsg = 0x5cfd; // "I won't touch these socks with my bare hands!"
+// Not Halloween Message : 0x5d2c to 0x5d40
+const uint16 dsAddr_notHalloweenMsg = 0x5d2c; // "It's not Halloween"
+// Not Manual Message : 0x5d41 to 0x5d6d
+const uint16 dsAddr_NotManualMsg = 0x5d41; // "It can't be controlled manually! I hate it!"
+// Nothing To Play Message : 0x5d6e to 0x5d86
+const uint16 dsAddr_nothingToPlayMsg = 0x5d6e; // "I have nothing to play"
+// Not Mine Message : 0x5d87 to 0x5da7
+const uint16 dsAddr_notMineMsg = 0x5d87; // "I can't take it. It's not mine."
+// Hey What's The Matter Message : 0x5da8 to 0x5dc1
+const uint16 dsAddr_HeyWtmQMsg = 0x5da8; // "Hey! What's the matter?!"
+// Its Open Message : 0x5dc2 to 0x5dcd
+const uint16 dsAddr_ItsOpenMsg = 0x5dc2; // "It's Open!"
+// Out Of Order Message : 0x5dce to 0x5de1
+const uint16 dsAddr_outOfOrderMsg = 0x5dce; // "It's out of order"
+// Captain Watching Message : 0x5de2 to 0x5e0a
+const uint16 dsAddr_captainWatchingMsg = 0x5de2; // "with captain watching? Better not"
+// Blunt Sickle Message : 0x5e0b to 0x5e24
+const uint16 dsAddr_bluntSickleMsg = 0x5e0b; // "The sickle is too blunt"
+// First Business Message : 0x5e25 to 0x5e53
+const uint16 dsAddr_firstBusinessMsg = 0x5e25; // "First I've got some business to take care of"
+// No Digging Knife Message : 0x5e54 to 0x5e8e
+const uint16 dsAddr_noDiggingKnifeMsg = 0x5e54; // "Digging it out with the knife could take a hundred years"
+
+// FIXME - Where is this message used?! Unused?
+// No Mess On Table Message : 0x5e8f to 0x5ebd
+const uint16 dsAddr_noMessOnTableMsg = 0x5e8f; // "I don't want to make more mess on this table"
+
+// Throw Crumbs To Bird Question Message : 0x5ebe to 0x5ee5
+const uint16 dsAddr_throwCrumbsToBirdQMsg = 0x5ebe; // "Should I throw the crumbs to the bird?"
+// Don't Waste Crumbs Message : 0x5ee6 to 0x5f10
+const uint16 dsAddr_dontWasteCrumbs = 0x5ee6; // "I don't want to waste these tasty crumbs"
+// Might Slip Fall In Message : 0x5f11 to 0x5f3b
+const uint16 dsAddr_mightSlipFallInMsg = 0x5f11; // "Better not... I might slip and fall in..."
+// Book Color Message Address Pointers : (6 * 2-byte) = 0x5f3c to 0x5f47
+const uint16 dsAddr_bookColorMsgPtr = 0x5f3c;
+// Book Color Message #0 : 0x5f48 to 0x5f60
+const uint16 dsAddr_bookColorMsg0 = 0x5f48; // ""The history of blues""
+// Book Color Message #1 : 0x5f61 to 0x5f8f
+const uint16 dsAddr_bookColorMsg1 = 0x5f61; // ""Manchester United, or the Red Devils story""
+// Book Color Message #2 : 0x5f90 to 0x5fb5
+const uint16 dsAddr_bookColorMsg2 = 0x5f90; // ""Greyhounds and other hunting dogs""
+// Book Color Message #3 : 0x5fb6 to 0x5fe6
+const uint16 dsAddr_bookColorMsg3 = 0x5fb6; // ""Greenhorn, or my adventures in the Wild West""
+// Book Color Message #4 : 0x5fe7 to 0x6008
+const uint16 dsAddr_bookColorMsg4 = 0x5fe7; // ""Charlie Brown and his company""
+// Book Color Message #5 : 0x6009 to 0x6034
+const uint16 dsAddr_bookColorMsg5 = 0x6009; // ""Pink Panther: an unauthorised biography""
+
+// Mansion Intrusion Function Pointers : (5 * 2-byte) = 0x6035 to 0x603e
+const uint16 dsAddr_MansionIntrusionFnPtr = 0x6035;
+
+// Save State Region : 0x6478 to 0xdbf1
+const uint16 dsAddr_saveState = 0x6478;
+const uint16 saveStateSize = 0x777a;
+
+// Save Description String (24 bytes) : 0x6478 to 0x648f
+
+// Ego (Mark) position in scene : 0x64af to 0x64b2
+const uint16 dsAddr_egoX = 0x64af; // 2 bytes
+const uint16 dsAddr_egoY = 0x64b1; // 2 bytes
+
+// Idle Animation List Table : 0x6540 to 0x????
+const uint16 dsAddr_idleAnimationListPtr = 0x6540;
+
+// Palette Effect Data : 0x6609 to 0x????
+const uint16 dsAddr_paletteEffectData = 0x6609;
+
+// Scene Fade Table (2 byte address * 42): 0x663e to 0x6691
+const uint16 dsAddr_sceneFadeTablePtr = 0x663e;
+
+// Scene Walkbox Table (2 byte LE address * 42) : 0x6746 to 0x6799
+const uint16 dsAddr_sceneWalkboxTablePtr = 0x6746;
+
+// Scene Zoom Table (2 byte address * 42) : 0x70f4 to 0x7147
+const uint16 dsAddr_sceneZoomTablePtr = 0x70f4;
+
+// Scene Object Table (2 byte address * 42) : 0x7254 to 0x72a7
+const uint16 dsAddr_sceneObjectTablePtr = 0x7254;
+
+// Scene Object Name : Sonny or whatever : 0x92e5 to 0x92f6
+const uint16 dsAddr_scnObjNameSonny = 0x92e5; // "Sonny or whatever"
+
+// Scene Object Name - Anne : 0x9820 to 0x9824
+const uint16 dsAddr_scnObjNameAnne = 0x9820; // "Anne"
+
+// Scene Object Name - Mike : 0xaa94 to 0xaa98
+const uint16 dsAddr_scnObjNameMike = 0xaa94; // "Mike"
+
+// Current Scene Id : 0xb4f3
+const uint16 dsAddr_currentScene = 0xb4f3; // 1 byte
+
+// Ons Animation Table (2 byte address * ??) : 0xb4f5 to 0x????
+const uint16 dsAddr_onsAnimationTablePtr = 0xb4f5;
+
+// Examine Object Callback Table (2 byte LE address * ??) : 0xb5ce to 0x????
+const uint16 dsAddr_objExamineCallbackTablePtr = 0xb5ce;
+
+// Use Object Callback Table (2 byte LE address * ??) : 0xb89c to 0x????
+const uint16 dsAddr_objUseCallbackTablePtr = 0xb89c;
+
+// Inventory Object Callback Table (3 byte (id, callbackAddr) * 7) : 0xbb72 to 0xbb86
+const uint16 dsAddr_objCallbackTablePtr = 0xbb72;
+// invItemToolboxFull = csAddr_openFullToolbox
+// invItemToolboxHalfEmpty = csAddr_openHalfEmptyToolbox
+// invItemDiveEquipment = csAddr_useDivingEquipment
+// invItemShovelAct2 = csAddr_digMansionWall
+// 0xff = csAddr_tooDarkHere // TODO: No object has id 0xff - Callback Disabled?
+// invItemBanknote = csAddr_examineBanknote
+// invItemTimePills = csAddr_useTimePills
+
+// Scene Hotspots Table (2 byte LE address * ??) : 0xbb87 to 0x????
+const uint16 dsAddr_sceneHotspotsPtr = 0xbb87;
+
+// Inventory Object Combining Table (5 byte (id, id, new object id, msgAddr) * 34) : 0xc335 to 0xc3de
+const uint16 dsAddr_objCombiningTablePtr = 0xc335;
+// 3 byte null terminator for Combining table 0xc3df to 0xc3e1
+
+// Object Combine Error Message : 0xc3e2 to 0xc41e
+const uint16 dsAddr_objCombineErrorMsg = 0xc3e2; // "Using these two objects ..."
+
+// Inventory (item ids held by Ego) (1 byte * 24) : 0xc48d to 0xc4a4
+const uint16 dsAddr_inventory = 0xc48d;
+// 0xc4a5 is null word alignment byte
+// Inventory item data address table (2 bytes * 92) : 0xc4a6 to 0xc55d
+const uint16 dsAddr_inventoryItemDataPtrTable = 0xc4a6;
+
+// Lans Animation Table (4 byte * ??) : 0xd89e to 0x????
+const uint16 dsAddr_lansAnimationTablePtr = 0xd89e;
+
+// Spoken With Mansion Guard Flag : 0xda96
+// FIXME - This is probably unecessary as although this location is set, it
+// doesn't now appear to be read.
+const uint16 dsAddr_spokenWithMansionGuardFlag = 0xda96; // 1 byte
+// Have Not Spoken With Mansion Guard Flag : 0xda97
+// FIXME - This is probably unecessary as although this location is set, it
+// doesn't now appear to be read.
+const uint16 dsAddr_haveNotSpokenWithMansionGuardFlag = 0xda97; // 1 byte
+
+// Dialog Stack - Pleading with Mansion Guard : 0xdaa6 to 0xdab1
+const uint16 dsAddr_dialogStackPleadingToMansionGuard = 0xdaa6;
+// Dialog Stack - Mansion Guard Drinking : 0xdab2 to 0xdab9
+// FIXME - Can't find where this is used...
+const uint16 dsAddr_dialogStackMansionGuardDrinking = 0xdab2;
+// Dialog Stack - Talking To Sonny : 0xdaba to 0xdac3
+const uint16 dsAddr_dialogStackSonny = 0xdaba;
+// Dialog Stack - Talking To Grandpa : 0xdac4 to 0xdacd
+const uint16 dsAddr_dialogStackGrandpa = 0xdac4;
+// Cave Thorns Cut Down Flag : 0xdaca
+// FIXME - Cave Thorns Flag overlap with dsAddr_dialogStackGrandpa. Bug or typo?
+const uint16 dsAddr_caveThornsCutDownFlag = 0xdaca; // 1 byte
+// Dialog Stack - Trying To Borrow Shotgun From Grandpa : 0xdace to 0xdad3
+const uint16 dsAddr_dialogStackGrandpaShotgun = 0xdace;
+// Dialog Stack - Trying To Borrow Fan From Grandpa : 0xdad4 to 0xdad9
+const uint16 dsAddr_dialogStackGrandpaFan = 0xdad4;
+// Dialog Stack - Ask Old Lady if OK : 0xdada to 0xdaef
+const uint16 dsAddr_dialogStackAskOldLadyOK = 0xdada;
+// Dialog Stack - Talking To Old Lady : 0xdaf0 to 0xdaf5
+const uint16 dsAddr_dialogStackOldLady = 0xdaf0;
+// Dialog Stack - Borrow Duster From Old Lady : 0xdaf6 to 0xdafb
+const uint16 dsAddr_dialogStackBorrowDusterFromOldLady = 0xdaf6;
+// Dialog Stack - Get Old Lady's Apple : 0xdafc to 0xdb01
+const uint16 dsAddr_dialogStackGetAppleOldLady = 0xdafc;
+// Dialog Stack - Giving Another Flower To Anne : 0xdb02 to 0xdb07
+const uint16 dsAddr_dialogStackAnotherFlowerToAnne = 0xdb02;
+// Dialog Stack - Talking To Squirrel : 0xdb08 to 0xdb13
+const uint16 dsAddr_dialogStackSquirrel = 0xdb08;
+// Dialog Stack - Talking To Dog : 0xdb14 to 0xdb1d
+const uint16 dsAddr_dialogStackDog = 0xdb14;
+// Dialog Stack - Take Axe : 0xdb1e to 0xdb23
+const uint16 dsAddr_dialogStackTakeAxe = 0xdb1e;
+// Dialog Stack - Talking To Busy Cook : 0xdb24 to 0xdb2d
+const uint16 dsAddr_dialogStackBusyCook = 0xdb24;
+// Dialog Stack - Talking To Mike the Robot Safe : 0xdb2e to 0xdb35
+const uint16 dsAddr_dialogStackRobotSafe = 0xdb2e;
+// Dialog Stack - Talking To John Noty At Endgame : 0xdb36 to 0xdb3f
+const uint16 dsAddr_dialogStackJohnNotyEndgame = 0xdb36;
+// Dialog Stack - Camp Guard Waiting For Documents : 0xdb40 to 0xdb4b
+const uint16 dsAddr_dialogStackCampGuardWantsDocuments = 0xdb40;
+// Dialog Stack - Camp Guard Reading Soldier News : 0xdb4c to 0xdb55
+const uint16 dsAddr_dialogStackCampGuardReadingNews = 0xdb4c;
+// Dialog Stack - Camp Guard Show Pass : 0xdb56 to 0xdb5b
+const uint16 dsAddr_dialogStackCampGuardShowPass = 0xdb56;
+// Dialog Stack - Jail Door Grates : 0xdb5c to 0xdb67
+const uint16 dsAddr_dialogStackJailDoorGrates = 0xdb5c;
+// Dialog Stack - Talking to Barman : 0xdb68 to 0xdb71
+const uint16 dsAddr_dialogStackBarman = 0xdb68;
+// Dialog Stack - Fall Into Mudpool : 0xdb72 to 0xdb79
+const uint16 dsAddr_dialogStackFallIntoMudpool = 0xdb72;
+// Dialog Stack - Talking To Mudpool Bird : 0xdb7a to 0xdb81
+const uint16 dsAddr_dialogStackMudpoolBird = 0xdb7a;
+// Dialog Stack - Interrogate Captain : 0xdb82 to 0xdb89
+const uint16 dsAddr_dialogStackInterrogateCaptain = 0xdb82;
+// Dialog Stack - Bar Cellar Door : 0xdb8a to 0xdb8f
+const uint16 dsAddr_dialogStackBarCellarDoor = 0xdb8a;
+// Current Music Id Playing : 0xdb90
+const uint16 dsAddr_currentMusic = 0xdb90; // 1 byte
+// Unused Byte : 0xdb91
+// Already Adjusted Hoop Pole Flag : 0xdb92
+const uint16 dsAddr_alreadyAdjustedHoopPoleFlag = 0xdb92; // 1 byte
+// Already Kicked Hen Flag : 0xdb93
+const uint16 dsAddr_alreadyKickedHenFlag = 0xdb93; // 1 byte
+// Already Pulled Trunk Release Lever Flag : 0xdb94
+const uint16 dsAddr_alreadyPulledTrunkReleaseLeverFlag = 0xdb94; // 1 byte
+// Car Trunk Empty Flag : 0xdb95
+const uint16 dsAddr_carTrunkEmptyFlag = 0xdb95; // 1 byte
+// Birds Gone From Scarecrow Flag : 0xdb96
+const uint16 dsAddr_birdsGoneFromScarecrowFlag = 0xdb96; // 1 byte
+// Already Spoken To Anne Flag : 0xdb97
+const uint16 dsAddr_alreadySpokenToAnneFlag = 0xdb97; // 1 byte
+// Flower Isle in Lake State (0 = Both Flowers Present, 1 = One Flower Taken, 2+ = Both Flowers Taken): 0xdb98
+const uint16 dsAddr_flowerIsleState = 0xdb98; // 1 byte
+// Already Got Broken Paddle Flag : 0xdb99
+const uint16 dsAddr_alreadyGotBrokenPaddleFlag = 0xdb99; // 1 byte
+// Given Flower To OldLady Already Flag : 0xdb9a
+const uint16 dsAddr_givenFlowerToOldLadyAlreadyFlag = 0xdb9a; // 1 byte
+// Given Flower To Anne Already Flag : 0xdb9b
+const uint16 dsAddr_givenFlowerToAnneAlreadyFlag = 0xdb9b; // 1 byte
+// Scared Guard Already Flag : 0xdb9c
+const uint16 dsAddr_scaredGuardAlreadyFlag = 0xdb9c; // 1 byte
+// Got Needle Already Flag : 0xdb9d
+const uint16 dsAddr_gotNeedleAlreadyFlag = 0xdb9d; // 1 byte
+// Got Potato Already Flag : 0xdb9e
+const uint16 dsAddr_gotPotatoAlreadyFlag = 0xdb9e; // 1 byte
+// Bees Gone Flag : 0xdb9f
+const uint16 dsAddr_beesGoneFlag = 0xdb9f; // 1 byte
+// Mansion Already Been Through Tunnel Flag : 0xdba0
+const uint16 dsAddr_mansionTunnelDoneFlag = 0xdba0; // 1 byte
+// Mansion Tree Hollow Empty Flag : 0xdba1
+const uint16 dsAddr_mansionTreeHollowEmptyFlag = 0xdba1; // 1 byte
+// Climbed Mansion Tree Already Flag : 0xdba2
+const uint16 dsAddr_climbedMansionTreeAlreadyFlag = 0xdba2; // 1 byte
+// Cellar Door Open Flag : 0xdba3
+const uint16 dsAddr_cellarDoorOpenFlag = 0xdba3; // 1 byte
+// Cellar Light On Flag : 0xdba4
+const uint16 dsAddr_lightOnFlag = 0xdba4; // 1 byte
+// Laundry State (0 = Wet on Line, 1 = Dry on Line, 2 = Not Present): 0xdba5
+const uint16 dsAddr_laundryState = 0xdba5; // 1 byte
+// Lake Diving Exit Message (0 to 5+) : 0xdba6
+const uint16 dsAddr_lakeDivingExitMessage = 0xdba6; // 1 byte
+// Searched Grandpa Drawers Flag : 0xdba7
+const uint16 dsAddr_SearchedGrandpaDrawersFlag = 0xdba7; // 1 byte
+// Hankerchief in Mousehole Flag : 0xdba8
+const uint16 dsAddr_HankerchiefInMouseholeFlag = 0xdba8; // 1 byte
+// Mouse Hole State : 0xdba9, 0 = Mouse Gone, 1 = Mouse Trapped, 2 = Mouse Success(?)
+const uint16 dsAddr_mouseHoleState = 0xdba9; // 1 byte
+// Mouse Nerve Message Said Flag : 0xdbaa
+const uint16 dsAddr_mouseNerveMsgSaidFlag = 0xdbaa; // 1 byte
+// Mouse Already Got Gold Nugget Flag : 0xdbab
+const uint16 dsAddr_mouseGotGoldNuggetFlag = 0xdbab; // 1 byte
+// Unused Byte : 0xdbac
+// Dog Has Bone Flag : 0xdbad
+const uint16 dsAddr_dogHasBoneFlag = 0xdbad; // 1 byte
+// Ego Already Scared By Spider Flag : 0xdbae
+const uint16 dsAddr_egoAlreadyScaredBySpiderFlag = 0xdbae; // 1 byte
+// Already Said That Anne is Beautiful Flag : 0xdbaf
+const uint16 dsAddr_alreadySaidAnneBeautifulFlag = 0xdbaf; // 1 byte
+// Squirrel's Nut State (0 = Nut in Tree, 1 = Nut in Grass, 2 = Nut Found with Rake) : 0xdbb0
+const uint16 dsAddr_squirrelNutState = 0xdbb0; // 1 byte
+// Nut Swapped For Apple in Fruit Bowl Flag : 0xdbb1
+const uint16 dsAddr_nutSwappedForAppleFlag = 0xdbb1; // 1 byte
+// Spoken To Man In Well Flag : 0xdbb2
+const uint16 dsAddr_spokenToManInWellFlag = 0xdbb2; // 1 byte
+// Spoken To Mirror Flag : 0xdbb3
+const uint16 dsAddr_spokenToMirrorFlag = 0xdbb3; // 1 byte
+// Cellar Shelves Examine Count (0 to 2(clamped))) : 0xdbb4
+const uint16 dsAddr_cellarShelfExamineCount = 0xdbb4; // 1 byte
+// Examined Bank Note Flag : 0xdbb5
+const uint16 dsAddr_examinedBanknoteFlag = 0xdbb5; // 1 byte
+// VGA Artist Quip Already Said Flag : 0xdbb6
+const uint16 dsAddr_vgaArtistQuipAlreadySaidFlag = 0xdbb6; // 1 byte
+// Mansion Desk Blue Drawer Open Flag : 0xdbb7
+const uint16 dsAddr_blueDrawerOpenFlag = 0xdbb7; // 1 byte
+// Mansion Desk Red Drawer Open Flag : 0xdbb8
+const uint16 dsAddr_redDrawerOpenFlag = 0xdbb8; // 1 byte
+// Mansion Desk Grey Drawer Open Flag : 0xdbb9
+const uint16 dsAddr_greyDrawerOpenFlag = 0xdbb9; // 1 byte
+// Mansion Desk Green Drawer Open Flag : 0xdbba
+const uint16 dsAddr_greenDrawerOpenFlag = 0xdbba; // 1 byte
+// Mansion Desk Brown Drawer Open Flag : 0xdbbb
+const uint16 dsAddr_brownDrawerOpenFlag = 0xdbbb; // 1 byte
+// Mansion Desk Pink Drawer Open Flag : 0xdbbc
+const uint16 dsAddr_pinkDrawerOpenFlag = 0xdbbc; // 1 byte
+// Mansion Colored Drawer Puzzle Hint Message Given Flag : 0xdbbd
+const uint16 dsAddr_drawerPuzzleHintGivenFlag = 0xdbbd; // 1 byte
+// Mansion Colored Drawer Got Dictaphone Flag : 0xdbbe
+const uint16 dsAddr_drawerGotDictaphoneFlag = 0xdbbe; // 1 byte
+// Mansion Colored Drawer Got Polaroid Flag : 0xdbbf
+const uint16 dsAddr_drawerGotPolaroidFlag = 0xdbbf; // 1 byte
+// Mansion Colored Drawer Puzzle Book Message Flag : 0xdbc0
+const uint16 dsAddr_drawerPuzzleBookMessageFlag = 0xdbc0; // 1 byte
+// Mansion Colored Drawer Puzzle - Random Book Color Value (0 = No Book, 1 to 6 = Books) : 0xdbc1
+const uint16 dsAddr_drawerPuzzleBookValue = 0xdbc1; // 1 byte
+// Mansion Colored Drawer Puzzle Solved Flag : 0xdbc2
+const uint16 dsAddr_drawerPuzzleSolvedFlag = 0xdbc2; // 1 byte
+// Mansion Trashcan Searched Flag : 0xdbc3
+const uint16 dsAddr_mansionTrashcanSearchedFlag = 0xdbc3; // 1 byte
+// Mansion Read Newspaper Flag : 0xdbc4
+const uint16 dsAddr_mansionReadNewspaperFlag = 0xdbc4; // 1 byte
+// Mansion TV On Flag : 0xdbc5
+const uint16 dsAddr_mansionTVOnFlag = 0xdbc5; // 1 byte
+// Mansion VCR Playing Tape Flag : 0xdbc6
+const uint16 dsAddr_mansionVCRPlayingTapeFlag = 0xdbc6; // 1 byte
+// Mansion VCR Played Tape Before Flag : 0xdbc7
+const uint16 dsAddr_mansionVCRPlayedTapeBeforeFlag = 0xdbc7; // 1 byte
+// Mansion VCR Tape Loaded Flag : 0xdbc8
+const uint16 dsAddr_mansionVCRTapeLoadedFlag = 0xdbc8; // 1 byte
+// Mansion Examined Couch Before Flag : 0xdbc9
+const uint16 dsAddr_mansionExaminedCouchBeforeFlag = 0xdbc9; // 1 byte
+// Mansion Used Polaroid on TV Flag : 0xdbca
+const uint16 dsAddr_usedPolaroidOnTVFlag = 0xdbca; // 1 byte
+// Mansion Used Dictaphone on TV Flag : 0xdbcb
+const uint16 dsAddr_usedDictaphoneOnTVFlag = 0xdbcb; // 1 byte
+// Mansion Cook Gone Flag : 0xdbcc
+const uint16 dsAddr_MansionCookGoneFlag = 0xdbcc; // 1 byte
+// Mansion Radio Broken Flag : 0xdbcd
+const uint16 dsAddr_MansionRadioBrokenFlag = 0xdbcd; // 1 byte
+// Mansion Got Radio Batteries Flag : 0xdbce
+const uint16 dsAddr_MansionGotRadioBatteriesFlag = 0xdbce; // 1 byte
+// Mansion Have Opened Fridge Before Flag : 0xdbcf
+const uint16 dsAddr_MansionHaveOpenedFridgeBeforeFlag = 0xdbcf; // 1 byte
+// Mansion Put Burning Paper In Fridge Flag : 0xdbd0
+const uint16 dsAddr_MansionPutBurningPaperInFridgeFlag = 0xdbd0; // 1 byte
+// Mansion Robot Safe Unlocked Flag : 0xdbd1
+const uint16 dsAddr_MansionRobotSafeUnlockedFlag = 0xdbd1; // 1 byte
+// Mansion Robot Safe Voice Test Passed Flag : 0xdbd2
+const uint16 dsAddr_MansionRobotSafeVoiceTestPassedFlag = 0xdbd2; // 1 byte
+// Mansion Robot Safe Scent Test Passed Flag : 0xdbd3
+const uint16 dsAddr_MansionRobotSafeScentTestPassedFlag = 0xdbd3; // 1 byte
+// Mansion Robot Safe View Test Passed Flag : 0xdbd4
+const uint16 dsAddr_MansionRobotSafeViewTestPassedFlag = 0xdbd4; // 1 byte
+// Mansion John Noty Outside Bathroom Flag : 0xdbd5
+const uint16 dsAddr_MansionJohnNotyOutsideBathroomFlag = 0xdbd5; // 1 byte
+// Mansion Sink State (0 - No Plug, Sink Empty, 1 - Plug, Sink Empty, 2 - Plug, Sink Full) : 0xdbd6
+const uint16 dsAddr_MansionSinkState = 0xdbd6; // 1 byte
+// Mansion Through Fan By Time Pill Flag : 0xdbd7
+const uint16 dsAddr_MansionThruFanByTimePillFlag = 0xdbd7; // 1 byte
+// Mansion Ventilator Fan Stopped Flag : 0xdbd8
+const uint16 dsAddr_MansionVentFanStoppedFlag = 0xdbd8; // 1 byte
+// Mansion John Noty Escaping Flag : 0xdbd9
+const uint16 dsAddr_MansionJohnNotyEscapingFlag = 0xdbd9; // 1 byte
+// Shown Pass To Guard Flag : 0xdbda
+const uint16 dsAddr_ShownPassToGuardFlag = 0xdbda; // 1 byte
+// Graffiti Message Id (0 to 6) : 0xdbdb
+const uint16 dsAddr_graffitiMsgId = 0xdbdb; // 1 byte
+// Got Food Bowl in Jail Flag : 0xdbdc
+const uint16 dsAddr_GotFoodBowlInJailFlag = 0xdbdc; // 1 byte
+// Jail Cable and Bowl State (0 = Cable not in Bowl, 1 = Cable in Bowl, 2 = Bowl Electrified 3 = Captain Shocked) : 0xdbdd
+const uint16 dsAddr_JailCableAndBowlState = 0xdbdd; // 1 byte
+// Got Jail Key Flag : 0xdbde
+const uint16 dsAddr_GotJailKeyFlag = 0xdbde; // 1 byte
+// First Act Trial State (0 = Before First Trial, 1 to 3 = Trial 1st to 3rd) : 0xdbdf
+const uint16 dsAddr_FirstActTrialState = 0xdbdf; // 1 byte
+// Already Tickled Captain Flag : 0xdbe0
+const uint16 dsAddr_AlreadyTickledCaptainFlag = 0xdbe0; // 1 byte
+// Cut Fence Flag : 0xdbe1
+const uint16 dsAddr_cutFenceFlag = 0xdbe1; // 1 byte
+// Act 1 Guard State (0 = Normal, 1 = With Kaleidoscope & Grenade, 2 = Kaleidoscope & No Grenade) : 0xdbe2
+const uint16 dsAddr_act1GuardState = 0xdbe2; // 1 byte
+// Spoken to Barman About Third Trial Flag : 0xdbe3
+const uint16 dsAddr_spokeToBarmanAboutThirdTrialFlag = 0xdbe3; // 1 byte
+// Got Mug Of Mud Flag : 0xdbe4
+const uint16 dsAddr_gotMugOfMudFlag = 0xdbe4; // 1 byte
+// Got Rope In Act 1 Flag : 0xdbe5
+const uint16 dsAddr_gotRopeAct1Flag = 0xdbe5; // 1 byte
+// Captain Drawer State : 0xdbe6
+const uint16 dsAddr_captainDrawerState = 0xdbe6; // 1 byte
+// Bird on Bar Radio Antenna Flag : 0xdbe7
+const uint16 dsAddr_birdOnBarRadioAntennaFlag = 0xdbe7; // 1 byte
+// Swapped Barman Mug Flag : 0xdbe8
+const uint16 dsAddr_swappedBarmanMugFlag = 0xdbe8; // 1 byte
+// Barman Passed Out Flag : 0xdbe9
+const uint16 dsAddr_barmanPassedOutFlag = 0xdbe9; // 1 byte
+// Counter for Mansion Intrusion Attempts : 0xdbea
+const uint16 dsAddr_mansionEntryCount = 0xdbea;// 1 byte
+// Unused Byte : 0xdbeb
+// John Noty Outside Mansion Door Flag : 0xdbec
+const uint16 dsAddr_johnNotyOutsideMansionDoorFlag = 0xdbec; // 1 byte
+// Unused Byte : 0xdbed
+// Lovestruck By Anne Flag : 0xdbee
+const uint16 dsAddr_lovestruckByAnneFlag = 0xdbee;// 1 byte
+// Mansion Handle in Door Hole Flag : 0xdbef
+const uint16 dsAddr_mansionHandleInDoorHoleFlag = 0xdbef;// 1 byte
+// Got Password Need to Speak To Barman Flag : 0xdbf0
+const uint16 dsAddr_gotPasswordNeedSpeakBarmanFlag = 0xdbf0; // 1 byte
+// Mansion Already Used Time Pills Flag : 0xdbf1
+const uint16 dsAddr_mansionAlreadyUsedTimePillsFlag = 0xdbf1; // 1 byte
+
+// Intro Credits #1 : 0xe3c2 to 0xe3e5 (Read Only)
+const uint16 dsAddr_introCredits1 = 0xe3c2; // "backgrounds ..."
+// Intro Credits #2 : 0xe3e6 to 0xe3fe (Read Only)
+const uint16 dsAddr_introCredits2 = 0xe3e6; // "music ..."
+// Intro Credits #3 : 0xe3ff to 0xe42e (Read Only)
+const uint16 dsAddr_introCredits3 = 0xe3ff; // "animation..."
+// Intro Credits #4 : 0xe42f to 0xe45b (Read Only)
+const uint16 dsAddr_introCredits4 = 0xe42f; // "programming..."
+// Credits #5 : 0xe45c to 0xe47b (Read Only)
+const uint16 dsAddr_credits5 = 0xe45c; // "after the tiring journey..."
+// Final Credits #6 : 0xe47c to 0xe487 (Read Only)
+const uint16 dsAddr_finalCredits6 = 0xe47c; // "THE END..."
+// Final Credits #7 : 0xe488 to 0xe782 (Read Only)
+const uint16 dsAddr_finalCredits7 = 0xe488; // "programming..."
+// 0xe783 to 0xe78f: 13 null bytes at end of dseg data - segment alignment padding?
+
class Resources {
-protected:
- Resources();
public:
- static Resources *instance();
+ Resources();
+ ~Resources();
bool loadArchives(const ADGameDescription *gd);
- void deinit();
+
void loadOff(Graphics::Surface &surface, byte *palette, int id);
Common::SeekableReadStream *loadLan(uint32 id) const;
Common::SeekableReadStream *loadLan000(uint32 id) const;
- //void loadOn(Graphics::Surface &surface, int id, uint16 &dst, uint16 *flags);
- //void loadOns(Graphics::Surface &surface, int id, uint16 &dst);
/*
* PSP (as the other sony playstation consoles - to be confirmed and 'ifdef'ed here too)
@@ -56,8 +1182,17 @@ public:
FilePack off, on, ons, lan000, lan500, sam_mmm, sam_sam, mmm, voices;
#endif
- Segment cseg, dseg, eseg;
+ Segment dseg;
Font font7, font8;
+
+ //const byte *getDialog(uint16 dialogNum) { return eseg.ptr(dialogOffsets[dialogNum]); }
+ uint16 getDialogAddr(uint16 dialogNum) { return dialogOffsets[dialogNum]; }
+
+ Segment eseg;
+private:
+ void precomputeDialogOffsets();
+
+ Common::Array<uint16> dialogOffsets;
};
} // End of namespace TeenAgent
diff --git a/engines/teenagent/scene.cpp b/engines/teenagent/scene.cpp
index 038c8ea05e..bdeb11a841 100644
--- a/engines/teenagent/scene.cpp
+++ b/engines/teenagent/scene.cpp
@@ -21,6 +21,7 @@
#include "common/config-manager.h"
#include "common/debug.h"
+#include "common/events.h"
#include "common/algorithm.h"
#include "common/ptr.h"
#include "common/textconsole.h"
@@ -28,24 +29,23 @@
#include "graphics/palette.h"
#include "teenagent/scene.h"
+#include "teenagent/inventory.h"
#include "teenagent/resources.h"
#include "teenagent/surface.h"
#include "teenagent/objects.h"
#include "teenagent/teenagent.h"
-#include "teenagent/dialog.h"
#include "teenagent/music.h"
namespace TeenAgent {
-Scene::Scene(TeenAgentEngine *engine, OSystem *system) : intro(false), _id(0), ons(0),
- orientation(kActorRight), actor_talking(false),
- message_timer(0), message_first_frame(0), message_last_frame(0), message_animation(NULL),
- current_event(SceneEvent::kNone), hide_actor(false), callback(0), callback_timer(0), _idle_timer(0) {
- _engine = engine;
- _system = system;
+Scene::Scene(TeenAgentEngine *vm) : _vm(vm), intro(false), _id(0), ons(0),
+ orientation(kActorRight), actorTalking(false), teenagent(vm), teenagentIdle(vm),
+ messageTimer(0), messageFirstFrame(0), messageLastFrame(0), messageAnimation(NULL),
+ currentEvent(SceneEvent::kNone), hideActor(false), callback(0), callbackTimer(0), _idleTimer(0) {
- _fade_timer = 0;
- on_enabled = true;
+ _fadeTimer = 0;
+ _fadeOld = 0;
+ onEnabled = true;
memset(palette, 0, sizeof(palette));
background.pixels = 0;
@@ -65,8 +65,8 @@ Scene::Scene(TeenAgentEngine *engine, OSystem *system) : intro(false), _id(0), o
if (!s)
error("invalid resource data");
- teenagent_idle.load(*s, Animation::kTypeVaria);
- if (teenagent_idle.empty())
+ teenagentIdle.load(*s, Animation::kTypeVaria);
+ if (teenagentIdle.empty())
error("invalid mark animation");
varia.close();
@@ -91,10 +91,10 @@ void Scene::warp(const Common::Point &_point, byte o) {
bool Scene::findPath(Scene::Path &p, const Common::Point &src, const Common::Point &dst) const {
const Common::Array<Walkbox> &scene_walkboxes = walkboxes[_id - 1];
- if (dst.x < 0 || dst.x > 319 || dst.y < 0 || dst.y > 199)
+ if (dst.x < 0 || dst.x >= kScreenWidth || dst.y < 0 || dst.y >= kScreenHeight)
return false;
- debug(1, "findPath %d,%d -> %d,%d", src.x, src.y, dst.x, dst.y);
+ debugC(1, kDebugScene, "findPath %d,%d -> %d,%d", src.x, src.y, dst.x, dst.y);
p.clear();
p.push_back(src);
p.push_back(dst);
@@ -113,7 +113,7 @@ bool Scene::findPath(Scene::Path &p, const Common::Point &src, const Common::Poi
break;
const Common::Point &p1 = *i, &p2 = *next;
- debug(1, "%d,%d -> %d,%d", p1.x, p1.y, p2.x, p2.y);
+ debugC(1, kDebugScene, "%d,%d -> %d,%d", p1.x, p1.y, p2.x, p2.y);
Common::List<uint>::iterator wi;
for (wi = boxes.begin(); wi != boxes.end(); ++wi) {
@@ -124,14 +124,14 @@ bool Scene::findPath(Scene::Path &p, const Common::Point &src, const Common::Poi
}
w.dump(1);
- debug(1, "%u: intersection mask 0x%04x, searching hints", *wi, mask);
+ debugC(1, kDebugScene, "%u: intersection mask 0x%04x, searching hints", *wi, mask);
int dx = p2.x - p1.x, dy = p2.y - p1.y;
if (dx >= 0) {
- if ((mask & 8) != 0 && w.side_hint[3] != 0) {
- debug(1, "hint left: %u", w.side_hint[3]);
+ if ((mask & 8) != 0 && w.sideHint[3] != 0) {
+ debugC(1, kDebugScene, "hint left: %u", w.sideHint[3]);
Common::Point w1, w2;
- w.rect.side(w1, w2, w.side_hint[3], p1);
- debug(1, "hint: %d,%d-%d,%d", w1.x, w1.y, w2.x, w2.y);
+ w.rect.side(w1, w2, w.sideHint[3], p1);
+ debugC(1, kDebugScene, "hint: %d,%d-%d,%d", w1.x, w1.y, w2.x, w2.y);
p.insert(next, w1);
if (mask & 2)
p.insert(next, w2);
@@ -139,11 +139,11 @@ bool Scene::findPath(Scene::Path &p, const Common::Point &src, const Common::Poi
break;
}
} else {
- if ((mask & 2) != 0 && w.side_hint[1] != 0) {
- debug(1, "hint right: %u", w.side_hint[1]);
+ if ((mask & 2) != 0 && w.sideHint[1] != 0) {
+ debugC(1, kDebugScene, "hint right: %u", w.sideHint[1]);
Common::Point w1, w2;
- w.rect.side(w1, w2, w.side_hint[1], p1);
- debug(1, "hint: %d,%d-%d,%d", w1.x, w1.y, w2.x, w2.y);
+ w.rect.side(w1, w2, w.sideHint[1], p1);
+ debugC(1, kDebugScene, "hint: %d,%d-%d,%d", w1.x, w1.y, w2.x, w2.y);
p.insert(next, w1);
if (mask & 8)
p.insert(next, w2);
@@ -153,11 +153,11 @@ bool Scene::findPath(Scene::Path &p, const Common::Point &src, const Common::Poi
}
if (dy >= 0) {
- if ((mask & 1) != 0 && w.side_hint[0] != 0) {
- debug(1, "hint top: %u", w.side_hint[0]);
+ if ((mask & 1) != 0 && w.sideHint[0] != 0) {
+ debugC(1, kDebugScene, "hint top: %u", w.sideHint[0]);
Common::Point w1, w2;
- w.rect.side(w1, w2, w.side_hint[0], p1);
- debug(1, "hint: %d,%d-%d,%d", w1.x, w1.y, w2.x, w2.y);
+ w.rect.side(w1, w2, w.sideHint[0], p1);
+ debugC(1, kDebugScene, "hint: %d,%d-%d,%d", w1.x, w1.y, w2.x, w2.y);
p.insert(next, w1);
if (mask & 4)
p.insert(next, w2);
@@ -165,11 +165,11 @@ bool Scene::findPath(Scene::Path &p, const Common::Point &src, const Common::Poi
break;
}
} else {
- if ((mask & 4) != 0 && w.side_hint[2] != 0) {
- debug(1, "hint bottom: %u", w.side_hint[2]);
+ if ((mask & 4) != 0 && w.sideHint[2] != 0) {
+ debugC(1, kDebugScene, "hint bottom: %u", w.sideHint[2]);
Common::Point w1, w2;
- w.rect.side(w1, w2, w.side_hint[2], p1);
- debug(1, "hint: %d,%d-%d,%d", w1.x, w1.y, w2.x, w2.y);
+ w.rect.side(w1, w2, w.sideHint[2], p1);
+ debugC(1, kDebugScene, "hint: %d,%d-%d,%d", w1.x, w1.y, w2.x, w2.y);
p.insert(next, w1);
if (mask & 1)
p.insert(next, w2);
@@ -187,13 +187,13 @@ bool Scene::findPath(Scene::Path &p, const Common::Point &src, const Common::Poi
void Scene::moveTo(const Common::Point &_point, byte orient, bool validate) {
Common::Point point(_point);
- debug(0, "moveTo(%d, %d, %u)", point.x, point.y, orient);
+ debugC(0, kDebugScene, "moveTo(%d, %d, %u)", point.x, point.y, orient);
const Common::Array<Walkbox> &scene_walkboxes = walkboxes[_id - 1];
for (byte i = 0; i < scene_walkboxes.size(); ++i) {
const Walkbox &w = scene_walkboxes[i];
if (w.rect.in(point)) {
- debug(0, "bumped into walkbox %u", i);
+ debugC(0, kDebugScene, "bumped into walkbox %u", i);
w.dump();
byte o = w.orientation;
switch (o) {
@@ -229,7 +229,7 @@ void Scene::moveTo(const Common::Point &_point, byte orient, bool validate) {
}
if (!findPath(path, position, point)) {
- _engine->cancel();
+ _vm->cancel();
return;
}
@@ -237,55 +237,53 @@ void Scene::moveTo(const Common::Point &_point, byte orient, bool validate) {
}
void Scene::loadObjectData() {
- Resources *res = Resources::instance();
-
//loading objects & walkboxes
objects.resize(42);
walkboxes.resize(42);
fades.resize(42);
for (byte i = 0; i < 42; ++i) {
- Common::Array<Object> &scene_objects = objects[i];
- scene_objects.clear();
+ Common::Array<Object> &sceneObjects = objects[i];
+ sceneObjects.clear();
- uint16 scene_table = res->dseg.get_word(0x7254 + i * 2);
- uint16 object_addr;
- while ((object_addr = res->dseg.get_word(scene_table)) != 0) {
+ uint16 sceneTable = _vm->res->dseg.get_word(dsAddr_sceneObjectTablePtr + (i * 2));
+ uint16 objectAddr;
+ while ((objectAddr = _vm->res->dseg.get_word(sceneTable)) != 0) {
Object obj;
- obj.load(res->dseg.ptr(object_addr));
+ obj.load(_vm->res->dseg.ptr(objectAddr));
//obj.dump();
- scene_objects.push_back(obj);
- scene_table += 2;
+ sceneObjects.push_back(obj);
+ sceneTable += 2;
}
- debug(0, "scene[%u] has %u object(s)", i + 1, scene_objects.size());
+ debugC(0, kDebugScene, "scene[%u] has %u object(s)", i + 1, sceneObjects.size());
- byte *walkboxes_base = res->dseg.ptr(READ_LE_UINT16(res->dseg.ptr(0x6746 + i * 2)));
- byte walkboxes_n = *walkboxes_base++;
- debug(0, "scene[%u] has %u walkboxes", i + 1, walkboxes_n);
+ byte *walkboxesBase = _vm->res->dseg.ptr(READ_LE_UINT16(_vm->res->dseg.ptr(dsAddr_sceneWalkboxTablePtr + i * 2)));
+ byte walkboxesCount = *walkboxesBase++;
+ debugC(0, kDebugScene, "scene[%u] has %u walkboxes", i + 1, walkboxesCount);
- Common::Array<Walkbox> &scene_walkboxes = walkboxes[i];
- for (byte j = 0; j < walkboxes_n; ++j) {
+ Common::Array<Walkbox> &sceneWalkboxes = walkboxes[i];
+ for (byte j = 0; j < walkboxesCount; ++j) {
Walkbox w;
- w.load(walkboxes_base + 14 * j);
- if ((w.side_hint[0] | w.side_hint[1] | w.side_hint[2] | w.side_hint[3]) == 0) {
- w.side_hint[0] = 2;
- w.side_hint[1] = 3;
- w.side_hint[2] = 4;
- w.side_hint[3] = 1;
+ w.load(walkboxesBase + 14 * j);
+ if ((w.sideHint[0] | w.sideHint[1] | w.sideHint[2] | w.sideHint[3]) == 0) {
+ w.sideHint[0] = 2;
+ w.sideHint[1] = 3;
+ w.sideHint[2] = 4;
+ w.sideHint[3] = 1;
}
//walkbox[i]->dump();
- scene_walkboxes.push_back(w);
+ sceneWalkboxes.push_back(w);
}
- byte *fade_table = res->dseg.ptr(res->dseg.get_word(0x663e + i * 2));
- Common::Array<FadeType> &scene_fades = fades[i];
- while (READ_LE_UINT16(fade_table) != 0xffff) {
+ byte *fadeTable = _vm->res->dseg.ptr(_vm->res->dseg.get_word(dsAddr_sceneFadeTablePtr + i * 2));
+ Common::Array<FadeType> &sceneFades = fades[i];
+ while (READ_LE_UINT16(fadeTable) != 0xffff) {
FadeType fade;
- fade.load(fade_table);
- fade_table += 9;
- scene_fades.push_back(fade);
+ fade.load(fadeTable);
+ fadeTable += 9;
+ sceneFades.push_back(fade);
}
- debug(0, "scene[%u] has %u fadeboxes", i + 1, scene_fades.size());
+ debugC(0, kDebugScene, "scene[%u] has %u fadeboxes", i + 1, sceneFades.size());
}
}
@@ -293,10 +291,10 @@ Object *Scene::findObject(const Common::Point &point) {
if (_id == 0)
return NULL;
- Common::Array<Object> &scene_objects = objects[_id - 1];
+ Common::Array<Object> &sceneObjects = objects[_id - 1];
- for (uint i = 0; i < scene_objects.size(); ++i) {
- Object &obj = scene_objects[i];
+ for (uint i = 0; i < sceneObjects.size(); ++i) {
+ Object &obj = sceneObjects[i];
if (obj.enabled != 0 && obj.rect.in(point))
return &obj;
}
@@ -304,41 +302,38 @@ Object *Scene::findObject(const Common::Point &point) {
}
byte *Scene::getOns(int id) {
- Resources *res = Resources::instance();
- return res->dseg.ptr(res->dseg.get_word(0xb4f5 + (id - 1) * 2));
+ return _vm->res->dseg.ptr(_vm->res->dseg.get_word(dsAddr_onsAnimationTablePtr + (id - 1) * 2));
}
byte *Scene::getLans(int id) {
- Resources *res = Resources::instance();
- return res->dseg.ptr(0xd89e + (id - 1) * 4);
+ return _vm->res->dseg.ptr(dsAddr_lansAnimationTablePtr + (id - 1) * 4);
}
void Scene::loadOns() {
- debug(0, "loading ons animation");
- Resources *res = Resources::instance();
+ debugC(0, kDebugScene, "loading ons animation");
- uint16 addr = res->dseg.get_word(0xb4f5 + (_id - 1) * 2);
- //debug(0, "ons index: %04x", addr);
+ uint16 addr = _vm->res->dseg.get_word(dsAddr_onsAnimationTablePtr + (_id - 1) * 2);
+ debugC(0, kDebugScene, "ons index: %04x", addr);
- ons_count = 0;
+ onsCount = 0;
byte b;
- byte on_id[16];
- while ((b = res->dseg.get_byte(addr)) != 0xff) {
- debug(0, "on: %04x = %02x", addr, b);
+ byte onId[16];
+ while ((b = _vm->res->dseg.get_byte(addr)) != 0xff) {
+ debugC(0, kDebugScene, "on: %04x = %02x", addr, b);
++addr;
if (b == 0)
continue;
- on_id[ons_count++] = b;
+ onId[onsCount++] = b;
}
delete[] ons;
ons = NULL;
- if (ons_count > 0) {
- ons = new Surface[ons_count];
- for (uint32 i = 0; i < ons_count; ++i) {
- Common::ScopedPtr<Common::SeekableReadStream> s(res->ons.getStream(on_id[i]));
+ if (onsCount > 0) {
+ ons = new Surface[onsCount];
+ for (uint32 i = 0; i < onsCount; ++i) {
+ Common::ScopedPtr<Common::SeekableReadStream> s(_vm->res->ons.getStream(onId[i]));
if (s) {
ons[i].load(*s, Surface::kTypeOns);
}
@@ -347,21 +342,20 @@ void Scene::loadOns() {
}
void Scene::loadLans() {
- debug(0, "loading lans animation");
- Resources *res = Resources::instance();
- //load lan000
+ debugC(0, kDebugScene, "loading lans animation");
+ // load lan000
for (byte i = 0; i < 4; ++i) {
animation[i].free();
- uint16 bx = 0xd89e + (_id - 1) * 4 + i;
- byte bxv = res->dseg.get_byte(bx);
- uint16 res_id = 4 * (_id - 1) + i + 1;
- debug(0, "lan[%u]@%04x = %02x, resource id: %u", i, bx, bxv, res_id);
+ uint16 bx = dsAddr_lansAnimationTablePtr + (_id - 1) * 4 + i;
+ byte bxv = _vm->res->dseg.get_byte(bx);
+ uint16 resId = 4 * (_id - 1) + i + 1;
+ debugC(0, kDebugScene, "lan[%u]@%04x = %02x, resource id: %u", i, bx, bxv, resId);
if (bxv == 0)
continue;
- Common::ScopedPtr<Common::SeekableReadStream> s(res->loadLan000(res_id));
+ Common::ScopedPtr<Common::SeekableReadStream> s(_vm->res->loadLan000(resId));
if (s) {
animation[i].load(*s, Animation::kTypeLan);
if (bxv != 0 && bxv != 0xff)
@@ -371,24 +365,23 @@ void Scene::loadLans() {
}
void Scene::init(int id, const Common::Point &pos) {
- debug(0, "init(%d)", id);
+ debugC(0, kDebugScene, "init(%d)", id);
_id = id;
- on_enabled = true; //reset on-rendering flag on loading.
+ onEnabled = true; //reset on-rendering flag on loading.
sounds.clear();
for (byte i = 0; i < 4; ++i)
- custom_animation[i].free();
+ customAnimation[i].free();
if (background.pixels == NULL)
- background.create(320, 200, Graphics::PixelFormat::createFormatCLUT8());
+ background.create(kScreenWidth, kScreenHeight, Graphics::PixelFormat::createFormatCLUT8());
warp(pos);
- Resources *res = Resources::instance();
- res->loadOff(background, palette, id);
+ _vm->res->loadOff(background, palette, id);
if (id == 24) {
- //dark scene
- if (res->dseg.get_byte(0xDBA4) != 1) {
- //dim down palette
+ // dark scene
+ if (_vm->res->dseg.get_byte(dsAddr_lightOnFlag) != 1) {
+ // dim down palette
uint i;
for (i = 0; i < 624; ++i) {
palette[i] = palette[i] > 0x20 ? palette[i] - 0x20 : 0;
@@ -399,62 +392,62 @@ void Scene::init(int id, const Common::Point &pos) {
}
}
- Common::ScopedPtr<Common::SeekableReadStream> stream(res->on.getStream(id));
- int sub_hack = 0;
- if (id == 7) { //something patched in the captains room
- switch (res->dseg.get_byte(0xdbe6)) {
+ Common::ScopedPtr<Common::SeekableReadStream> stream(_vm->res->on.getStream(id));
+ int subHack = 0;
+ if (id == 7) { // something patched in the captains room
+ switch (_vm->res->dseg.get_byte(dsAddr_captainDrawerState)) {
case 2:
break;
case 1:
- sub_hack = 1;
+ subHack = 1;
break;
default:
- sub_hack = 2;
+ subHack = 2;
}
}
- on.load(*stream, SurfaceList::kTypeOn, sub_hack);
+ on.load(*stream, subHack);
loadOns();
loadLans();
- //check music
- int now_playing = _engine->music->getId();
+ // check music
+ int nowPlaying = _vm->music->getId();
- if (now_playing != res->dseg.get_byte(0xDB90))
- _engine->music->load(res->dseg.get_byte(0xDB90));
+ if (nowPlaying != _vm->res->dseg.get_byte(dsAddr_currentMusic))
+ _vm->music->load(_vm->res->dseg.get_byte(dsAddr_currentMusic));
- _system->copyRectToScreen(background.pixels, background.pitch, 0, 0, background.w, background.h);
+ _vm->_system->copyRectToScreen(background.pixels, background.pitch, 0, 0, background.w, background.h);
setPalette(0);
}
void Scene::playAnimation(byte idx, uint id, bool loop, bool paused, bool ignore) {
- debug(0, "playAnimation(%u, %u, loop:%s, paused:%s, ignore:%s)", idx, id, loop ? "true" : "false", paused ? "true" : "false", ignore ? "true" : "false");
+ debugC(0, kDebugScene, "playAnimation(%u, %u, loop:%s, paused:%s, ignore:%s)", idx, id, loop ? "true" : "false", paused ? "true" : "false", ignore ? "true" : "false");
assert(idx < 4);
- Common::ScopedPtr<Common::SeekableReadStream> s(Resources::instance()->loadLan(id + 1));
+ Common::ScopedPtr<Common::SeekableReadStream> s(_vm->res->loadLan(id + 1));
if (!s)
error("playing animation %u failed", id);
- custom_animation[idx].load(*s);
- custom_animation[idx].loop = loop;
- custom_animation[idx].paused = paused;
- custom_animation[idx].ignore = ignore;
+ customAnimation[idx].load(*s);
+ customAnimation[idx].loop = loop;
+ customAnimation[idx].paused = paused;
+ customAnimation[idx].ignore = ignore;
}
void Scene::playActorAnimation(uint id, bool loop, bool ignore) {
- debug(0, "playActorAnimation(%u, loop:%s, ignore:%s)", id, loop ? "true" : "false", ignore ? "true" : "false");
- Common::ScopedPtr<Common::SeekableReadStream> s(Resources::instance()->loadLan(id + 1));
+ debugC(0, kDebugScene, "playActorAnimation(%u, loop:%s, ignore:%s)", id, loop ? "true" : "false", ignore ? "true" : "false");
+ Common::ScopedPtr<Common::SeekableReadStream> s(_vm->res->loadLan(id + 1));
if (!s)
error("playing animation %u failed", id);
- actor_animation.load(*s);
- actor_animation.loop = loop;
- actor_animation.ignore = ignore;
- actor_animation.id = id;
+ actorAnimation.load(*s);
+ actorAnimation.loop = loop;
+ actorAnimation.ignore = ignore;
+ actorAnimation.id = id;
}
Animation *Scene::getAnimation(byte slot) {
assert(slot < 4);
- return custom_animation + slot;
+ return customAnimation + slot;
}
byte Scene::peekFlagEvent(uint16 addr) const {
@@ -463,17 +456,17 @@ byte Scene::peekFlagEvent(uint16 addr) const {
if (e.type == SceneEvent::kSetFlag && e.callback == addr)
return e.color;
}
- return Resources::instance()->dseg.get_byte(addr);
+ return _vm->res->dseg.get_byte(addr);
}
void Scene::push(const SceneEvent &event) {
- //debug(0, "push");
+ debugC(0, kDebugScene, "push");
//event.dump();
if (event.type == SceneEvent::kWalk && !events.empty()) {
SceneEvent &prev = events.back();
if (prev.type == SceneEvent::kWalk && prev.color == event.color) {
- debug(0, "fixing double-move [skipping event!]");
- if ((event.color & 2) != 0) { //relative move
+ debugC(0, kDebugScene, "fixing double-move [skipping event!]");
+ if ((event.color & 2) != 0) { // relative move
prev.dst.x += event.dst.x;
prev.dst.y += event.dst.y;
} else {
@@ -489,7 +482,7 @@ bool Scene::processEvent(const Common::Event &event) {
switch (event.type) {
case Common::EVENT_LBUTTONDOWN:
case Common::EVENT_RBUTTONDOWN:
- if (!message.empty() && message_first_frame == 0) {
+ if (!message.empty() && messageFirstFrame == 0) {
clearMessage();
nextEvent();
return true;
@@ -505,16 +498,16 @@ bool Scene::processEvent(const Common::Event &event) {
clearMessage();
events.clear();
sounds.clear();
- current_event.clear();
- message_color = 0xd1;
+ currentEvent.clear();
+ messageColor = textColorMark;
for (int i = 0; i < 4; ++i)
- custom_animation[i].free();
- _engine->playMusic(4);
- _engine->loadScene(10, Common::Point(136, 153));
+ customAnimation[i].free();
+ _vm->playMusic(4);
+ _vm->loadScene(10, Common::Point(136, 153));
return true;
}
- if (!message.empty() && message_first_frame == 0) {
+ if (!message.empty() && messageFirstFrame == 0) {
clearMessage();
nextEvent();
return true;
@@ -534,8 +527,8 @@ bool Scene::processEvent(const Common::Event &event) {
if (event.kbd.flags & Common::KBD_CTRL) {
uint feature = event.kbd.keycode - '1';
if (feature < DebugFeatures::kMax) {
- debug_features.feature[feature] = !debug_features.feature[feature];
- debug(0, "switched feature %u %s", feature, debug_features.feature[feature] ? "on" : "off");
+ debugFeatures.feature[feature] = !debugFeatures.feature[feature];
+ debugC(0, kDebugScene, "switched feature %u %s", feature, debugFeatures.feature[feature] ? "on" : "off");
}
}
break;
@@ -556,25 +549,22 @@ struct ZOrderCmp {
};
int Scene::lookupZoom(uint y) const {
- Resources *res = Resources::instance();
- for (byte *zoom_table = res->dseg.ptr(res->dseg.get_word(0x70f4 + (_id - 1) * 2));
- zoom_table[0] != 0xff && zoom_table[1] != 0xff;
- zoom_table += 2) {
- //debug(0, "%d %d->%d", y, zoom_table[0], zoom_table[1]);
- if (y <= zoom_table[0]) {
- //debug(0, "%d %d->%d", y, zoom_table[0], zoom_table[1]);
- return 256u * (100 - zoom_table[1]) / 100;
+ debugC(2, kDebugScene, "lookupZoom(%d)", y);
+ for (byte *zoomTable = _vm->res->dseg.ptr(_vm->res->dseg.get_word(dsAddr_sceneZoomTablePtr + (_id - 1) * 2));
+ zoomTable[0] != 0xff && zoomTable[1] != 0xff;
+ zoomTable += 2) {
+ debugC(2, kDebugScene, "\t%d %d->%d", y, zoomTable[0], zoomTable[1]);
+ if (y <= zoomTable[0]) {
+ return 256u * (100 - zoomTable[1]) / 100;
}
}
return 256;
}
-
void Scene::paletteEffect(byte step) {
- Resources *res = Resources::instance();
- byte *src = res->dseg.ptr(0x6609);
- byte *dst = palette + 3 * 0xf2;
- for (byte i = 0; i < 0xd; ++i) {
+ byte *src = _vm->res->dseg.ptr(dsAddr_paletteEffectData);
+ byte *dst = palette + (3 * 242);
+ for (byte i = 0; i < 13; ++i) {
for (byte c = 0; c < 3; ++c, ++src)
*dst++ = *src > step ? *src - step : 0;
}
@@ -584,9 +574,9 @@ byte Scene::findFade() const {
if (_id <= 0)
return 0;
- const Common::Array<FadeType> &scene_fades = fades[_id - 1];
- for (uint i = 0; i < scene_fades.size(); ++i) {
- const FadeType &fade = scene_fades[i];
+ const Common::Array<FadeType> &sceneFades = fades[_id - 1];
+ for (uint i = 0; i < sceneFades.size(); ++i) {
+ const FadeType &fade = sceneFades[i];
if (fade.rect.in(position)) {
return fade.value;
}
@@ -594,110 +584,109 @@ byte Scene::findFade() const {
return 0;
}
-bool Scene::render(bool tick_game, bool tick_mark, uint32 delta) {
- Resources *res = Resources::instance();
+bool Scene::render(bool tickGame, bool tickMark, uint32 messageDelta) {
bool busy;
bool restart;
- uint32 game_delta = tick_game ? 1 : 0;
- uint32 mark_delta = tick_mark ? 1 : 0;
+ uint32 gameDelta = tickGame ? 1 : 0;
+ uint32 markDelta = tickMark ? 1 : 0;
do {
restart = false;
busy = processEventQueue();
- if (_fade_timer && game_delta != 0) {
- if (_fade_timer > 0) {
- _fade_timer -= game_delta;
- setPalette(_fade_timer);
+ if (_fadeTimer && gameDelta != 0) {
+ if (_fadeTimer > 0) {
+ _fadeTimer -= gameDelta;
+ setPalette(_fadeTimer);
} else {
- _fade_timer += game_delta;
- setPalette(_fade_timer + 4);
+ _fadeTimer += gameDelta;
+ setPalette(_fadeTimer + 4);
}
}
- switch (current_event.type) {
+ switch (currentEvent.type) {
case SceneEvent::kCredits: {
- _system->fillScreen(0);
- ///\todo: optimize me
- Graphics::Surface *surface = _system->lockScreen();
- res->font7.render(surface, current_event.dst.x, current_event.dst.y -= game_delta, current_event.message, current_event.color);
- _system->unlockScreen();
-
- if (current_event.dst.y < -(int)current_event.timer)
- current_event.clear();
+ _vm->_system->fillScreen(0);
+ // TODO: optimize me
+ Graphics::Surface *surface = _vm->_system->lockScreen();
+ _vm->res->font7.render(surface, currentEvent.dst.x, currentEvent.dst.y -= gameDelta, currentEvent.message, currentEvent.color);
+ _vm->_system->unlockScreen();
+
+ if (currentEvent.dst.y < -(int)currentEvent.timer)
+ currentEvent.clear();
}
return true;
default:
;
}
- if (!message.empty() && message_timer != 0) {
- if (message_timer <= delta) {
+ if (!message.empty() && messageTimer != 0) {
+ if (messageTimer <= messageDelta) {
clearMessage();
nextEvent();
continue;
} else
- message_timer -= delta;
+ messageTimer -= messageDelta;
}
- if (current_event.type == SceneEvent::kCreditsMessage) {
- _system->fillScreen(0);
- Graphics::Surface *surface = _system->lockScreen();
- if (current_event.lan == 8) {
- res->font8.shadow_color = current_event.orientation;
- res->font8.render(surface, current_event.dst.x, current_event.dst.y, message, current_event.color);
+ if (currentEvent.type == SceneEvent::kCreditsMessage) {
+ _vm->_system->fillScreen(0);
+ Graphics::Surface *surface = _vm->_system->lockScreen();
+ if (currentEvent.lan == 8) {
+ _vm->res->font8.setShadowColor(currentEvent.orientation);
+ _vm->res->font8.render(surface, currentEvent.dst.x, currentEvent.dst.y, message, currentEvent.color);
} else {
- res->font7.render(surface, current_event.dst.x, current_event.dst.y, message, 0xd1);
+ _vm->res->font7.render(surface, currentEvent.dst.x, currentEvent.dst.y, message, textColorCredits);
}
- _system->unlockScreen();
+ _vm->_system->unlockScreen();
return true;
}
- if (background.pixels && debug_features.feature[DebugFeatures::kShowBack]) {
- _system->copyRectToScreen(background.pixels, background.pitch, 0, 0, background.w, background.h);
+ if (background.pixels && debugFeatures.feature[DebugFeatures::kShowBack]) {
+ _vm->_system->copyRectToScreen(background.pixels, background.pitch, 0, 0, background.w, background.h);
} else
- _system->fillScreen(0);
+ _vm->_system->fillScreen(0);
- Graphics::Surface *surface = _system->lockScreen();
+ Graphics::Surface *surface = _vm->_system->lockScreen();
- bool got_any_animation = false;
+ bool gotAnyAnimation = false;
- if (ons != NULL && debug_features.feature[DebugFeatures::kShowOns]) {
- for (uint32 i = 0; i < ons_count; ++i) {
+ if (ons != NULL && debugFeatures.feature[DebugFeatures::kShowOns]) {
+ for (uint32 i = 0; i < onsCount; ++i) {
Surface *s = ons + i;
if (s != NULL)
s->render(surface);
}
}
- Common::List<Surface *> z_order;
+ Common::List<Surface *> zOrder;
for (byte i = 0; i < 4; ++i) {
- Animation *a = custom_animation + i;
- Surface *s = a->currentFrame(game_delta);
+ Animation *a = customAnimation + i;
+ Surface *s = a->currentFrame(gameDelta);
if (s != NULL) {
if (!a->ignore)
busy = true;
if (!a->paused && !a->loop)
- got_any_animation = true;
+ gotAnyAnimation = true;
} else {
a = animation + i;
- if (!custom_animation[i].empty()) {
- debug(0, "custom animation ended, restart animation in the same slot.");
- custom_animation[i].free();
+ if (!customAnimation[i].empty()) {
+ debugC(0, kDebugScene, "custom animation ended, restart animation in the same slot.");
+ customAnimation[i].free();
a->restart();
}
- s = a->currentFrame(game_delta);
+ s = a->currentFrame(gameDelta);
}
- if (current_event.type == SceneEvent::kWaitLanAnimationFrame && current_event.slot == i) {
+ if (currentEvent.type == SceneEvent::kWaitLanAnimationFrame && currentEvent.slot == i) {
if (s == NULL) {
restart |= nextEvent();
continue;
}
int index = a->currentIndex();
- if (index == current_event.animation) {
- debug(0, "kWaitLanAnimationFrame(%d, %d) complete", current_event.slot, current_event.animation);
+ if (index == currentEvent.animation) {
+ debugC(0, kDebugScene, "kWaitLanAnimationFrame(%d, %d) complete", currentEvent.slot, currentEvent.animation);
restart |= nextEvent();
}
}
@@ -705,8 +694,8 @@ bool Scene::render(bool tick_game, bool tick_mark, uint32 delta) {
if (s == NULL)
continue;
- if (debug_features.feature[DebugFeatures::kShowLan])
- z_order.push_back(s);
+ if (debugFeatures.feature[DebugFeatures::kShowLan])
+ zOrder.push_back(s);
if (a->id == 0)
continue;
@@ -722,38 +711,36 @@ bool Scene::render(bool tick_game, bool tick_mark, uint32 delta) {
}
}
- Common::sort(z_order.begin(), z_order.end(), ZOrderCmp());
- Common::List<Surface *>::iterator z_order_it;
+ Common::sort(zOrder.begin(), zOrder.end(), ZOrderCmp());
+ Common::List<Surface *>::iterator zOrderIter;
- Surface *mark = actor_animation.currentFrame(game_delta);
+ Surface *mark = actorAnimation.currentFrame(gameDelta);
int horizon = position.y;
- for (z_order_it = z_order.begin(); z_order_it != z_order.end(); ++z_order_it) {
- Surface *s = *z_order_it;
+ for (zOrderIter = zOrder.begin(); zOrderIter != zOrder.end(); ++zOrderIter) {
+ Surface *s = *zOrderIter;
if (s->y + s->h > horizon)
break;
s->render(surface);
}
if (mark != NULL) {
- actor_animation_position = mark->render(surface);
- if (!actor_animation.ignore)
+ actorAnimationPosition = mark->render(surface);
+ if (!actorAnimation.ignore)
busy = true;
else
busy = false;
- got_any_animation = true;
- } else if (!hide_actor) {
- actor_animation.free();
+ gotAnyAnimation = true;
+ } else if (!hideActor) {
+ actorAnimation.free();
uint zoom = lookupZoom(position.y);
- {
- byte fade = findFade();
- static byte old_fade = 0;
- if (fade != old_fade) {
- old_fade = fade;
- paletteEffect(fade);
- if (_fade_timer == 0)
- setPalette(4);
- }
+
+ byte fade = findFade();
+ if (fade != _fadeOld) {
+ _fadeOld = fade;
+ paletteEffect(fade);
+ if (_fadeTimer == 0)
+ setPalette(4);
}
if (!path.empty()) {
@@ -767,31 +754,31 @@ bool Scene::render(bool tick_game, bool tick_mark, uint32 delta) {
o = dp.y > 0 ? kActorDown : kActorUp;
}
- if (tick_mark) {
- int speed_x = zoom / 32; //8 * zoom / 256
- int speed_y = (o == kActorDown || o == kActorUp ? 2 : 1) * zoom / 256;
- if (speed_x == 0)
- speed_x = 1;
- if (speed_y == 0)
- speed_y = 1;
+ if (tickMark) {
+ int speedX = zoom / 32; // 8 * zoom / 256
+ int speedY = (o == kActorDown || o == kActorUp ? 2 : 1) * zoom / 256;
+ if (speedX == 0)
+ speedX = 1;
+ if (speedY == 0)
+ speedY = 1;
- position.y += (ABS(dp.y) < speed_y ? dp.y : SIGN(dp.y) * speed_y);
+ position.y += (ABS(dp.y) < speedY ? dp.y : SIGN(dp.y) * speedY);
position.x += (o == kActorDown || o == kActorUp) ?
- (ABS(dp.x) < speed_y ? dp.x : SIGN(dp.x) * speed_y) :
- (ABS(dp.x) < speed_x ? dp.x : SIGN(dp.x) * speed_x);
+ (ABS(dp.x) < speedY ? dp.x : SIGN(dp.x) * speedY) :
+ (ABS(dp.x) < speedX ? dp.x : SIGN(dp.x) * speedX);
}
- _idle_timer = 0;
- teenagent_idle.resetIndex();
- actor_animation_position = teenagent.render(surface, position, o, mark_delta, false, zoom);
+ _idleTimer = 0;
+ teenagentIdle.resetIndex();
+ actorAnimationPosition = teenagent.render(surface, position, o, markDelta, false, zoom);
- if (tick_mark && position == destination) {
+ if (tickMark && position == destination) {
path.pop_front();
if (path.empty()) {
if (orientation == 0)
- orientation = o; //save last orientation
+ orientation = o; // save last orientation
nextEvent();
- got_any_animation = true;
+ gotAnyAnimation = true;
restart = true;
}
busy = true;
@@ -799,65 +786,63 @@ bool Scene::render(bool tick_game, bool tick_mark, uint32 delta) {
busy = true;
} else {
teenagent.resetIndex();
- _idle_timer += mark_delta;
- if (_idle_timer < 50)
- actor_animation_position = teenagent.render(surface, position, orientation, 0, actor_talking, zoom);
+ _idleTimer += markDelta;
+ if (_idleTimer < 50)
+ actorAnimationPosition = teenagent.render(surface, position, orientation, 0, actorTalking, zoom);
else
- actor_animation_position = teenagent_idle.renderIdle(surface, position, orientation, mark_delta, zoom, _engine->_rnd);
+ actorAnimationPosition = teenagentIdle.renderIdle(surface, position, orientation, markDelta, zoom, _vm->_rnd);
}
}
if (restart) {
- _system->unlockScreen();
+ _vm->_system->unlockScreen();
continue;
}
- //removed mark == null. In final scene of chapter 2 mark rendered above table.
- //if it'd cause any bugs, add hack here. (_id != 23 && mark == NULL)
- if (on_enabled &&
- debug_features.feature[DebugFeatures::kShowOn]) {
- on.render(surface, actor_animation_position);
- }
+ // removed mark == null. In final scene of chapter 2 mark rendered above table.
+ // if it'd cause any bugs, add hack here. (_id != 23 && mark == NULL)
+ if (onEnabled && debugFeatures.feature[DebugFeatures::kShowOn])
+ on.render(surface, actorAnimationPosition);
- for (; z_order_it != z_order.end(); ++z_order_it) {
- Surface *s = *z_order_it;
+ for (; zOrderIter != zOrder.end(); ++zOrderIter) {
+ Surface *s = *zOrderIter;
s->render(surface);
}
if (!message.empty()) {
bool visible = true;
- if (message_first_frame != 0 && message_animation != NULL) {
- int index = message_animation->currentIndex() + 1;
- //debug(0, "message: %s first: %u index: %u", message.c_str(), message_first_frame, index);
- if (index < message_first_frame)
+ if (messageFirstFrame != 0 && messageAnimation != NULL) {
+ int index = messageAnimation->currentIndex() + 1;
+ debugC(0, kDebugScene, "message: %s first: %u index: %u", message.c_str(), messageFirstFrame, index);
+ if (index < messageFirstFrame)
visible = false;
- if (index > message_last_frame) {
+ if (index > messageLastFrame) {
clearMessage();
visible = false;
}
}
if (visible) {
- res->font7.render(surface, message_pos.x, message_pos.y, message, message_color);
+ _vm->res->font7.render(surface, messagePos.x, messagePos.y, message, messageColor);
busy = true;
}
}
- if (!busy && !restart && tick_game && callback_timer) {
- if (--callback_timer == 0) {
- if (_engine->inventory->active())
- _engine->inventory->activate(false);
- _engine->processCallback(callback);
+ if (!busy && !restart && tickGame && callbackTimer) {
+ if (--callbackTimer == 0) {
+ if (_vm->inventory->active())
+ _vm->inventory->activate(false);
+ _vm->processCallback(callback);
}
- //debug(0, "callback timer = %u", callback_timer);
+ debugC(0, kDebugScene, "callback timer = %u", callbackTimer);
}
//if (!current_event.empty())
// current_event.dump();
- if (!debug_features.feature[DebugFeatures::kHidePath]) {
- const Common::Array<Walkbox> & scene_walkboxes = walkboxes[_id - 1];
- for (uint i = 0; i < scene_walkboxes.size(); ++i) {
- scene_walkboxes[i].rect.render(surface, 0xd0 + i);
+ if (!debugFeatures.feature[DebugFeatures::kHidePath]) {
+ const Common::Array<Walkbox> & sceneWalkboxes = walkboxes[_id - 1];
+ for (uint i = 0; i < sceneWalkboxes.size(); ++i) {
+ sceneWalkboxes[i].rect.render(surface, 0xd0 + i);
}
Common::Point last_p = position;
@@ -872,39 +857,39 @@ bool Scene::render(bool tick_game, bool tick_mark, uint32 delta) {
}
}
- _system->unlockScreen();
+ _vm->_system->unlockScreen();
- if (current_event.type == SceneEvent::kWait) {
- if (current_event.timer > delta) {
+ if (currentEvent.type == SceneEvent::kWait) {
+ if (currentEvent.timer > messageDelta) {
busy = true;
- current_event.timer -= delta;
+ currentEvent.timer -= messageDelta;
}
- if (current_event.timer <= delta)
+ if (currentEvent.timer <= messageDelta)
restart |= nextEvent();
}
- if (!restart && current_event.type == SceneEvent::kWaitForAnimation && !got_any_animation) {
- debug(0, "no animations, nextevent");
+ if (!restart && currentEvent.type == SceneEvent::kWaitForAnimation && !gotAnyAnimation) {
+ debugC(0, kDebugScene, "no animations, nextevent");
nextEvent();
restart = true;
}
if (busy) {
- _idle_timer = 0;
- teenagent_idle.resetIndex();
+ _idleTimer = 0;
+ teenagentIdle.resetIndex();
}
} while (restart);
for (Sounds::iterator i = sounds.begin(); i != sounds.end();) {
Sound &sound = *i;
if (sound.delay == 0) {
- debug(1, "sound %u started", sound.id);
- _engine->playSoundNow(sound.id);
+ debugC(1, kDebugScene, "sound %u started", sound.id);
+ _vm->playSoundNow(sound.id);
i = sounds.erase(i);
} else {
- sound.delay -= game_delta;
+ sound.delay -= gameDelta;
++i;
}
}
@@ -913,363 +898,364 @@ bool Scene::render(bool tick_game, bool tick_mark, uint32 delta) {
}
bool Scene::processEventQueue() {
- while (!events.empty() && current_event.empty()) {
- //debug(0, "processing next event");
- current_event = events.front();
+ while (!events.empty() && currentEvent.empty()) {
+ debugC(0, kDebugScene, "processing next event");
+ currentEvent = events.front();
events.pop_front();
- switch (current_event.type) {
+ switch (currentEvent.type) {
case SceneEvent::kSetOn: {
- byte on_id = current_event.ons;
- if (on_id != 0) {
- --on_id;
- byte *ptr = getOns(current_event.scene == 0 ? _id : current_event.scene);
- debug(0, "on[%u] = %02x", on_id, current_event.color);
- ptr[on_id] = current_event.color;
+ byte onId = currentEvent.ons;
+ if (onId != 0) {
+ --onId;
+ byte *ptr = getOns(currentEvent.scene == 0 ? _id : currentEvent.scene);
+ debugC(0, kDebugScene, "on[%u] = %02x", onId, currentEvent.color);
+ ptr[onId] = currentEvent.color;
} else {
- on_enabled = current_event.color != 0;
- debug(0, "%s on rendering", on_enabled ? "enabling" : "disabling");
+ onEnabled = currentEvent.color != 0;
+ debugC(0, kDebugScene, "%s on rendering", onEnabled ? "enabling" : "disabling");
}
loadOns();
- current_event.clear();
+ currentEvent.clear();
}
break;
case SceneEvent::kSetLan: {
- if (current_event.lan != 0) {
- debug(0, "lan[%u] = %02x", current_event.lan - 1, current_event.color);
- byte *ptr = getLans(current_event.scene == 0 ? _id : current_event.scene);
- ptr[current_event.lan - 1] = current_event.color;
+ if (currentEvent.lan != 0) {
+ debugC(0, kDebugScene, "lan[%u] = %02x", currentEvent.lan - 1, currentEvent.color);
+ byte *ptr = getLans(currentEvent.scene == 0 ? _id : currentEvent.scene);
+ ptr[currentEvent.lan - 1] = currentEvent.color;
}
loadLans();
- current_event.clear();
+ currentEvent.clear();
}
break;
case SceneEvent::kLoadScene: {
- if (current_event.scene != 0) {
- init(current_event.scene, current_event.dst);
- if (current_event.orientation != 0)
- orientation = current_event.orientation;
+ if (currentEvent.scene != 0) {
+ init(currentEvent.scene, currentEvent.dst);
+ if (currentEvent.orientation != 0)
+ orientation = currentEvent.orientation;
} else {
- //special case, empty scene
+ // special case, empty scene
background.free();
on.free();
delete[] ons;
ons = NULL;
for (byte i = 0; i < 4; ++i) {
animation[i].free();
- custom_animation[i].free();
+ customAnimation[i].free();
}
}
- current_event.clear();
+ currentEvent.clear();
}
break;
case SceneEvent::kWalk: {
- Common::Point dst = current_event.dst;
- if ((current_event.color & 2) != 0) { //relative move
+ Common::Point dst = currentEvent.dst;
+ if ((currentEvent.color & 2) != 0) { // relative move
dst.x += position.x;
dst.y += position.y;
}
- if ((current_event.color & 1) != 0) {
- warp(dst, current_event.orientation);
- current_event.clear();
+ if ((currentEvent.color & 1) != 0) {
+ warp(dst, currentEvent.orientation);
+ currentEvent.clear();
} else
- moveTo(dst, current_event.orientation);
+ moveTo(dst, currentEvent.orientation);
}
break;
case SceneEvent::kCreditsMessage:
case SceneEvent::kMessage: {
- message = current_event.message;
- message_animation = NULL;
- if (current_event.first_frame) {
- message_timer = 0;
- message_first_frame = current_event.first_frame;
- message_last_frame = current_event.last_frame;
- if (current_event.slot > 0) {
- message_animation = custom_animation + (current_event.slot - 1);
- //else if (!animation[current_event.slot].empty())
- // message_animation = animation + current_event.slot;
+ message = currentEvent.message;
+ messageAnimation = NULL;
+ if (currentEvent.firstFrame) {
+ messageTimer = 0;
+ messageFirstFrame = currentEvent.firstFrame;
+ messageLastFrame = currentEvent.lastFrame;
+ if (currentEvent.slot > 0) {
+ messageAnimation = customAnimation + (currentEvent.slot - 1);
+ //else if (!animation[currentEvent.slot].empty())
+ // messageAnimation = animation + currentEvent.slot;
} else
- message_animation = &actor_animation;
- debug(0, "async message %d-%d (slot %u)", message_first_frame, message_last_frame, current_event.slot);
+ messageAnimation = &actorAnimation;
+ debugC(0, kDebugScene, "async message %d-%d (slot %u)", messageFirstFrame, messageLastFrame, currentEvent.slot);
} else {
- message_timer = current_event.timer ? current_event.timer * 110 : messageDuration(message);
- message_first_frame = message_last_frame = 0;
+ messageTimer = currentEvent.timer ? currentEvent.timer * 110 : messageDuration(message);
+ messageFirstFrame = messageLastFrame = 0;
}
Common::Point p;
- if (current_event.dst.x == 0 && current_event.dst.y == 0) {
- p = Common::Point((actor_animation_position.left + actor_animation_position.right) / 2,
- actor_animation_position.top);
+ if (currentEvent.dst.x == 0 && currentEvent.dst.y == 0) {
+ p = Common::Point((actorAnimationPosition.left + actorAnimationPosition.right) / 2,
+ actorAnimationPosition.top);
} else {
- p = current_event.dst;
+ p = currentEvent.dst;
}
- byte message_slot = current_event.slot;
- if (message_slot != 0) {
- --message_slot;
- assert(message_slot < 4);
- const Surface *s = custom_animation[message_slot].currentFrame(0);
+ byte messageSlot = currentEvent.slot;
+ if (messageSlot != 0) {
+ --messageSlot;
+ assert(messageSlot < 4);
+ const Surface *s = customAnimation[messageSlot].currentFrame(0);
if (s == NULL)
- s = animation[message_slot].currentFrame(0);
+ s = animation[messageSlot].currentFrame(0);
if (s != NULL) {
p.x = s->x + s->w / 2;
p.y = s->y;
} else
- warning("no animation in slot %u", message_slot);
+ warning("no animation in slot %u", messageSlot);
}
- message_pos = messagePosition(message, p);
- message_color = current_event.color;
+ messagePos = messagePosition(message, p);
+ messageColor = currentEvent.color;
- if (message_first_frame)
- current_event.clear(); //async message, clearing event
+ if (messageFirstFrame)
+ currentEvent.clear(); // async message, clearing event
}
break;
case SceneEvent::kPlayAnimation: {
- byte slot = current_event.slot & 7; //0 - mark's
- if (current_event.animation != 0) {
- debug(0, "playing animation %u in slot %u(%02x)", current_event.animation, slot, current_event.slot);
+ byte slot = currentEvent.slot & 7; // 0 - mark's
+ if (currentEvent.animation != 0) {
+ debugC(0, kDebugScene, "playing animation %u in slot %u(%02x)", currentEvent.animation, slot, currentEvent.slot);
if (slot != 0) {
--slot;
assert(slot < 4);
- playAnimation(slot, current_event.animation, (current_event.slot & 0x80) != 0, (current_event.slot & 0x40) != 0, (current_event.slot & 0x20) != 0);
+ playAnimation(slot, currentEvent.animation, (currentEvent.slot & 0x80) != 0, (currentEvent.slot & 0x40) != 0, (currentEvent.slot & 0x20) != 0);
} else
- actor_talking = true;
+ actorTalking = true;
} else {
if (slot != 0) {
--slot;
- debug(0, "cancelling animation in slot %u", slot);
+ debugC(0, kDebugScene, "cancelling animation in slot %u", slot);
assert(slot < 4);
- custom_animation[slot].free();
+ customAnimation[slot].free();
} else
- actor_talking = true;
+ actorTalking = true;
}
- current_event.clear();
+ currentEvent.clear();
}
break;
case SceneEvent::kPauseAnimation: {
- byte slot = current_event.slot & 7; //0 - mark's
+ byte slot = currentEvent.slot & 7; // 0 - mark's
if (slot != 0) {
--slot;
- debug(1, "pause animation in slot %u", slot);
- custom_animation[slot].paused = (current_event.slot & 0x80) != 0;
+ debugC(1, kDebugScene, "pause animation in slot %u", slot);
+ customAnimation[slot].paused = (currentEvent.slot & 0x80) != 0;
} else {
- actor_talking = false;
+ actorTalking = false;
}
- current_event.clear();
+ currentEvent.clear();
}
break;
case SceneEvent::kClearAnimations:
for (byte i = 0; i < 4; ++i)
- custom_animation[i].free();
- actor_talking = false;
- current_event.clear();
+ customAnimation[i].free();
+ actorTalking = false;
+ currentEvent.clear();
break;
case SceneEvent::kPlayActorAnimation:
- debug(0, "playing actor animation %u", current_event.animation);
- playActorAnimation(current_event.animation, (current_event.slot & 0x80) != 0, (current_event.slot & 0x20) != 0);
- current_event.clear();
+ debugC(0, kDebugScene, "playing actor animation %u", currentEvent.animation);
+ playActorAnimation(currentEvent.animation, (currentEvent.slot & 0x80) != 0, (currentEvent.slot & 0x20) != 0);
+ currentEvent.clear();
break;
case SceneEvent::kPlayMusic:
- debug(0, "setting music %u", current_event.music);
- _engine->setMusic(current_event.music);
- Resources::instance()->dseg.set_byte(0xDB90, current_event.music);
- current_event.clear();
+ debugC(0, kDebugScene, "setting music %u", currentEvent.music);
+ _vm->setMusic(currentEvent.music);
+ _vm->res->dseg.set_byte(dsAddr_currentMusic, currentEvent.music);
+ currentEvent.clear();
break;
case SceneEvent::kPlaySound:
- debug(0, "playing sound %u, delay: %u", current_event.sound, current_event.color);
- sounds.push_back(Sound(current_event.sound, current_event.color));
- current_event.clear();
+ debugC(0, kDebugScene, "playing sound %u, delay: %u", currentEvent.sound, currentEvent.color);
+ sounds.push_back(Sound(currentEvent.sound, currentEvent.color));
+ currentEvent.clear();
break;
case SceneEvent::kEnableObject: {
- debug(0, "%s object #%u", current_event.color ? "enabling" : "disabling", current_event.object - 1);
- Object *obj = getObject(current_event.object - 1, current_event.scene == 0 ? _id : current_event.scene);
- obj->enabled = current_event.color;
+ debugC(0, kDebugScene, "%s object #%u", currentEvent.color ? "enabling" : "disabling", currentEvent.object - 1);
+ Object *obj = getObject(currentEvent.object - 1, currentEvent.scene == 0 ? _id : currentEvent.scene);
+ obj->enabled = currentEvent.color;
obj->save();
- current_event.clear();
+ currentEvent.clear();
}
break;
case SceneEvent::kHideActor:
- hide_actor = current_event.color != 0;
- current_event.clear();
+ hideActor = currentEvent.color != 0;
+ currentEvent.clear();
break;
case SceneEvent::kWaitForAnimation:
- debug(0, "waiting for the animation");
+ debugC(0, kDebugScene, "waiting for the animation");
break;
case SceneEvent::kWaitLanAnimationFrame:
- debug(0, "waiting for the frame %d in slot %d", current_event.animation, current_event.slot);
+ debugC(0, kDebugScene, "waiting for the frame %d in slot %d", currentEvent.animation, currentEvent.slot);
break;
case SceneEvent::kTimer:
- callback = current_event.callback;
- callback_timer = current_event.timer;
- debug(0, "triggering callback %04x in %u frames", callback, callback_timer);
- current_event.clear();
+ callback = currentEvent.callback;
+ callbackTimer = currentEvent.timer;
+ debugC(0, kDebugScene, "triggering callback %04x in %u frames", callback, callbackTimer);
+ currentEvent.clear();
break;
case SceneEvent::kEffect:
- _system->delayMillis(80); //2 vsyncs
- _system->setShakePos(8);
- _system->updateScreen();
+ _vm->_system->delayMillis(80); // 2 vsyncs
+ _vm->_system->setShakePos(8);
+ _vm->_system->updateScreen();
- _system->delayMillis(80); //2 vsyncs
- _system->setShakePos(0);
- _system->updateScreen();
+ _vm->_system->delayMillis(80); // 2 vsyncs
+ _vm->_system->setShakePos(0);
+ _vm->_system->updateScreen();
- _system->delayMillis(80); //2 vsyncs
- _system->setShakePos(4);
- _system->updateScreen();
+ _vm->_system->delayMillis(80); // 2 vsyncs
+ _vm->_system->setShakePos(4);
+ _vm->_system->updateScreen();
- _system->delayMillis(80); //2 vsyncs
- _system->setShakePos(0);
- _system->updateScreen();
+ _vm->_system->delayMillis(80); // 2 vsyncs
+ _vm->_system->setShakePos(0);
+ _vm->_system->updateScreen();
- current_event.clear();
+ currentEvent.clear();
break;
case SceneEvent::kFade:
- _fade_timer = current_event.orientation != 0 ? 5 : -5;
- current_event.clear();
+ _fadeTimer = currentEvent.orientation != 0 ? 5 : -5;
+ currentEvent.clear();
break;
case SceneEvent::kWait:
- debug(0, "wait %u", current_event.timer);
+ debugC(0, kDebugScene, "wait %u", currentEvent.timer);
break;
case SceneEvent::kCredits:
- debug(0, "showing credits");
+ debugC(0, kDebugScene, "showing credits");
break;
case SceneEvent::kQuit:
- debug(0, "quit!");
- _engine->quitGame();
+ debugC(0, kDebugScene, "quit!");
+ _vm->quitGame();
break;
case SceneEvent::kSetFlag:
- debug(0, "async set_flag(%04x, %d)", current_event.callback, current_event.color);
- Resources::instance()->dseg.set_byte(current_event.callback, current_event.color);
- current_event.clear();
+ debugC(0, kDebugScene, "async set_flag(%04x, %d)", currentEvent.callback, currentEvent.color);
+ _vm->res->dseg.set_byte(currentEvent.callback, currentEvent.color);
+ currentEvent.clear();
break;
default:
- error("empty/unhandler event[%d]", (int)current_event.type);
+ error("empty/unhandler event[%d]", (int)currentEvent.type);
}
}
+
if (events.empty()) {
- message_color = 0xd1;
- hide_actor = false;
+ messageColor = textColorMark;
+ hideActor = false;
}
- return !current_event.empty();
+
+ return !currentEvent.empty();
}
void Scene::setPalette(unsigned mul) {
- //debug(0, "setPalette(%u)", mul);
+ debugC(0, kDebugScene, "setPalette(%u)", mul);
byte p[3 * 256];
for (int i = 0; i < 3 * 256; ++i) {
p[i] = (unsigned)palette[i] * mul;
}
- _system->getPaletteManager()->setPalette(p, 0, 256);
+ _vm->_system->getPaletteManager()->setPalette(p, 0, 256);
}
-Object *Scene::getObject(int id, int scene_id) {
+Object *Scene::getObject(int id, int sceneId) {
assert(id > 0);
- if (scene_id == 0)
- scene_id = _id;
+ if (sceneId == 0)
+ sceneId = _id;
- if (scene_id == 0)
+ if (sceneId == 0)
return NULL;
- Common::Array<Object> &scene_objects = objects[scene_id - 1];
+ Common::Array<Object> &sceneObjects = objects[sceneId - 1];
--id;
- if (id >= (int)scene_objects.size())
+ if (id >= (int)sceneObjects.size())
return NULL;
- return &scene_objects[id];
+ return &sceneObjects[id];
}
-Common::Point Scene::messagePosition(const Common::String &str, Common::Point message_position) {
- Resources *res = Resources::instance();
+Common::Point Scene::messagePosition(const Common::String &str, Common::Point pos) {
int lines = 1;
for (uint i = 0; i < str.size(); ++i)
if (str[i] == '\n')
++lines;
- uint w = res->font7.render(NULL, 0, 0, str, 0);
- uint h = res->font7.height * lines + 3;
+ uint w = _vm->res->font7.render(NULL, 0, 0, str, 0);
+ uint h = _vm->res->font7.getHeight() * lines + 3;
- message_position.x -= w / 2;
- message_position.y -= h;
+ pos.x -= w / 2;
+ pos.y -= h;
- if (message_position.x + w > 320)
- message_position.x = 320 - w;
- if (message_position.x < 0)
- message_position.x = 0;
- if (message_position.y + h > 320)
- message_position.y = 200 - h;
- if (message_position.y < 0)
- message_position.y = 0;
+ if (pos.x + w > kScreenWidth)
+ pos.x = kScreenWidth - w;
+ if (pos.x < 0)
+ pos.x = 0;
+ if (pos.y + h > kScreenHeight)
+ pos.y = kScreenHeight - h;
+ if (pos.y < 0)
+ pos.y = 0;
- return message_position;
+ return pos;
}
uint Scene::messageDuration(const Common::String &str) {
- //original game uses static delays: 100-slow, 50, 20 and 1 tick - crazy speed.
- //total delay = total message length * delay / 8 + 60.
- uint total_width = str.size();
+ // original game uses static delays: 100-slow, 50, 20 and 1 tick - crazy speed.
+ // total delay = total message length * delay / 8 + 60.
+ uint totalWidth = str.size();
- int speed = Common::ConfigManager::instance().getInt("talkspeed");
+ int speed = ConfMan.getInt("talkspeed");
if (speed < 0)
speed = 60;
- uint delay_delta = 1 + (255 - speed) * 99 / 255;
+ uint delayDelta = 1 + (255 - speed) * 99 / 255;
- uint delay = 60 + (total_width * delay_delta) / 8;
- //debug(0, "delay = %u, delta: %u", delay, delay_delta);
+ uint delay = 60 + (totalWidth * delayDelta) / 8;
+ debugC(0, kDebugScene, "delay = %u, delta: %u", delay, delayDelta);
return delay * 10;
}
void Scene::displayMessage(const Common::String &str, byte color, const Common::Point &pos) {
//assert(!str.empty());
- //debug(0, "displayMessage: %s", str.c_str());
+ debugC(0, kDebugScene, "displayMessage: %s", str.c_str());
message = str;
- message_pos = (pos.x | pos.y) ? pos : messagePosition(str, position);
- message_color = color;
- message_timer = messageDuration(message);
+ messagePos = (pos.x | pos.y) ? pos : messagePosition(str, position);
+ messageColor = color;
+ messageTimer = messageDuration(message);
}
void Scene::clear() {
clearMessage();
events.clear();
- current_event.clear();
+ currentEvent.clear();
for (int i = 0; i < 4; ++i) {
animation[i].free();
- custom_animation[i].free();
+ customAnimation[i].free();
}
callback = 0;
- callback_timer = 0;
+ callbackTimer = 0;
}
void Scene::clearMessage() {
message.clear();
- message_timer = 0;
- message_color = 0xd1;
- message_first_frame = 0;
- message_last_frame = 0;
- message_animation = NULL;
+ messageTimer = 0;
+ messageColor = textColorMark;
+ messageFirstFrame = 0;
+ messageLastFrame = 0;
+ messageAnimation = NULL;
}
} // End of namespace TeenAgent
diff --git a/engines/teenagent/scene.h b/engines/teenagent/scene.h
index 32e784bb60..14aefa0cca 100644
--- a/engines/teenagent/scene.h
+++ b/engines/teenagent/scene.h
@@ -27,8 +27,8 @@
#include "teenagent/objects.h"
#include "teenagent/surface.h"
#include "teenagent/surface_list.h"
+#include "teenagent/teenagent.h"
-#include "common/system.h"
#include "common/array.h"
#include "common/list.h"
@@ -39,7 +39,6 @@ struct Event;
namespace TeenAgent {
class TeenAgentEngine;
-class Dialog;
struct SceneEvent {
enum Type {
@@ -84,22 +83,22 @@ struct SceneEvent {
byte lan;
union {
byte music;
- byte first_frame;
+ byte firstFrame;
};
union {
byte sound;
- byte last_frame;
+ byte lastFrame;
};
byte object;
SceneEvent(Type type_) :
- type(type_), message(), color(0xd1), slot(0), animation(0), timer(0), orientation(0), dst(),
+ type(type_), message(), color(textColorMark), slot(0), animation(0), timer(0), orientation(0), dst(),
scene(0), ons(0), lan(0), music(0), sound(0), object(0) {}
void clear() {
type = kNone;
message.clear();
- color = 0xd1;
+ color = textColorMark;
slot = 0;
orientation = 0;
animation = 0;
@@ -118,7 +117,7 @@ struct SceneEvent {
}
void dump() const {
- debug(0, "event[%d]: \"%s\"[%02x], slot: %d, animation: %u, timer: %u, dst: (%d, %d) [%u], scene: %u, ons: %u, lan: %u, object: %u, music: %u, sound: %u",
+ debugC(0, kDebugScene, "event[%d]: \"%s\"[%02x], slot: %d, animation: %u, timer: %u, dst: (%d, %d) [%u], scene: %u, ons: %u, lan: %u, object: %u, music: %u, sound: %u",
(int)type, message.c_str(), color, slot, animation, timer, dst.x, dst.y, orientation, scene, ons, lan, object, music, sound
);
}
@@ -126,13 +125,13 @@ struct SceneEvent {
class Scene {
public:
- Scene(TeenAgentEngine *engine, OSystem *system);
+ Scene(TeenAgentEngine *engine);
~Scene();
bool intro;
void init(int id, const Common::Point &pos);
- bool render(bool tick_game, bool tick_mark, uint32 message_delta);
+ bool render(bool tickGame, bool tickMark, uint32 messageDelta);
int getId() const { return _id; }
void warp(const Common::Point &point, byte orientation = 0);
@@ -140,7 +139,7 @@ public:
void moveTo(const Common::Point &point, byte orientation = 0, bool validate = false);
Common::Point getPosition() const { return position; }
- void displayMessage(const Common::String &str, byte color = 0xd1, const Common::Point &pos = Common::Point());
+ void displayMessage(const Common::String &str, byte color = textColorMark, const Common::Point &pos = Common::Point());
void setOrientation(uint8 o) { orientation = o; }
void push(const SceneEvent &event);
byte peekFlagEvent(uint16 addr) const;
@@ -153,15 +152,15 @@ public:
byte *getOns(int id);
byte *getLans(int id);
- bool eventRunning() const { return !current_event.empty(); }
+ bool eventRunning() const { return !currentEvent.empty(); }
Walkbox *getWalkbox(byte id) { return &walkboxes[_id - 1][id]; }
- Object *getObject(int id, int scene_id = 0);
+ Object *getObject(int id, int sceneId = 0);
Object *findObject(const Common::Point &point);
void loadObjectData();
Animation *getAnimation(byte slot);
- inline Animation *getActorAnimation() { return &actor_animation; }
+ inline Animation *getActorAnimation() { return &actorAnimation; }
inline const Common::String &getMessage() const { return message; }
void setPalette(unsigned mul);
int lookupZoom(uint y) const;
@@ -173,39 +172,38 @@ private:
void playAnimation(byte idx, uint id, bool loop, bool paused, bool ignore);
void playActorAnimation(uint id, bool loop, bool ignore);
- byte palette[768];
+ byte palette[3 * 256];
void paletteEffect(byte step);
byte findFade() const;
- static Common::Point messagePosition(const Common::String &str, Common::Point position);
- static uint messageDuration(const Common::String &str);
+ Common::Point messagePosition(const Common::String &str, Common::Point pos);
+ uint messageDuration(const Common::String &str);
bool processEventQueue();
inline bool nextEvent() {
- current_event.clear();
+ currentEvent.clear();
return processEventQueue();
}
void clearMessage();
- TeenAgentEngine *_engine;
- OSystem *_system;
+ TeenAgentEngine *_vm;
int _id;
Graphics::Surface background;
SurfaceList on;
- bool on_enabled;
+ bool onEnabled;
Surface *ons;
- uint32 ons_count;
- Animation actor_animation, animation[4], custom_animation[4];
- Common::Rect actor_animation_position, animation_position[4];
+ uint32 onsCount;
+ Animation actorAnimation, animation[4], customAnimation[4];
+ Common::Rect actorAnimationPosition, animationPosition[4];
- Actor teenagent, teenagent_idle;
+ Actor teenagent, teenagentIdle;
Common::Point position;
typedef Common::List<Common::Point> Path;
Path path;
uint8 orientation;
- bool actor_talking;
+ bool actorTalking;
bool findPath(Path &p, const Common::Point &src, const Common::Point &dst) const;
@@ -214,22 +212,24 @@ private:
Common::Array<Common::Array<FadeType> > fades;
Common::String message;
- Common::Point message_pos;
- byte message_color;
- uint message_timer;
- byte message_first_frame;
- byte message_last_frame;
- Animation *message_animation;
+ Common::Point messagePos;
+ byte messageColor;
+ uint messageTimer;
+ byte messageFirstFrame;
+ byte messageLastFrame;
+ Animation *messageAnimation;
typedef Common::List<SceneEvent> EventList;
EventList events;
- SceneEvent current_event;
- bool hide_actor;
+ SceneEvent currentEvent;
+ bool hideActor;
- uint16 callback, callback_timer;
+ uint16 callback, callbackTimer;
- int _fade_timer;
- uint _idle_timer;
+ int _fadeTimer;
+ byte _fadeOld;
+
+ uint _idleTimer;
struct Sound {
byte id, delay;
@@ -254,7 +254,7 @@ private:
feature[i] = true;
}
}
- } debug_features;
+ } debugFeatures;
};
} // End of namespace TeenAgent
diff --git a/engines/teenagent/segment.h b/engines/teenagent/segment.h
index 303198b071..286337d120 100644
--- a/engines/teenagent/segment.h
+++ b/engines/teenagent/segment.h
@@ -41,26 +41,21 @@ public:
assert(offset < _size);
return _data[offset];
}
+
inline uint16 get_word(uint32 offset) const {
assert(offset + 1 < _size);
return READ_LE_UINT16(_data + offset);
}
- inline uint32 get_quad(uint32 offset) const {
- assert(offset + 3 < _size);
- return READ_LE_UINT32(_data + offset);
- }
+
inline void set_byte(uint32 offset, byte v) const {
assert(offset < _size);
_data[offset] = v;
}
+
inline void set_word(uint32 offset, uint16 v) const {
assert(offset + 1 < _size);
return WRITE_LE_UINT16(_data + offset, v);
}
- inline void set_quad(uint32 offset, uint32 v) const {
- assert(offset + 3 < _size);
- return WRITE_LE_UINT32(_data + offset, v);
- }
const byte *ptr(uint32 addr) const {
assert(addr < _size);
@@ -71,6 +66,7 @@ public:
assert(addr < _size);
return _data + addr;
}
+
uint size() const { return _size; }
};
diff --git a/engines/teenagent/surface.cpp b/engines/teenagent/surface.cpp
index 63312990ee..4db25bc749 100644
--- a/engines/teenagent/surface.cpp
+++ b/engines/teenagent/surface.cpp
@@ -21,6 +21,8 @@
#include "teenagent/surface.h"
#include "teenagent/pack.h"
+#include "teenagent/teenagent.h"
+
#include "common/stream.h"
#include "common/debug.h"
@@ -34,7 +36,7 @@ Surface::~Surface() {
}
void Surface::load(Common::SeekableReadStream &stream, Type type) {
- //debug(0, "load()");
+ debugC(0, kDebugSurface, "load()");
free();
x = y = 0;
@@ -44,71 +46,71 @@ void Surface::load(Common::SeekableReadStream &stream, Type type) {
if (type != kTypeLan) {
uint16 pos = stream.readUint16LE();
- x = pos % 320;
- y = pos / 320;
+ x = pos % kScreenWidth;
+ y = pos / kScreenWidth;
}
- //debug(0, "declared info: %ux%u (%04xx%04x) -> %u,%u", w_, h_, w_, h_, x, y);
+ debugC(0, kDebugSurface, "declared info: %ux%u (%04xx%04x) -> %u,%u", w_, h_, w_, h_, x, y);
if (stream.eos() || w_ == 0)
return;
if (w_ * h_ > stream.size()) {
- debug(0, "invalid surface %ux%u -> %u,%u", w_, h_, x, y);
+ debugC(0, kDebugSurface, "invalid surface %ux%u -> %u,%u", w_, h_, x, y);
return;
}
- //debug(0, "creating surface %ux%u -> %u,%u", w_, h_, x, y);
+ debugC(0, kDebugSurface, "creating surface %ux%u -> %u,%u", w_, h_, x, y);
create(w_, h_, Graphics::PixelFormat::createFormatCLUT8());
stream.read(pixels, w_ * h_);
}
-Common::Rect Surface::render(Graphics::Surface *surface, int dx, int dy, bool mirror, Common::Rect src_rect, uint zoom) const {
- if (src_rect.isEmpty()) {
- src_rect = Common::Rect(0, 0, w, h);
+Common::Rect Surface::render(Graphics::Surface *surface, int dx, int dy, bool mirror, Common::Rect srcRect, uint zoom) const {
+ if (srcRect.isEmpty()) {
+ srcRect = Common::Rect(0, 0, w, h);
}
- Common::Rect dst_rect(x + dx, y + dy, x + dx + zoom * src_rect.width() / 256, y + dy + zoom * src_rect.height() / 256);
- if (dst_rect.left < 0) {
- src_rect.left = -dst_rect.left;
- dst_rect.left = 0;
+ Common::Rect dstRect(x + dx, y + dy, x + dx + zoom * srcRect.width() / 256, y + dy + zoom * srcRect.height() / 256);
+ if (dstRect.left < 0) {
+ srcRect.left = -dstRect.left;
+ dstRect.left = 0;
}
- if (dst_rect.right > surface->w) {
- src_rect.right -= dst_rect.right - surface->w;
- dst_rect.right = surface->w;
+ if (dstRect.right > surface->w) {
+ srcRect.right -= dstRect.right - surface->w;
+ dstRect.right = surface->w;
}
- if (dst_rect.top < 0) {
- src_rect.top -= dst_rect.top;
- dst_rect.top = 0;
+ if (dstRect.top < 0) {
+ srcRect.top -= dstRect.top;
+ dstRect.top = 0;
}
- if (dst_rect.bottom > surface->h) {
- src_rect.bottom -= dst_rect.bottom - surface->h;
- dst_rect.bottom = surface->h;
+ if (dstRect.bottom > surface->h) {
+ srcRect.bottom -= dstRect.bottom - surface->h;
+ dstRect.bottom = surface->h;
}
- if (src_rect.isEmpty() || dst_rect.isEmpty())
+ if (srcRect.isEmpty() || dstRect.isEmpty())
return Common::Rect();
if (zoom == 256) {
- const byte *src = (const byte *)getBasePtr(0, src_rect.top);
- byte *dst_base = (byte *)surface->getBasePtr(dst_rect.left, dst_rect.top);
+ const byte *src = (const byte *)getBasePtr(0, srcRect.top);
+ byte *dstBase = (byte *)surface->getBasePtr(dstRect.left, dstRect.top);
- for (int i = src_rect.top; i < src_rect.bottom; ++i) {
- byte *dst = dst_base;
- for (int j = src_rect.left; j < src_rect.right; ++j) {
+ for (int i = srcRect.top; i < srcRect.bottom; ++i) {
+ byte *dst = dstBase;
+ for (int j = srcRect.left; j < srcRect.right; ++j) {
byte p = src[(mirror ? w - j - 1 : j)];
if (p != 0xff)
*dst++ = p;
else
++dst;
}
- dst_base += surface->pitch;
+ dstBase += surface->pitch;
src += pitch;
}
} else {
- byte *dst = (byte *)surface->getBasePtr(dst_rect.left, dst_rect.top);
- for (int i = 0; i < dst_rect.height(); ++i) {
- for (int j = 0; j < dst_rect.width(); ++j) {
+ byte *dst = (byte *)surface->getBasePtr(dstRect.left, dstRect.top);
+ for (int i = 0; i < dstRect.height(); ++i) {
+ for (int j = 0; j < dstRect.width(); ++j) {
int px = j * 256 / zoom;
- const byte *src = (const byte *)getBasePtr(src_rect.left + (mirror ? w - px - 1 : px), src_rect.top + i * 256 / zoom);
+ const byte *src = (const byte *)getBasePtr(srcRect.left + (mirror ? w - px - 1 : px), srcRect.top + i * 256 / zoom);
byte p = *src;
if (p != 0xff)
dst[j] = p;
@@ -116,7 +118,7 @@ Common::Rect Surface::render(Graphics::Surface *surface, int dx, int dy, bool mi
dst += surface->pitch;
}
}
- return dst_rect;
+ return dstRect;
}
} // End of namespace TeenAgent
diff --git a/engines/teenagent/surface.h b/engines/teenagent/surface.h
index 51368c6bee..3e591ed3e0 100644
--- a/engines/teenagent/surface.h
+++ b/engines/teenagent/surface.h
@@ -33,16 +33,17 @@ namespace TeenAgent {
class Surface : public Graphics::Surface {
public:
- enum Type {kTypeOns, kTypeLan};
-
- uint16 x, y;
-
Surface();
~Surface();
+
+ enum Type {kTypeOns, kTypeLan};
+
void load(Common::SeekableReadStream &, Type type);
- Common::Rect render(Graphics::Surface *surface, int dx = 0, int dy = 0, bool mirror = false, Common::Rect src_rect = Common::Rect(), uint zoom = 256) const;
+ Common::Rect render(Graphics::Surface *surface, int dx = 0, int dy = 0, bool mirror = false, Common::Rect srcRect = Common::Rect(), uint zoom = 256) const;
bool empty() const { return pixels == NULL; }
+
+ uint16 x, y;
};
} // End of namespace TeenAgent
diff --git a/engines/teenagent/surface_list.cpp b/engines/teenagent/surface_list.cpp
index 31387ac3cb..e293ce6470 100644
--- a/engines/teenagent/surface_list.cpp
+++ b/engines/teenagent/surface_list.cpp
@@ -19,34 +19,35 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#include "teenagent/surface.h"
#include "teenagent/surface_list.h"
-#include "objects.h"
+#include "teenagent/surface.h"
+#include "teenagent/objects.h"
+#include "teenagent/teenagent.h"
namespace TeenAgent {
-SurfaceList::SurfaceList() : surfaces(NULL), surfaces_n(0) {}
+SurfaceList::SurfaceList() : surfaces(NULL), surfacesCount(0) {}
SurfaceList::~SurfaceList() {
free();
}
-void SurfaceList::load(Common::SeekableReadStream &stream, Type type, int sub_hack) {
+void SurfaceList::load(Common::SeekableReadStream &stream, int subHack) {
free();
byte fn = stream.readByte();
if (stream.eos())
return;
- surfaces_n = fn - sub_hack;
- debug(0, "loading %u surfaces from list (skip %d)", surfaces_n, sub_hack);
+ surfacesCount = fn - subHack;
+ debugC(0, kDebugSurface, "loading %u surfaces from list (skip %d)", surfacesCount, subHack);
- if (surfaces_n == 0)
+ if (surfacesCount == 0)
return;
- surfaces = new Surface[surfaces_n];
+ surfaces = new Surface[surfacesCount];
- for (byte i = 0; i < surfaces_n; ++i) {
+ for (byte i = 0; i < surfacesCount; ++i) {
uint offset = stream.readUint16LE();
uint pos = stream.pos();
stream.seek(offset);
@@ -58,11 +59,11 @@ void SurfaceList::load(Common::SeekableReadStream &stream, Type type, int sub_ha
void SurfaceList::free() {
delete[] surfaces;
surfaces = NULL;
- surfaces_n = 0;
+ surfacesCount = 0;
}
void SurfaceList::render(Graphics::Surface *surface, const Common::Rect &clip) const {
- for (uint i = 0; i < surfaces_n; ++i) {
+ for (uint i = 0; i < surfacesCount; ++i) {
const Surface &s = surfaces[i];
Common::Rect r(s.x, s.y, s.x + s.w, s.y + s.h);
if (r.bottom < clip.bottom || !clip.intersects(r))
diff --git a/engines/teenagent/surface_list.h b/engines/teenagent/surface_list.h
index 2d7be0d52b..73a41fb5f8 100644
--- a/engines/teenagent/surface_list.h
+++ b/engines/teenagent/surface_list.h
@@ -23,23 +23,23 @@
#define TEENAGENT_SURFACE_LIST_H__
#include "common/stream.h"
+#include "graphics/surface.h"
namespace TeenAgent {
class Surface;
class SurfaceList {
public:
- enum Type { kTypeOn };
-
SurfaceList();
~SurfaceList();
- void load(Common::SeekableReadStream &, Type type, int sub_hack = 0);
+
+ void load(Common::SeekableReadStream &, int subHack = 0);
void free();
void render(Graphics::Surface *surface, const Common::Rect &clip) const;
protected:
Surface *surfaces;
- uint surfaces_n;
+ uint surfacesCount;
};
}
diff --git a/engines/teenagent/teenagent.cpp b/engines/teenagent/teenagent.cpp
index 57c069fe59..0b48a18b26 100644
--- a/engines/teenagent/teenagent.cpp
+++ b/engines/teenagent/teenagent.cpp
@@ -21,6 +21,7 @@
#include "common/config-manager.h"
#include "common/debug.h"
+#include "common/debug-channels.h"
#include "common/events.h"
#include "common/savefile.h"
#include "common/system.h"
@@ -39,26 +40,56 @@
#include "graphics/thumbnail.h"
#include "teenagent/console.h"
+#include "teenagent/dialog.h"
+#include "teenagent/inventory.h"
#include "teenagent/music.h"
#include "teenagent/objects.h"
#include "teenagent/pack.h"
+#include "teenagent/resources.h"
#include "teenagent/scene.h"
#include "teenagent/teenagent.h"
namespace TeenAgent {
TeenAgentEngine::TeenAgentEngine(OSystem *system, const ADGameDescription *gd)
- : Engine(system), action(kActionNone), _gameDescription(gd),
- _rnd("teenagent") {
- music = new MusicPlayer();
+ : Engine(system), _action(kActionNone), _gameDescription(gd), _rnd("teenagent") {
+ DebugMan.addDebugChannel(kDebugActor, "Actor", "Enable Actor Debug");
+ DebugMan.addDebugChannel(kDebugAnimation, "Animation", "Enable Animation Debug");
+ DebugMan.addDebugChannel(kDebugCallbacks, "Callbacks", "Enable Callbacks Debug");
+ DebugMan.addDebugChannel(kDebugDialog, "Dialog", "Enable Dialog Debug");
+ DebugMan.addDebugChannel(kDebugFont, "Font", "Enable Font Debug");
+ DebugMan.addDebugChannel(kDebugInventory, "Inventory", "Enable Inventory Debug");
+ DebugMan.addDebugChannel(kDebugMusic, "Music", "Enable Music Debug");
+ DebugMan.addDebugChannel(kDebugObject, "Object", "Enable Object Debug");
+ DebugMan.addDebugChannel(kDebugPack, "Pack", "Enable Pack Debug");
+ DebugMan.addDebugChannel(kDebugScene, "Scene", "Enable Scene Debug");
+ DebugMan.addDebugChannel(kDebugSurface, "Surface", "Enable Surface Debug");
+
+ music = new MusicPlayer(this);
+ dialog = new Dialog(this);
+ res = new Resources();
console = 0;
}
TeenAgentEngine::~TeenAgentEngine() {
+ delete dialog;
+ dialog = 0;
+ delete scene;
+ scene = 0;
+ delete inventory;
+ inventory = 0;
delete music;
+ music = 0;
+ _mixer->stopAll();
+ _useHotspots.clear();
+ delete res;
+ res = 0;
+
+ CursorMan.popCursor();
delete console;
+ DebugMan.clearAllDebugChannels();
}
bool TeenAgentEngine::trySelectedObject() {
@@ -66,66 +97,64 @@ bool TeenAgentEngine::trySelectedObject() {
if (inv == NULL)
return false;
- Resources *res = Resources::instance();
- debug(0, "checking active object %u on %u", inv->id, dst_object->id);
+ debugC(0, kDebugObject, "checking active object %u on %u", inv->id, _dstObject->id);
//mouse time challenge hack:
- if ((res->dseg.get_byte(0) == 1 && inv->id == 49 && dst_object->id == 5) ||
- (res->dseg.get_byte(0) == 2 && inv->id == 29 && dst_object->id == 5)) {
+ if ((res->dseg.get_byte(dsAddr_timedCallbackState) == 1 && inv->id == kInvItemRock && _dstObject->id == 5) ||
+ (res->dseg.get_byte(dsAddr_timedCallbackState) == 2 && inv->id == kInvItemSuperGlue && _dstObject->id == 5)) {
//putting rock into hole or superglue on rock
- processCallback(0x8d57);
+ fnPutRockInHole();
return true;
}
- const Common::Array<UseHotspot> &hotspots = use_hotspots[scene->getId() - 1];
+ const Common::Array<UseHotspot> &hotspots = _useHotspots[scene->getId() - 1];
for (uint i = 0; i < hotspots.size(); ++i) {
const UseHotspot &spot = hotspots[i];
- if (spot.inventory_id == inv->id && dst_object->id == spot.object_id) {
- debug(0, "use object on hotspot!");
+ if (spot.inventoryId == inv->id && _dstObject->id == spot.objectId) {
+ debugC(0, kDebugObject, "use object on hotspot!");
spot.dump();
- if (spot.actor_x != 0xffff && spot.actor_y != 0xffff)
- moveTo(spot.actor_x, spot.actor_y, spot.orientation);
+ if (spot.actorX != 0xffff && spot.actorY != 0xffff)
+ moveTo(spot.actorX, spot.actorY, spot.orientation);
if (!processCallback(spot.callback))
- debug(0, "fixme! display proper description");
+ debugC(0, kDebugObject, "FIXME: display proper description");
inventory->resetSelectedObject();
return true;
}
}
- //error
+ // error
inventory->resetSelectedObject();
- displayMessage(0x3457);
+ displayMessage(dsAddr_objErrorMsg); // "That's no good"
return true;
}
void TeenAgentEngine::processObject() {
- if (dst_object == NULL)
+ if (_dstObject == NULL)
return;
- Resources *res = Resources::instance();
- switch (action) {
+ switch (_action) {
case kActionExamine: {
if (trySelectedObject())
break;
- byte *dcall = res->dseg.ptr(0xb5ce);
+ byte *dcall = res->dseg.ptr(dsAddr_objExamineCallbackTablePtr);
dcall = res->dseg.ptr(READ_LE_UINT16(dcall + scene->getId() * 2 - 2));
- dcall += 2 * dst_object->id - 2;
+ dcall += 2 * _dstObject->id - 2;
uint16 callback = READ_LE_UINT16(dcall);
if (callback == 0 || !processCallback(callback))
- displayMessage(dst_object->description);
+ displayMessage(_dstObject->description);
}
break;
case kActionUse: {
if (trySelectedObject())
break;
- byte *dcall = res->dseg.ptr(0xb89c);
+ byte *dcall = res->dseg.ptr(dsAddr_objUseCallbackTablePtr);
dcall = res->dseg.ptr(READ_LE_UINT16(dcall + scene->getId() * 2 - 2));
- dcall += 2 * dst_object->id - 2;
+ dcall += 2 * _dstObject->id - 2;
uint16 callback = READ_LE_UINT16(dcall);
if (!processCallback(callback))
- displayMessage(dst_object->description);
+ displayMessage(_dstObject->description);
}
break;
@@ -134,20 +163,19 @@ void TeenAgentEngine::processObject() {
}
}
-
void TeenAgentEngine::use(Object *object) {
if (object == NULL || scene->eventRunning())
return;
- dst_object = object;
+ _dstObject = object;
object->rect.dump();
- object->actor_rect.dump();
+ object->actorRect.dump();
- action = kActionUse;
- if (object->actor_rect.valid())
- scene->moveTo(Common::Point(object->actor_rect.right, object->actor_rect.bottom), object->actor_orientation);
- else if (object->actor_orientation > 0)
- scene->setOrientation(object->actor_orientation);
+ _action = kActionUse;
+ if (object->actorRect.valid())
+ scene->moveTo(Common::Point(object->actorRect.right, object->actorRect.bottom), object->actorOrientation);
+ else if (object->actorOrientation > 0)
+ scene->setOrientation(object->actorOrientation);
}
void TeenAgentEngine::examine(const Common::Point &point, Object *object) {
@@ -155,53 +183,39 @@ void TeenAgentEngine::examine(const Common::Point &point, Object *object) {
return;
if (object != NULL) {
- Common::Point dst = object->actor_rect.center();
- debug(0, "click %d, %d, object %d, %d", point.x, point.y, dst.x, dst.y);
- action = kActionExamine;
- if (object->actor_rect.valid())
- scene->moveTo(dst, object->actor_orientation, true); //validate examine message. Original engine does not let you into walkboxes
- dst_object = object;
- } else if (!scene_busy) {
- //do not reset anything while scene is busy, but allow interrupts while walking.
- debug(0, "click %d, %d", point.x, point.y);
- action = kActionNone;
+ Common::Point dst = object->actorRect.center();
+ debugC(0, kDebugObject, "click %d, %d, object %d, %d", point.x, point.y, dst.x, dst.y);
+ _action = kActionExamine;
+ if (object->actorRect.valid())
+ scene->moveTo(dst, object->actorOrientation, true); // validate examine message. Original engine does not let you into walkboxes
+ _dstObject = object;
+ } else if (!_sceneBusy) {
+ // do not reset anything while scene is busy, but allow interrupts while walking.
+ debugC(0, kDebugObject, "click %d, %d", point.x, point.y);
+ _action = kActionNone;
scene->moveTo(point, 0, true);
- dst_object = NULL;
+ _dstObject = NULL;
}
}
void TeenAgentEngine::init() {
- _mark_delay = 80;
- _game_delay = 110;
+ _markDelay = 80;
+ _gameDelay = 110;
- Resources *res = Resources::instance();
- use_hotspots.resize(42);
- byte *scene_hotspots = res->dseg.ptr(0xbb87);
+ _useHotspots.resize(42);
+ byte *sceneHotspots = res->dseg.ptr(dsAddr_sceneHotspotsPtr);
for (byte i = 0; i < 42; ++i) {
- Common::Array<UseHotspot> & hotspots = use_hotspots[i];
- byte *hotspots_ptr = res->dseg.ptr(READ_LE_UINT16(scene_hotspots + i * 2));
- while (*hotspots_ptr) {
+ Common::Array<UseHotspot> & hotspots = _useHotspots[i];
+ byte *hotspotsPtr = res->dseg.ptr(READ_LE_UINT16(sceneHotspots + i * 2));
+ while (*hotspotsPtr) {
UseHotspot h;
- h.load(hotspots_ptr);
- hotspots_ptr += 9;
+ h.load(hotspotsPtr);
+ hotspotsPtr += 9;
hotspots.push_back(h);
}
}
}
-void TeenAgentEngine::deinit() {
- _mixer->stopAll();
- delete scene;
- scene = NULL;
- delete inventory;
- inventory = NULL;
- //delete music;
- //music = NULL;
- use_hotspots.clear();
- Resources::instance()->deinit();
- CursorMan.popCursor();
-}
-
Common::Error TeenAgentEngine::loadGameState(int slot) {
debug(0, "loading from slot %d", slot);
Common::ScopedPtr<Common::InSaveFile> in(_saveFileMan->openForLoading(Common::String::format("teenagent.%02d", slot)));
@@ -211,22 +225,19 @@ Common::Error TeenAgentEngine::loadGameState(int slot) {
if (!in)
return Common::kReadPermissionDenied;
- Resources *res = Resources::instance();
+ assert(res->dseg.size() >= dsAddr_saveState + saveStateSize);
- const uint dataSize = 0x777a;
- assert(res->dseg.size() >= 0x6478 + dataSize);
-
- char *data = (char *)malloc(dataSize);
+ char *data = (char *)malloc(saveStateSize);
if (!data)
error("[TeenAgentEngine::loadGameState] Cannot allocate buffer");
in->seek(0);
- if (in->read(data, dataSize) != dataSize) {
+ if (in->read(data, saveStateSize) != saveStateSize) {
free(data);
return Common::kReadingFailed;
}
- memcpy(res->dseg.ptr(0x6478), data, dataSize);
+ memcpy(res->dseg.ptr(dsAddr_saveState), data, saveStateSize);
free(data);
@@ -234,10 +245,10 @@ Common::Error TeenAgentEngine::loadGameState(int slot) {
inventory->activate(false);
inventory->reload();
- setMusic(Resources::instance()->dseg.get_byte(0xDB90));
+ setMusic(res->dseg.get_byte(dsAddr_currentMusic));
- int id = res->dseg.get_byte(0xB4F3);
- uint16 x = res->dseg.get_word(0x64AF), y = res->dseg.get_word(0x64B1);
+ int id = res->dseg.get_byte(dsAddr_currentScene);
+ uint16 x = res->dseg.get_word(dsAddr_egoX), y = res->dseg.get_word(dsAddr_egoY);
scene->loadObjectData();
scene->init(id, Common::Point(x, y));
scene->setPalette(4);
@@ -251,15 +262,15 @@ Common::Error TeenAgentEngine::saveGameState(int slot, const Common::String &des
if (!out)
return Common::kWritingFailed;
- Resources *res = Resources::instance();
- res->dseg.set_byte(0xB4F3, scene->getId());
+ res->dseg.set_byte(dsAddr_currentScene, scene->getId());
Common::Point pos = scene->getPosition();
- res->dseg.set_word(0x64AF, pos.x);
- res->dseg.set_word(0x64B1, pos.y);
+ res->dseg.set_word(dsAddr_egoX, pos.x);
+ res->dseg.set_word(dsAddr_egoY, pos.y);
- assert(res->dseg.size() >= 0x6478 + 0x777a);
- strncpy((char *)res->dseg.ptr(0x6478), desc.c_str(), 0x16);
- out->write(res->dseg.ptr(0x6478), 0x777a);
+ assert(res->dseg.size() >= dsAddr_saveState + saveStateSize);
+ // FIXME: Description string is 24 bytes and null based on detection.cpp code, not 22?
+ strncpy((char *)res->dseg.ptr(dsAddr_saveState), desc.c_str(), 22);
+ out->write(res->dseg.ptr(dsAddr_saveState), saveStateSize);
if (!Graphics::saveThumbnail(*out))
warning("saveThumbnail failed");
@@ -267,7 +278,6 @@ Common::Error TeenAgentEngine::saveGameState(int slot, const Common::String &des
return Common::kNoError;
}
-
int TeenAgentEngine::skipEvents() const {
Common::EventManager *_event = _system->getEventManager();
Common::Event event;
@@ -295,7 +305,7 @@ bool TeenAgentEngine::showCDLogo() {
if (!cdlogo.exists("cdlogo.res") || !cdlogo.open("cdlogo.res"))
return true;
- const uint bgSize = 0xfa00;
+ const uint bgSize = kScreenWidth * kScreenHeight;
const uint paletteSize = 3 * 256;
byte *bg = (byte *)malloc(bgSize);
@@ -314,8 +324,8 @@ bool TeenAgentEngine::showCDLogo() {
for (uint c = 0; c < paletteSize; ++c)
palette[c] *= 4;
- _system->getPaletteManager()->setPalette(palette, 0, 0x100);
- _system->copyRectToScreen(bg, 320, 0, 0, 320, 200);
+ _system->getPaletteManager()->setPalette(palette, 0, 256);
+ _system->copyRectToScreen(bg, kScreenWidth, 0, 0, kScreenWidth, kScreenHeight);
_system->updateScreen();
free(bg);
@@ -341,7 +351,7 @@ bool TeenAgentEngine::showLogo() {
if (!frame)
return true;
- const uint bgSize = 0xfa00;
+ const uint bgSize = kScreenWidth * kScreenHeight;
const uint paletteSize = 3 * 256;
byte *bg = (byte *)malloc(bgSize);
@@ -360,7 +370,7 @@ bool TeenAgentEngine::showLogo() {
for (uint c = 0; c < paletteSize; ++c)
palette[c] *= 4;
- _system->getPaletteManager()->setPalette(palette, 0, 0x100);
+ _system->getPaletteManager()->setPalette(palette, 0, 256);
free(palette);
@@ -374,7 +384,7 @@ bool TeenAgentEngine::showLogo() {
return r > 0 ? true : false;
}
}
- _system->copyRectToScreen(bg, 320, 0, 0, 320, 200);
+ _system->copyRectToScreen(bg, kScreenWidth, 0, 0, kScreenWidth, kScreenHeight);
frame.reset(logo.getStream(i));
if (!frame) {
@@ -419,23 +429,23 @@ bool TeenAgentEngine::showMetropolis() {
palette[c] *= 4;
}
- _system->getPaletteManager()->setPalette(palette, 0, 0x100);
+ _system->getPaletteManager()->setPalette(palette, 0, 256);
free(palette);
const uint varia6Size = 21760;
const uint varia9Size = 18302;
- byte *varia_6 = (byte *)malloc(varia6Size);
- byte *varia_9 = (byte *)malloc(varia9Size);
- if (!varia_6 || !varia_9) {
- free(varia_6);
- free(varia_9);
+ byte *varia6Data = (byte *)malloc(varia6Size);
+ byte *varia9Data = (byte *)malloc(varia9Size);
+ if (!varia6Data || !varia9Data) {
+ free(varia6Data);
+ free(varia9Data);
error("[TeenAgentEngine::showMetropolis] Cannot allocate buffer");
}
- varia.read(6, varia_6, varia6Size);
- varia.read(9, varia_9, varia9Size);
+ varia.read(6, varia6Data, varia6Size);
+ varia.read(9, varia9Data, varia9Size);
const uint colorsSize = 56 * 160 * 2;
byte *colors = (byte *)malloc(colorsSize);
@@ -449,8 +459,8 @@ bool TeenAgentEngine::showMetropolis() {
{
int r = skipEvents();
if (r != 0) {
- free(varia_6);
- free(varia_9);
+ free(varia6Data);
+ free(varia9Data);
free(colors);
return r > 0 ? true : false;
}
@@ -458,7 +468,7 @@ bool TeenAgentEngine::showMetropolis() {
Graphics::Surface *surface = _system->lockScreen();
if (logo_y > 0) {
- surface->fillRect(Common::Rect(0, 0, 320, logo_y), 0);
+ surface->fillRect(Common::Rect(0, 0, kScreenWidth, logo_y), 0);
}
{
@@ -485,7 +495,7 @@ bool TeenAgentEngine::showMetropolis() {
}
byte *dst = (byte *)surface->getBasePtr(0, 131);
- byte *src = varia_6;
+ byte *src = varia6Data;
for (uint y = 0; y < 68; ++y) {
for (uint x = 0; x < 320; ++x) {
if (*src++ == 1) {
@@ -497,7 +507,7 @@ bool TeenAgentEngine::showMetropolis() {
_system->unlockScreen();
_system->copyRectToScreen(
- varia_9 + (logo_y < 0 ? -logo_y * 320 : 0), 320,
+ varia9Data + (logo_y < 0 ? -logo_y * 320 : 0), 320,
0, logo_y >= 0 ? logo_y : 0,
320, logo_y >= 0 ? 57 : 57 + logo_y);
@@ -509,38 +519,37 @@ bool TeenAgentEngine::showMetropolis() {
_system->delayMillis(100);
}
- free(varia_6);
- free(varia_9);
+ free(varia6Data);
+ free(varia9Data);
free(colors);
return true;
}
Common::Error TeenAgentEngine::run() {
- Resources *res = Resources::instance();
if (!res->loadArchives(_gameDescription))
return Common::kUnknownError;
Common::EventManager *_event = _system->getEventManager();
- initGraphics(320, 200, false);
+ initGraphics(kScreenWidth, kScreenHeight, false);
console = new Console(this);
- scene = new Scene(this, _system);
+ scene = new Scene(this);
inventory = new Inventory(this);
init();
- CursorMan.pushCursor(res->dseg.ptr(0x00da), 8, 12, 0, 0, 1);
+ CursorMan.pushCursor(res->dseg.ptr(dsAddr_cursor), 8, 12, 0, 0, 1);
syncSoundSettings();
setMusic(1);
_mixer->playStream(Audio::Mixer::kMusicSoundType, &_musicHandle, music, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, false);
- int load_slot = Common::ConfigManager::instance().getInt("save_slot");
- if (load_slot >= 0) {
- loadGameState(load_slot);
+ int loadSlot = ConfMan.getInt("save_slot");
+ if (loadSlot >= 0) {
+ loadGameState(loadSlot);
} else {
if (!showCDLogo())
return Common::kNoError;
@@ -549,32 +558,30 @@ Common::Error TeenAgentEngine::run() {
if (!showMetropolis())
return Common::kNoError;
scene->intro = true;
- scene_busy = true;
- processCallback(0x24c);
+ _sceneBusy = true;
+ fnIntro();
}
CursorMan.showMouse(true);
- uint32 game_timer = 0;
- uint32 mark_timer = 0;
+ uint32 gameTimer = 0;
+ uint32 markTimer = 0;
Common::Event event;
Common::Point mouse;
uint32 timer = _system->getMillis();
do {
- Object *current_object = scene->findObject(mouse);
+ Object *currentObject = scene->findObject(mouse);
while (_event->pollEvent(event)) {
- if (event.type == Common::EVENT_RTL) {
- deinit();
+ if (event.type == Common::EVENT_RTL)
return Common::kNoError;
- }
- if ((!scene_busy && inventory->processEvent(event)) || scene->processEvent(event))
+ if ((!_sceneBusy && inventory->processEvent(event)) || scene->processEvent(event))
continue;
- //debug(0, "event");
+ debug(5, "event");
switch (event.type) {
case Common::EVENT_KEYDOWN:
if ((event.kbd.hasFlags(Common::KBD_CTRL) && event.kbd.keycode == Common::KEYCODE_d) ||
@@ -583,33 +590,33 @@ Common::Error TeenAgentEngine::run() {
} else if (event.kbd.hasFlags(0) && event.kbd.keycode == Common::KEYCODE_F5) {
openMainMenuDialog();
} if (event.kbd.hasFlags(Common::KBD_CTRL) && event.kbd.keycode == Common::KEYCODE_f) {
- _mark_delay = _mark_delay == 80 ? 40 : 80;
- debug(0, "mark_delay = %u", _mark_delay);
+ _markDelay = _markDelay == 80 ? 40 : 80;
+ debug(5, "markDelay = %u", _markDelay);
}
break;
case Common::EVENT_LBUTTONDOWN:
if (scene->getId() < 0)
break;
- examine(event.mouse, current_object);
+ examine(event.mouse, currentObject);
break;
case Common::EVENT_RBUTTONDOWN:
- //if (current_object)
- // debug(0, "%d, %s", current_object->id, current_object->name.c_str());
+ if (currentObject)
+ debugC(0, kDebugObject, "%d, %s", currentObject->id, currentObject->name.c_str());
if (scene->getId() < 0)
break;
- if (current_object == NULL)
+ if (currentObject == NULL)
break;
- if (res->dseg.get_byte(0) == 3 && current_object->id == 1) {
- processCallback(0x5189); //boo!
+ if (res->dseg.get_byte(dsAddr_timedCallbackState) == 3 && currentObject->id == 1) {
+ fnGuardDrinking();
break;
}
- if (res->dseg.get_byte(0) == 4 && current_object->id == 5) {
- processCallback(0x99e0); //getting an anchor
+ if (res->dseg.get_byte(dsAddr_timedCallbackState) == 4 && currentObject->id == 5) {
+ fnGotAnchor();
break;
}
- use(current_object);
+ use(currentObject);
break;
case Common::EVENT_MOUSEMOVE:
mouse = event.mouse;
@@ -622,60 +629,60 @@ Common::Error TeenAgentEngine::run() {
//game delays: slow 16, normal 11, fast 5, crazy 1
//mark delays: 4 * (3 - hero_speed), normal == 1
//game delays in 1/100th of seconds
- uint32 new_timer = _system->getMillis();
- uint32 delta = new_timer - timer;
- timer = new_timer;
+ uint32 newTimer = _system->getMillis();
+ uint32 delta = newTimer - timer;
+ timer = newTimer;
- bool tick_game = game_timer <= delta;
- if (tick_game)
- game_timer = _game_delay - ((delta - game_timer) % _game_delay);
+ bool tickGame = gameTimer <= delta;
+ if (tickGame)
+ gameTimer = _gameDelay - ((delta - gameTimer) % _gameDelay);
else
- game_timer -= delta;
+ gameTimer -= delta;
- bool tick_mark = mark_timer <= delta;
- if (tick_mark)
- mark_timer = _mark_delay - ((delta - mark_timer) % _mark_delay);
+ bool tickMark = markTimer <= delta;
+ if (tickMark)
+ markTimer = _markDelay - ((delta - markTimer) % _markDelay);
else
- mark_timer -= delta;
+ markTimer -= delta;
- if (tick_game || tick_mark) {
- bool b = scene->render(tick_game, tick_mark, delta);
- if (!inventory->active() && !b && action != kActionNone) {
+ if (tickGame || tickMark) {
+ bool b = scene->render(tickGame, tickMark, delta);
+ if (!inventory->active() && !b && _action != kActionNone) {
processObject();
- action = kActionNone;
- dst_object = NULL;
+ _action = kActionNone;
+ _dstObject = NULL;
}
- scene_busy = b;
+ _sceneBusy = b;
}
- _system->showMouse(scene->getMessage().empty() && !scene_busy);
+ _system->showMouse(scene->getMessage().empty() && !_sceneBusy);
- bool busy = inventory->active() || scene_busy;
+ bool busy = inventory->active() || _sceneBusy;
Graphics::Surface *surface = _system->lockScreen();
if (!busy) {
- InventoryObject *selected_object = inventory->selectedObject();
- if (current_object || selected_object) {
+ InventoryObject *selectedObject = inventory->selectedObject();
+ if (currentObject || selectedObject) {
Common::String name;
- if (selected_object) {
- name += selected_object->name;
+ if (selectedObject) {
+ name += selectedObject->name;
name += " & ";
}
- if (current_object)
- name += current_object->name;
+ if (currentObject)
+ name += currentObject->name;
- uint w = res->font7.render(NULL, 0, 0, name, 0xd1);
- res->font7.render(surface, (320 - w) / 2, 180, name, 0xd1, true);
+ uint w = res->font7.render(NULL, 0, 0, name, textColorMark);
+ res->font7.render(surface, (kScreenWidth - w) / 2, 180, name, textColorMark, true);
#if 0
- if (current_object) {
- current_object->rect.render(surface, 0x80);
- current_object->actor_rect.render(surface, 0x81);
+ if (currentObject) {
+ currentObject->rect.render(surface, 0x80);
+ currentObject->actorRect.render(surface, 0x81);
}
#endif
}
}
- inventory->render(surface, tick_game ? 1 : 0);
+ inventory->render(surface, tickGame ? 1 : 0);
_system->unlockScreen();
@@ -683,20 +690,19 @@ Common::Error TeenAgentEngine::run() {
console->onFrame();
- uint32 next_tick = MIN(game_timer, mark_timer);
- if (next_tick > 0) {
- _system->delayMillis(next_tick > 40 ? 40 : next_tick);
+ uint32 nextTick = MIN(gameTimer, markTimer);
+ if (nextTick > 0) {
+ _system->delayMillis(nextTick > 40 ? 40 : nextTick);
}
} while (!shouldQuit());
- deinit();
return Common::kNoError;
}
Common::String TeenAgentEngine::parseMessage(uint16 addr) {
Common::String message;
for (
- const char *str = (const char *)Resources::instance()->dseg.ptr(addr);
+ const char *str = (const char *)res->dseg.ptr(addr);
str[0] != 0 || str[1] != 0;
++str) {
char c = str[0];
@@ -708,12 +714,12 @@ Common::String TeenAgentEngine::parseMessage(uint16 addr) {
return message;
}
-void TeenAgentEngine::displayMessage(const Common::String &str, byte color, uint16 position) {
+void TeenAgentEngine::displayMessage(const Common::String &str, byte color, uint16 x, uint16 y) {
if (str.empty()) {
return;
}
- if (color == 0xd1) { //mark's
+ if (color == textColorMark) { // mark's
SceneEvent e(SceneEvent::kPlayAnimation);
e.animation = 0;
e.slot = 0x80;
@@ -725,8 +731,8 @@ void TeenAgentEngine::displayMessage(const Common::String &str, byte color, uint
event.message = str;
event.color = color;
event.slot = 0;
- event.dst.x = position % 320;
- event.dst.y = position / 320;
+ event.dst.x = x;
+ event.dst.y = y;
scene->push(event);
}
@@ -738,46 +744,45 @@ void TeenAgentEngine::displayMessage(const Common::String &str, byte color, uint
}
}
-void TeenAgentEngine::displayMessage(uint16 addr, byte color, uint16 position) {
- displayMessage(parseMessage(addr), color, position);
+void TeenAgentEngine::displayMessage(uint16 addr, byte color, uint16 x, uint16 y) {
+ displayMessage(parseMessage(addr), color, x, y);
}
-void TeenAgentEngine::displayAsyncMessage(uint16 addr, uint16 position, uint16 first_frame, uint16 last_frame, byte color) {
+void TeenAgentEngine::displayAsyncMessage(uint16 addr, uint16 x, uint16 y, uint16 firstFrame, uint16 lastFrame, byte color) {
SceneEvent event(SceneEvent::kMessage);
event.message = parseMessage(addr);
event.slot = 0;
event.color = color;
- event.dst.x = position % 320;
- event.dst.y = position / 320;
- event.first_frame = first_frame;
- event.last_frame = last_frame;
+ event.dst.x = x;
+ event.dst.y = y;
+ event.firstFrame = firstFrame;
+ event.lastFrame = lastFrame;
scene->push(event);
}
-void TeenAgentEngine::displayAsyncMessageInSlot(uint16 addr, byte slot, uint16 first_frame, uint16 last_frame, byte color) {
+void TeenAgentEngine::displayAsyncMessageInSlot(uint16 addr, byte slot, uint16 firstFrame, uint16 lastFrame, byte color) {
SceneEvent event(SceneEvent::kMessage);
event.message = parseMessage(addr);
event.slot = slot + 1;
event.color = color;
- event.first_frame = first_frame;
- event.last_frame = last_frame;
+ event.firstFrame = firstFrame;
+ event.lastFrame = lastFrame;
scene->push(event);
}
-
void TeenAgentEngine::displayCredits(uint16 addr, uint16 timer) {
SceneEvent event(SceneEvent::kCreditsMessage);
- const byte *src = Resources::instance()->dseg.ptr(addr);
+ const byte *src = res->dseg.ptr(addr);
event.orientation = *src++;
event.color = *src++;
event.lan = 8;
event.dst.y = *src;
while (true) {
- ++src; //skip y position
+ ++src; // skip y position
Common::String line((const char *)src);
event.message += line;
src += line.size() + 1;
@@ -785,33 +790,33 @@ void TeenAgentEngine::displayCredits(uint16 addr, uint16 timer) {
break;
event.message += "\n";
}
- int w = Resources::instance()->font8.render(NULL, 0, 0, event.message, 0xd1);
- event.dst.x = (320 - w) / 2;
+ int w = res->font8.render(NULL, 0, 0, event.message, textColorCredits);
+ event.dst.x = (kScreenWidth - w) / 2;
event.timer = timer;
scene->push(event);
}
void TeenAgentEngine::displayCredits() {
SceneEvent event(SceneEvent::kCredits);
- event.message = parseMessage(0xe488);
- event.dst.y = 200;
+ event.message = parseMessage(dsAddr_finalCredits7);
+ event.dst.y = kScreenHeight;
int lines = 1;
for (uint i = 0; i < event.message.size(); ++i)
if (event.message[i] == '\n')
++lines;
- event.dst.x = (320 - Resources::instance()->font7.render(NULL, 0, 0, event.message, 0xd1)) / 2;
+ event.dst.x = (kScreenWidth - res->font7.render(NULL, 0, 0, event.message, textColorCredits)) / 2;
event.timer = 11 * lines - event.dst.y + 22;
- //debug(0, "credits = %s", event.message.c_str());
+ debug(2, "credits = %s", event.message.c_str());
scene->push(event);
}
-void TeenAgentEngine::displayCutsceneMessage(uint16 addr, uint16 position) {
+void TeenAgentEngine::displayCutsceneMessage(uint16 addr, uint16 x, uint16 y) {
SceneEvent event(SceneEvent::kCreditsMessage);
event.message = parseMessage(addr);
- event.dst.x = position % 320;
- event.dst.y = position / 320;
+ event.dst.x = x;
+ event.dst.y = y;
event.lan = 7;
scene->push(event);
@@ -822,7 +827,7 @@ void TeenAgentEngine::moveTo(const Common::Point &dst, byte o, bool warp) {
}
void TeenAgentEngine::moveTo(Object *obj) {
- moveTo(obj->actor_rect.right, obj->actor_rect.bottom, obj->actor_orientation);
+ moveTo(obj->actorRect.right, obj->actorRect.bottom, obj->actorOrientation);
}
void TeenAgentEngine::moveTo(uint16 x, uint16 y, byte o, bool warp) {
@@ -865,7 +870,6 @@ void TeenAgentEngine::playActorAnimation(uint16 id, bool async, bool ignore) {
waitAnimation();
}
-
void TeenAgentEngine::loadScene(byte id, const Common::Point &pos, byte o) {
loadScene(id, pos.x, pos.y, o);
}
@@ -890,21 +894,21 @@ void TeenAgentEngine::enableOn(bool enable) {
scene->push(event);
}
-void TeenAgentEngine::setOns(byte id, byte value, byte scene_id) {
+void TeenAgentEngine::setOns(byte id, byte value, byte sceneId) {
SceneEvent event(SceneEvent::kSetOn);
event.ons = id + 1;
event.color = value;
- event.scene = scene_id;
+ event.scene = sceneId;
scene->push(event);
}
-void TeenAgentEngine::setLan(byte id, byte value, byte scene_id) {
+void TeenAgentEngine::setLan(byte id, byte value, byte sceneId) {
if (id == 0)
error("setting lan 0 is invalid");
SceneEvent event(SceneEvent::kSetLan);
event.lan = id;
event.color = value;
- event.scene = scene_id;
+ event.scene = sceneId;
scene->push(event);
}
@@ -925,35 +929,34 @@ void TeenAgentEngine::reloadLan() {
scene->push(event);
}
-
void TeenAgentEngine::playMusic(byte id) {
SceneEvent event(SceneEvent::kPlayMusic);
event.music = id;
scene->push(event);
}
-void TeenAgentEngine::playSound(byte id, byte skip_frames) {
- if (skip_frames > 0)
- --skip_frames;
+void TeenAgentEngine::playSound(byte id, byte skipFrames) {
+ if (skipFrames > 0)
+ --skipFrames;
SceneEvent event(SceneEvent::kPlaySound);
event.sound = id;
- event.color = skip_frames;
+ event.color = skipFrames;
scene->push(event);
}
-void TeenAgentEngine::enableObject(byte id, byte scene_id) {
+void TeenAgentEngine::enableObject(byte id, byte sceneId) {
SceneEvent event(SceneEvent::kEnableObject);
event.object = id + 1;
event.color = 1;
- event.scene = scene_id;
+ event.scene = sceneId;
scene->push(event);
}
-void TeenAgentEngine::disableObject(byte id, byte scene_id) {
+void TeenAgentEngine::disableObject(byte id, byte sceneId) {
SceneEvent event(SceneEvent::kEnableObject);
event.object = id + 1;
event.color = 0;
- event.scene = scene_id;
+ event.scene = sceneId;
scene->push(event);
}
@@ -1015,7 +1018,6 @@ void TeenAgentEngine::wait(uint16 frames) {
}
void TeenAgentEngine::playSoundNow(byte id) {
- Resources *res = Resources::instance();
uint size = res->sam_sam.getSize(id);
if (size == 0) {
warning("skipping invalid sound %u", id);
@@ -1024,28 +1026,26 @@ void TeenAgentEngine::playSoundNow(byte id) {
byte *data = (byte *)malloc(size);
res->sam_sam.read(id, data, size);
- //debug(0, "playing %u samples...", size);
+ debug(3, "playing %u samples...", size);
Audio::AudioStream *stream = Audio::makeRawStream(data, size, 11025, 0);
- _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream); //dispose is YES by default
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream); // dispose is YES by default
}
-
void TeenAgentEngine::setMusic(byte id) {
- debug(0, "starting music %u", id);
- Resources *res = Resources::instance();
+ debugC(0, kDebugMusic, "starting music %u", id);
- if (id != 1) //intro music
- *res->dseg.ptr(0xDB90) = id;
+ if (id != 1) // intro music
+ res->dseg.set_byte(dsAddr_currentMusic, id);
if (_gameDescription->flags & ADGF_CD) {
byte track2cd[] = {7, 2, 0, 9, 3, 6, 8, 10, 4, 5, 11};
if (id == 0 || id > 11 || track2cd[id - 1] == 0) {
- debug(0, "no cd music for id %u", id);
+ debugC(0, kDebugMusic, "no cd music for id %u", id);
return;
}
byte track = track2cd[id - 1];
- debug(0, "playing cd track %u", track);
+ debugC(0, kDebugMusic, "playing cd track %u", track);
_system->getAudioCDManager()->play(track, -1, 0, 0);
} else if (music->load(id))
music->start();
diff --git a/engines/teenagent/teenagent.h b/engines/teenagent/teenagent.h
index 737f07ba85..d6a2c0d3c6 100644
--- a/engines/teenagent/teenagent.h
+++ b/engines/teenagent/teenagent.h
@@ -23,12 +23,15 @@
#define TEENAGENT_ENGINE_H
#include "engines/engine.h"
-#include "teenagent/pack.h"
-#include "teenagent/resources.h"
-#include "teenagent/inventory.h"
+
#include "audio/audiostream.h"
#include "audio/mixer.h"
+
#include "common/random.h"
+#include "common/rect.h"
+#include "common/array.h"
+
+#include "teenagent/dialog.h"
struct ADGameDescription;
@@ -43,14 +46,34 @@ struct ADGameDescription;
namespace TeenAgent {
struct Object;
+struct UseHotspot;
class Scene;
class MusicPlayer;
+class Dialog;
class Console;
+class Resources;
+class Inventory;
+
+// Engine Debug Flags
+enum {
+ kDebugActor = (1 << 0),
+ kDebugAnimation = (1 << 1),
+ kDebugCallbacks = (1 << 2),
+ kDebugDialog = (1 << 3),
+ kDebugFont = (1 << 4),
+ kDebugInventory = (1 << 5),
+ kDebugMusic = (1 << 6),
+ kDebugObject = (1 << 7),
+ kDebugPack = (1 << 8),
+ kDebugScene = (1 << 9),
+ kDebugSurface = (1 << 10)
+};
+
+const uint16 kScreenWidth = 320;
+const uint16 kScreenHeight = 200;
class TeenAgentEngine : public Engine {
public:
- enum Action { kActionNone, kActionExamine, kActionUse };
-
TeenAgentEngine(OSystem *system, const ADGameDescription *gd);
~TeenAgentEngine();
@@ -58,15 +81,16 @@ public:
virtual Common::Error loadGameState(int slot);
virtual Common::Error saveGameState(int slot, const Common::String &desc);
virtual bool canLoadGameStateCurrently() { return true; }
- virtual bool canSaveGameStateCurrently() { return !scene_busy; }
+ virtual bool canSaveGameStateCurrently() { return !_sceneBusy; }
virtual bool hasFeature(EngineFeature f) const;
void init();
- void deinit();
+
+ enum Action { kActionNone, kActionExamine, kActionUse };
void examine(const Common::Point &point, Object *object);
void use(Object *object);
- inline void cancel() { action = kActionNone; }
+ inline void cancel() { _action = kActionNone; }
bool processCallback(uint16 addr);
inline Scene *getScene() { return scene; }
@@ -76,15 +100,15 @@ public:
bool showMetropolis();
int skipEvents() const;
- static Common::String parseMessage(uint16 addr);
+ Common::String parseMessage(uint16 addr);
//event driven:
- void displayMessage(uint16 addr, byte color = 0xd1, uint16 position = 0);
- void displayMessage(const Common::String &str, byte color = 0xd1, uint16 position = 0);
- void displayAsyncMessage(uint16 addr, uint16 position, uint16 first_frame, uint16 last_frame, byte color = 0xd1);
- void displayAsyncMessageInSlot(uint16 addr, byte slot, uint16 first_frame, uint16 last_frame, byte color = 0xd1);
+ void displayMessage(uint16 addr, byte color = textColorMark, uint16 x = 0, uint16 y = 0);
+ void displayMessage(const Common::String &str, byte color = textColorMark, uint16 x = 0, uint16 y = 0);
+ void displayAsyncMessage(uint16 addr, uint16 x, uint16 y, uint16 firstFrame, uint16 lastFrame, byte color = textColorMark);
+ void displayAsyncMessageInSlot(uint16 addr, byte slot, uint16 firstFrame, uint16 lastFrame, byte color = textColorMark);
void displayCredits(uint16 addr, uint16 timer = 0);
- void displayCutsceneMessage(uint16 addr, uint16 position);
+ void displayCutsceneMessage(uint16 addr, uint16 x, uint16 y);
void moveTo(const Common::Point &dst, byte o, bool warp = false);
void moveTo(uint16 x, uint16 y, byte o, bool warp = false);
void moveTo(Object *obj);
@@ -94,18 +118,18 @@ public:
void loadScene(byte id, const Common::Point &pos, byte o = 0);
void loadScene(byte id, uint16 x, uint16 y, byte o = 0);
void enableOn(bool enable = true);
- void setOns(byte id, byte value, byte scene_id = 0);
- void setLan(byte id, byte value, byte scene_id = 0);
+ void setOns(byte id, byte value, byte sceneId = 0);
+ void setLan(byte id, byte value, byte sceneId = 0);
void setFlag(uint16 addr, byte value);
byte getFlag(uint16 addr);
void reloadLan();
void rejectMessage();
void playMusic(byte id); //schedules play
- void playSound(byte id, byte skip_frames);
+ void playSound(byte id, byte skipFrames);
void playSoundNow(byte id);
- void enableObject(byte id, byte scene_id = 0);
- void disableObject(byte id, byte scene_id = 0);
+ void enableObject(byte id, byte sceneId = 0);
+ void disableObject(byte id, byte sceneId = 0);
void hideActor();
void showActor();
void waitAnimation();
@@ -119,9 +143,11 @@ public:
Common::RandomSource _rnd;
+ Resources *res;
Scene *scene;
Inventory *inventory;
MusicPlayer *music;
+ Dialog *dialog;
Console *console;
void setMusic(byte id);
@@ -130,17 +156,47 @@ private:
void processObject();
bool trySelectedObject();
- bool scene_busy;
- Action action;
- Object *dst_object;
+ bool _sceneBusy;
+ Action _action;
+ Object *_dstObject;
Audio::AudioStream *_musicStream;
Audio::SoundHandle _musicHandle, _soundHandle;
const ADGameDescription *_gameDescription;
- uint _mark_delay, _game_delay;
-
- Common::Array<Common::Array<UseHotspot> > use_hotspots;
+ uint _markDelay, _gameDelay;
+
+ Common::Array<Common::Array<UseHotspot> > _useHotspots;
+
+ void fnIntro();
+ void fnPoleClimbFail();
+ void fnGotAnchor();
+ void fnGetOutOfLake();
+ void fnGuardDrinking();
+ void fnEgoDefaultPosition();
+ void fnEnterCave();
+ void fnEgoScaredBySpider();
+ void fnMoveToLadderAndLeaveCellar();
+ void fnLeaveCellar();
+ void fnPutRockInHole();
+ void fnEgoBottomRightTurn();
+ bool fnCheckingDrawers();
+ void fnDrawerOpenMessage();
+ bool fnRobotSafeAlreadyUnlockedCheck();
+ void fnRobotSafeUnlockCheck();
+ bool fnMansionIntrusionAttempt();
+ void fnSecondMansionIntrusion();
+ void fnThirdMansionIntrusion();
+ void fnFourthMansionIntrusion();
+ void fnFifthMansionIntrusion();
+ void fnSixthMansionIntrusion();
+ void fnTooDark();
+ bool fnIsCookGone();
+ void fnEgoSuspiciousPosition();
+ void fnGivingFlowerToOldLady();
+ void fnGiveAnotherFlowerToOldLady();
+ void fnGivingFlowerToAnne();
+ void fnGiveAnotherFlowerToAnne();
};
} // End of namespace TeenAgent
diff --git a/engines/tinsel/actors.cpp b/engines/tinsel/actors.cpp
index a784ff5788..0ba8b7cdba 100644
--- a/engines/tinsel/actors.cpp
+++ b/engines/tinsel/actors.cpp
@@ -319,8 +319,8 @@ static void ActorRestoredProcess(CORO_PARAM, const void *param) {
CORO_BEGIN_CODE(_ctx);
_ctx->pic = RestoreInterpretContext(r->pic);
-
- // The newly added check here specially sets the process to RES_NOT when loading a savegame.
+
+ // The newly added check here specially sets the process to RES_NOT when loading a savegame.
// This is needed particularly for the Psychiatrist scene in Discworld 1 - otherwise Rincewind
// can't go upstairs without leaving the building and returning. If this patch causes problems
// in other scenes, an added check for the hCode == 1174490602 could be added.
diff --git a/engines/tinsel/pcode.cpp b/engines/tinsel/pcode.cpp
index 6ea18c8268..04bc2856ca 100644
--- a/engines/tinsel/pcode.cpp
+++ b/engines/tinsel/pcode.cpp
@@ -152,7 +152,7 @@ static const byte fragment12[] = {OP_JMPTRUE | OPSIZE16, FRAGMENT_WORD(1491),
OP_IMM | OPSIZE16, FRAGMENT_WORD(322), OP_LIBCALL | OPSIZE8, 46, // Give back the whistle
OP_JUMP | OPSIZE16, FRAGMENT_WORD(1568)};
static const byte fragment13[] = {OP_ZERO, OP_GSTORE | OPSIZE16, FRAGMENT_WORD(306)};
-static const byte fragment14[] = {OP_LIBCALL | OPSIZE8, 58,
+static const byte fragment14[] = {OP_LIBCALL | OPSIZE8, 58,
OP_IMM, FRAGMENT_DWORD((42 << 23)), OP_ONE, OP_ZERO, OP_LIBCALL | OPSIZE8, 44,
OP_LIBCALL | OPSIZE8, 97, OP_JUMP | OPSIZE16, FRAGMENT_WORD(2220)
};
@@ -222,7 +222,7 @@ const WorkaroundEntry workaroundList[] = {
// times would cause the game to crash
{TINSEL_V2, true, false, Common::kPlatformUnknown, 1109294728, 0, sizeof(fragment13), fragment13},
- // DW1 PSX DEMO: Alters a script in the PSX DW1 demo to show the Idle animation scene rather than
+ // DW1 PSX DEMO: Alters a script in the PSX DW1 demo to show the Idle animation scene rather than
// quitting the game when no user input happens for a while
{TINSEL_V1, true, true, Common::kPlatformPSX, 0, 2186, sizeof(fragment14), fragment14},
diff --git a/engines/tinsel/saveload.cpp b/engines/tinsel/saveload.cpp
index 518e27f02b..2ef92d853f 100644
--- a/engines/tinsel/saveload.cpp
+++ b/engines/tinsel/saveload.cpp
@@ -502,7 +502,7 @@ static bool DoRestore() {
delete f; // Invalid header, or savegame too new -> skip it
return false;
}
-
+
// Load in the data. For older savegame versions, we potentially need to load the data twice, once
// for pre 1.5 savegames, and if that fails, a second time for 1.5 savegames
int numInterpreters = hdr.numInterpreters;
diff --git a/engines/toltecs/animation.cpp b/engines/toltecs/animation.cpp
index eef9cef9ed..084332cf83 100644
--- a/engines/toltecs/animation.cpp
+++ b/engines/toltecs/animation.cpp
@@ -53,7 +53,7 @@ void AnimationPlayer::start(uint resIndex) {
_vm->_arc->closeResource();
debug(1, "AnimationPlayer::start() width = %d; height = %d; frameCount = %d", _width, _height, _frameCount);
-
+
_vm->_sceneWidth = _width;
_vm->_sceneHeight = _height;
@@ -63,7 +63,7 @@ void AnimationPlayer::start(uint resIndex) {
_frameNumber = 0;
// TODO mov screenFlag01, 0FFFFh
// TODO mov animDrawFrameFlag, 0FFFFh
-
+
_firstNextFrameOffset = _nextFrameOffset;
_firstCurFrameSize = _curFrameSize;
_firstNextFrameSize = _nextFrameSize;
@@ -81,25 +81,25 @@ void AnimationPlayer::nextFrame() {
} else {
_frameNumber++;
}
-
+
debug(1, "AnimationPlayer::nextFrame() frameNumber = %d", _frameNumber);
if (_keepFrameCounter > 0) {
_keepFrameCounter--;
return;
}
-
+
_vm->_arc->openResource(_resIndex);
_vm->_arc->seek(_nextFrameOffset, SEEK_CUR);
_curFrameSize = _nextFrameSize;
-
+
if (_curFrameSize == 0)
_curFrameSize = 1;
-
+
_vm->_arc->read(_animBuffer, _curFrameSize);
_nextFrameSize = _vm->_arc->readUint32LE();
_nextFrameOffset += _curFrameSize + 4;
-
+
if (_curFrameSize > 1) {
unpackFrame();
// TODO mov animDrawFrameFlag, 0FFFFh
diff --git a/engines/toltecs/animation.h b/engines/toltecs/animation.h
index 22576d7535..54ec5d8afa 100644
--- a/engines/toltecs/animation.h
+++ b/engines/toltecs/animation.h
@@ -54,7 +54,7 @@ public:
uint16 _width, _height;
uint16 _frameNumber, _frameCount;
uint32 _keepFrameCounter;
-
+
uint32 _curFrameSize;
uint32 _nextFrameSize, _nextFrameOffset;
diff --git a/engines/toltecs/menu.cpp b/engines/toltecs/menu.cpp
index 415f19ca31..6e23ff988f 100644
--- a/engines/toltecs/menu.cpp
+++ b/engines/toltecs/menu.cpp
@@ -21,8 +21,11 @@
*
*/
+#include "audio/mixer.h"
#include "common/savefile.h"
+#include "common/config-manager.h"
+
#include "toltecs/toltecs.h"
#include "toltecs/menu.h"
#include "toltecs/palette.h"
@@ -37,7 +40,7 @@ MenuSystem::MenuSystem(ToltecsEngine *vm) : _vm(vm) {
MenuSystem::~MenuSystem() {
}
-int MenuSystem::run() {
+int MenuSystem::run(MenuID menuId) {
//debug("MenuSystem::run()");
@@ -50,18 +53,13 @@ int MenuSystem::run() {
memcpy(backgroundOrig.getBasePtr(0,0), _vm->_screen->_frontScreen, 640 * 400);
_currMenuID = kMenuIdNone;
- _newMenuID = kMenuIdMain;
+ _newMenuID = menuId;
_currItemID = kItemIdNone;
_editingDescription = false;
- _cfgText = true;
- _cfgVoices = true;
- _cfgMasterVolume = 10;
- _cfgVoicesVolume = 10;
- _cfgMusicVolume = 10;
- _cfgSoundFXVolume = 10;
- _cfgBackgroundVolume = 10;
- _running = true;
+
+ _running = true;
_top = 30 - _vm->_guiHeight / 2;
+
_needRedraw = false;
// TODO: buildColorTransTable2
@@ -78,7 +76,7 @@ int MenuSystem::run() {
update();
_vm->_system->updateScreen();
}
-
+
// Restore original background
memcpy(_vm->_screen->_frontScreen, backgroundOrig.getBasePtr(0,0), 640 * 400);
_vm->_system->copyRectToScreen(_vm->_screen->_frontScreen, 640, 0, 0, 640, 400);
@@ -89,7 +87,7 @@ int MenuSystem::run() {
_background->free();
delete _background;
- return 0;
+ return 0;
}
void MenuSystem::update() {
@@ -104,7 +102,7 @@ void MenuSystem::update() {
if (_needRedraw) {
//_vm->_system->copyRectToScreen(_vm->_screen->_frontScreen + 39 * 640 + 60, 640, 60, 39, 520, 247);
- _vm->_system->copyRectToScreen(_vm->_screen->_frontScreen, 640, 0, 0, 640, 400);
+ _vm->_system->copyRectToScreen(_vm->_screen->_frontScreen, 640, 0, _top, 640, 400 - _top);
//debug("redraw");
_needRedraw = false;
}
@@ -204,7 +202,7 @@ void MenuSystem::handleKeyDown(const Common::KeyState& kbd) {
ItemID MenuSystem::findItemAt(int x, int y) {
for (Common::Array<Item>::iterator iter = _items.begin(); iter != _items.end(); iter++) {
- if ((*iter).rect.contains(x, y))
+ if ((*iter).rect.contains(x, y - _top))
return (*iter).id;
}
return kItemIdNone;
@@ -241,8 +239,8 @@ void MenuSystem::initMenu(MenuID menuID) {
drawString(0, 74, 320, 1, 229, _vm->getSysString(kStrWhatCanIDoForYou));
addClickTextItem(kItemIdLoad, 0, 115, 320, 0, _vm->getSysString(kStrLoad), 229, 255);
addClickTextItem(kItemIdSave, 0, 135, 320, 0, _vm->getSysString(kStrSave), 229, 255);
- addClickTextItem(kItemIdToggleText, 0, 165, 320, 0, _vm->getSysString(kStrTextOn), 229, 255);
- addClickTextItem(kItemIdToggleVoices, 0, 185, 320, 0, _vm->getSysString(kStrVoicesOn), 229, 255);
+ addClickTextItem(kItemIdToggleText, 0, 165, 320, 0, _vm->getSysString(_vm->_cfgText ? kStrTextOn : kStrTextOff), 229, 255);
+ addClickTextItem(kItemIdToggleVoices, 0, 185, 320, 0, _vm->getSysString(_vm->_cfgVoices ? kStrVoicesOn : kStrVoicesOff), 229, 255);
addClickTextItem(kItemIdVolumesMenu, 0, 215, 320, 0, _vm->getSysString(kStrVolume), 229, 255);
addClickTextItem(kItemIdPlay, 0, 245, 320, 0, _vm->getSysString(kStrPlay), 229, 255);
addClickTextItem(kItemIdQuit, 0, 275, 320, 0, _vm->getSysString(kStrQuit), 229, 255);
@@ -326,13 +324,13 @@ void MenuSystem::clickItem(ItemID id) {
_newMenuID = kMenuIdLoad;
break;
case kItemIdToggleText:
- setCfgText(!_cfgText, true);
- if (!_cfgVoices && !_cfgText)
+ setCfgText(!_vm->_cfgText, true);
+ if (!_vm->_cfgVoices && !_vm->_cfgText)
setCfgVoices(true, false);
break;
case kItemIdToggleVoices:
- setCfgVoices(!_cfgVoices, true);
- if (!_cfgVoices && !_cfgText)
+ setCfgVoices(!_vm->_cfgVoices, true);
+ if (!_vm->_cfgVoices && !_vm->_cfgText)
setCfgText(true, false);
break;
case kItemIdVolumesMenu:
@@ -416,7 +414,7 @@ void MenuSystem::restoreRect(int x, int y, int w, int h) {
}
void MenuSystem::shadeRect(int x, int y, int w, int h, byte color1, byte color2) {
- byte *src = (byte *)_background->getBasePtr(x, y);
+ byte *src = (byte *)_vm->_screen->_frontScreen + x + y * 640;
for (int xc = 0; xc < w; xc++) {
src[xc] = color2;
src[xc + h * 640] = color1;
@@ -518,49 +516,51 @@ void MenuSystem::clickSavegameItem(ItemID id) {
}
void MenuSystem::setCfgText(bool value, bool active) {
- if (_cfgText != value) {
+ if (_vm->_cfgText != value) {
Item *item = getItem(kItemIdToggleText);
- _cfgText = value;
+ _vm->_cfgText = value;
restoreRect(item->rect.left, item->rect.top, item->rect.width() + 1, item->rect.height() - 2);
- setItemCaption(item, _vm->getSysString(_cfgText ? kStrTextOn : kStrTextOff));
+ setItemCaption(item, _vm->getSysString(_vm->_cfgText ? kStrTextOn : kStrTextOff));
drawItem(kItemIdToggleText, true);
+ ConfMan.setBool("subtitles", value);
}
}
void MenuSystem::setCfgVoices(bool value, bool active) {
- if (_cfgVoices != value) {
+ if (_vm->_cfgVoices != value) {
Item *item = getItem(kItemIdToggleVoices);
- _cfgVoices = value;
+ _vm->_cfgVoices = value;
restoreRect(item->rect.left, item->rect.top, item->rect.width() + 1, item->rect.height() - 2);
- setItemCaption(item, _vm->getSysString(_cfgVoices ? kStrVoicesOn : kStrVoicesOff));
+ setItemCaption(item, _vm->getSysString(_vm->_cfgVoices ? kStrVoicesOn : kStrVoicesOff));
drawItem(kItemIdToggleVoices, true);
+ ConfMan.setBool("speech_mute", !value);
}
}
void MenuSystem::drawVolumeBar(ItemID itemID) {
int w = 440, y, volume;
char text[21];
-
+
switch (itemID) {
- case kItemIdMaster:
+ case kItemIdMaster: // unused in ScummVM, always 20
y = 130 + 25 * 0;
- volume = _cfgMasterVolume;
+ volume = 20;
break;
case kItemIdVoices:
y = 130 + 25 * 1;
- volume = _cfgVoicesVolume;
+ volume = _vm->_cfgVoicesVolume;
break;
case kItemIdMusic:
y = 130 + 25 * 2;
- volume = _cfgMusicVolume;
+ volume = _vm->_cfgMusicVolume;
break;
case kItemIdSoundFX:
y = 130 + 25 * 3;
- volume = _cfgSoundFXVolume;
+ volume = _vm->_cfgSoundFXVolume;
break;
- case kItemIdBackground:
+ case kItemIdBackground: // unused in ScummVM, always 20
y = 130 + 25 * 4;
- volume = _cfgBackgroundVolume;
+ volume = 20;
break;
default:
return;
@@ -568,46 +568,48 @@ void MenuSystem::drawVolumeBar(ItemID itemID) {
Font font(_vm->_res->load(_vm->_screen->getFontResIndex(1))->data);
restoreRect(390, y - font.getHeight(), 100, 25);
-
+
for (int i = 0; i < volume; i++)
text[i] = '|';
text[volume] = 0;
-
+
drawString(0, y, w, 0, 246, text);
-
+
}
void MenuSystem::changeVolumeBar(ItemID itemID, int delta) {
-
- int *volume, newVolume;
+ byte newVolume;
switch (itemID) {
- case kItemIdMaster:
- volume = &_cfgMasterVolume;
- break;
case kItemIdVoices:
- volume = &_cfgVoicesVolume;
+ _vm->_cfgVoicesVolume = CLIP(_vm->_cfgVoicesVolume + delta, 0, 20);
+ // Always round volume up instead of down.
+ newVolume = (_vm->_cfgVoicesVolume * Audio::Mixer::kMaxChannelVolume + 19) / 20;
+ _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, newVolume);
+ ConfMan.setInt("speech_volume", newVolume);
break;
case kItemIdMusic:
- volume = &_cfgMusicVolume;
+ _vm->_cfgMusicVolume = CLIP(_vm->_cfgMusicVolume + delta, 0, 20);
+ newVolume = (_vm->_cfgMusicVolume * Audio::Mixer::kMaxChannelVolume + 19) / 20;
+ _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, newVolume);
+ ConfMan.setInt("music_volume", newVolume);
break;
case kItemIdSoundFX:
- volume = &_cfgSoundFXVolume;
+ _vm->_cfgSoundFXVolume = CLIP(_vm->_cfgSoundFXVolume + delta, 0, 20);
+ newVolume = (_vm->_cfgSoundFXVolume * Audio::Mixer::kMaxChannelVolume + 19) / 20;
+ _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, newVolume);
+ ConfMan.setInt("sfx_volume", newVolume);
break;
+ case kItemIdMaster:
case kItemIdBackground:
- volume = &_cfgBackgroundVolume;
+ // unused in ScummVM
break;
default:
return;
}
- newVolume = CLIP(*volume + delta, 0, 20);
-
- if (newVolume != *volume) {
- *volume = newVolume;
- drawVolumeBar(itemID);
- }
-
+ _vm->syncSoundSettings();
+ drawVolumeBar(itemID);
}
} // End of namespace Toltecs
diff --git a/engines/toltecs/menu.h b/engines/toltecs/menu.h
index 3e2c2da8d9..a72205c2e5 100644
--- a/engines/toltecs/menu.h
+++ b/engines/toltecs/menu.h
@@ -29,14 +29,6 @@
namespace Toltecs {
-enum MenuID {
- kMenuIdNone,
- kMenuIdMain,
- kMenuIdSave,
- kMenuIdLoad,
- kMenuIdVolumes
-};
-
enum ItemID {
kItemIdNone,
// Main menu
@@ -85,10 +77,10 @@ public:
MenuSystem(ToltecsEngine *vm);
~MenuSystem();
- int run();
+ int run(MenuID menuId);
void update();
void handleEvents();
-
+
protected:
struct Item {
@@ -99,7 +91,7 @@ protected:
int x, y, w;
uint fontNum;
};
-
+
struct SavegameItem {
int _slotNum;
Common::String _description;
@@ -124,9 +116,6 @@ protected:
Common::Array<Item> _items;
Common::Array<SavegameItem> _savegames;
-
- bool _cfgText, _cfgVoices;
- int _cfgMasterVolume, _cfgVoicesVolume, _cfgMusicVolume, _cfgSoundFXVolume, _cfgBackgroundVolume;
void addClickTextItem(ItemID id, int x, int y, int w, uint fontNum, const char *caption, byte defaultColor, byte activeColor);
@@ -134,13 +123,13 @@ protected:
void handleMouseMove(int x, int y);
void handleMouseClick(int x, int y);
void handleKeyDown(const Common::KeyState& kbd);
-
+
ItemID findItemAt(int x, int y);
Item *getItem(ItemID id);
void setItemCaption(Item *item, const char *caption);
void initMenu(MenuID menuID);
-
+
void enterItem(ItemID id);
void leaveItem(ItemID id);
void clickItem(ItemID id);
diff --git a/engines/toltecs/microtiles.cpp b/engines/toltecs/microtiles.cpp
index 0b61ac38a5..60e65bdaf3 100644
--- a/engines/toltecs/microtiles.cpp
+++ b/engines/toltecs/microtiles.cpp
@@ -138,7 +138,7 @@ Common::Rect * MicroTileArray::getRectangles(int *num_rects, int min_x, int min_
x0 = CLIP (x0, min_x, max_x);
y0 = CLIP (y0, min_y, max_y);
y1 = CLIP (y1, min_y, max_y);
-
+
// FIXME: Why is the following code in an #if block?
#if 1
start = i;
diff --git a/engines/toltecs/movie.cpp b/engines/toltecs/movie.cpp
index 76d42ebf0a..35accb5d93 100644
--- a/engines/toltecs/movie.cpp
+++ b/engines/toltecs/movie.cpp
@@ -61,7 +61,7 @@ void MoviePlayer::playMovie(uint resIndex) {
int16 savedCameraY = _vm->_cameraY;
int16 savedGuiHeight = _vm->_guiHeight;
byte moviePalette[768];
-
+
_vm->_isSaveAllowed = false;
memset(moviePalette, 0, sizeof(moviePalette));
@@ -78,7 +78,7 @@ void MoviePlayer::playMovie(uint resIndex) {
_vm->_arc->readUint32LE();
_vm->_arc->readUint32LE();
_framesPerSoundChunk = _vm->_arc->readUint32LE();
- _vm->_arc->readUint32LE();
+ int rate = _vm->_arc->readUint32LE();
_vm->_sceneWidth = 640;
_vm->_sceneHeight = 400;
@@ -87,7 +87,7 @@ void MoviePlayer::playMovie(uint resIndex) {
_vm->_cameraY = 0;
_vm->_guiHeight = 0;
- _audioStream = Audio::makeQueuingAudioStream(22050, false);
+ _audioStream = Audio::makeQueuingAudioStream(rate, false);
_vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, _audioStream);
@@ -96,49 +96,52 @@ void MoviePlayer::playMovie(uint resIndex) {
fetchAudioChunks();
- uint32 lastTime = _vm->_mixer->getSoundElapsedTime(_audioStreamHandle);
+ byte *chunkBuffer = NULL;
+ uint32 chunkBufferSize = 0;
+ uint32 frame = 0;
while (_chunkCount--) {
-
byte chunkType = _vm->_arc->readByte();
uint32 chunkSize = _vm->_arc->readUint32LE();
- byte *chunkBuffer = NULL;
- uint32 movieOffset;
debug(0, "chunkType = %d; chunkSize = %d", chunkType, chunkSize);
-
+
// Skip audio chunks - we've already queued them in
// fetchAudioChunks() above
if (chunkType == kChunkAudio) {
_vm->_arc->skip(chunkSize);
} else {
- chunkBuffer = new byte[chunkSize];
+ // Only reallocate the chunk buffer if the new chunk is bigger
+ if (chunkSize > chunkBufferSize) {
+ delete[] chunkBuffer;
+ chunkBuffer = new byte[chunkSize];
+ chunkBufferSize = chunkSize;
+ }
+
_vm->_arc->read(chunkBuffer, chunkSize);
}
- movieOffset = _vm->_arc->pos();
-
switch (chunkType) {
case kChunkFirstImage:
case kChunkSubsequentImages:
unpackRle(chunkBuffer, _vm->_screen->_backScreen);
- // TODO: Rework this
- _vm->_screen->updateShakeScreen();
_vm->_screen->_fullRefresh = true;
- _vm->updateInput();
- _vm->drawScreen();
_soundChunkFramesLeft--;
if (_soundChunkFramesLeft <= _framesPerSoundChunk) {
fetchAudioChunks();
}
- while (_vm->_mixer->getSoundElapsedTime(_audioStreamHandle) < lastTime + 111) {
- g_system->delayMillis(10);
+ while (_vm->_mixer->getSoundElapsedTime(_audioStreamHandle) < (1000 * frame) / 9) {
+ if (_vm->_screen->_shakeActive && _vm->_screen->updateShakeScreen()) {
+ _vm->_screen->_fullRefresh = true;
+ }
+ _vm->updateInput();
+ _vm->drawScreen();
+ // Note: drawScreen() calls delayMillis()
}
- lastTime = _vm->_mixer->getSoundElapsedTime(_audioStreamHandle);
-
+ frame++;
break;
case kChunkPalette:
unpackPalette(chunkBuffer, moviePalette, 256, 3);
@@ -150,10 +153,10 @@ void MoviePlayer::playMovie(uint resIndex) {
// Already processed
break;
case kChunkShowSubtitle:
- // TODO: Check if the text is a subtitle (last character == 0xFE).
- // If so, don't show it if text display is disabled.
- memcpy(_vm->_script->getSlotData(subtitleSlot), chunkBuffer, chunkSize);
- _vm->_screen->updateTalkText(subtitleSlot, 0);
+ if (_vm->_cfgText) {
+ memcpy(_vm->_script->getSlotData(subtitleSlot), chunkBuffer, chunkSize);
+ _vm->_screen->updateTalkText(subtitleSlot, 0);
+ }
break;
case kChunkShakeScreen: // start/stop shakescreen effect
if (chunkBuffer[0] == 0xFF)
@@ -176,20 +179,17 @@ void MoviePlayer::playMovie(uint resIndex) {
error("MoviePlayer::playMovie(%04X) Unknown chunk type %d at %08X", resIndex, chunkType, _vm->_arc->pos() - 5 - chunkSize);
}
- delete[] chunkBuffer;
-
- _vm->_arc->seek(movieOffset, SEEK_SET);
-
if (!handleInput())
break;
-
}
+ delete[] chunkBuffer;
+
_audioStream->finish();
_vm->_mixer->stopHandle(_audioStreamHandle);
_vm->_arc->closeResource();
-
+
debug(0, "playMovie() done");
_vm->_sceneWidth = savedSceneWidth;
diff --git a/engines/toltecs/movie.h b/engines/toltecs/movie.h
index aecfac240f..8fa48975d7 100644
--- a/engines/toltecs/movie.h
+++ b/engines/toltecs/movie.h
@@ -36,7 +36,7 @@ public:
~MoviePlayer();
void playMovie(uint resIndex);
-
+
protected:
ToltecsEngine *_vm;
Audio::QueuingAudioStream *_audioStream;
@@ -47,11 +47,11 @@ protected:
void unpackPalette(byte *source, byte *dest, int elemCount, int elemSize);
void unpackRle(byte *source, byte *dest);
-
+
void fetchAudioChunks();
-
+
bool handleInput();
-
+
};
} // End of namespace Toltecs
diff --git a/engines/toltecs/music.cpp b/engines/toltecs/music.cpp
index c322961077..830e4a97da 100644
--- a/engines/toltecs/music.cpp
+++ b/engines/toltecs/music.cpp
@@ -20,15 +20,13 @@
*
*/
-// FIXME: This code is taken from SAGA and needs more work (e.g. setVolume).
+#include "audio/midiparser.h"
+#include "common/textconsole.h"
#include "toltecs/toltecs.h"
#include "toltecs/music.h"
#include "toltecs/resource.h"
-#include "audio/midiparser.h"
-#include "common/textconsole.h"
-
namespace Toltecs {
MusicPlayer::MusicPlayer(bool isGM) : _isGM(isGM), _buffer(NULL) {
@@ -62,7 +60,7 @@ void MusicPlayer::playMIDI(const byte *data, uint32 size, bool loop) {
memcpy(_buffer, data, size);
MidiParser *parser;
-
+
if (!memcmp(data, "FORM", 4))
parser = MidiParser::createParser_XMIDI(NULL);
else
@@ -77,7 +75,7 @@ void MusicPlayer::playMIDI(const byte *data, uint32 size, bool loop) {
_parser = parser;
- setVolume(127);
+ syncVolume();
_isLooping = loop;
_isPlaying = true;
@@ -86,16 +84,6 @@ void MusicPlayer::playMIDI(const byte *data, uint32 size, bool loop) {
}
}
-void MusicPlayer::pause() {
- setVolume(-1);
- _isPlaying = false;
-}
-
-void MusicPlayer::resume() {
- setVolume(127);
- _isPlaying = true;
-}
-
void MusicPlayer::stopAndClear() {
Common::StackLock lock(_mutex);
stop();
diff --git a/engines/toltecs/music.h b/engines/toltecs/music.h
index 79df1ea2f5..8d364dbb9f 100644
--- a/engines/toltecs/music.h
+++ b/engines/toltecs/music.h
@@ -37,8 +37,6 @@ public:
MusicPlayer(bool isGM = true);
void playMIDI(const byte *data, uint32 size, bool loop = false);
- void pause();
- void resume();
void stopAndClear();
// MidiDriver_BASE interface implementation
diff --git a/engines/toltecs/palette.cpp b/engines/toltecs/palette.cpp
index 706218e0ba..74683c6d7a 100644
--- a/engines/toltecs/palette.cpp
+++ b/engines/toltecs/palette.cpp
@@ -31,7 +31,7 @@ namespace Toltecs {
Palette::Palette(ToltecsEngine *vm) : _vm(vm) {
clearFragments();
-
+
memset(_colorTransTable, 0, sizeof(_colorTransTable));
}
@@ -81,7 +81,7 @@ void Palette::setDeltaPalette(byte *palette, byte mask, int8 deltaValue, int16 c
if (mask & 4) colors[index * 3 + 2] = CLIP<int>(rgb + deltaValue, 0, 63) << 2;
index++;
}
-
+
debug(0, "startIndex = %d; colorCount = %d", startIndex, colorCount);
_vm->_system->getPaletteManager()->setPalette((const byte *)colors, 0, 256);
@@ -101,9 +101,9 @@ void Palette::addFragment(uint resIndex, int16 id) {
Resource *fragmentResource = _vm->_res->load(resIndex);
byte count = fragmentResource->size / 3;
-
+
memcpy(&_mainPalette[_fragmentIndex * 3], fragmentResource->data, count * 3);
-
+
PaletteFragment fragment;
fragment.id = id;
fragment.index = _fragmentIndex;
@@ -126,7 +126,7 @@ uint16 Palette::findFragment(int16 id) {
break;
}
}
-
+
debug(0, "Palette::findFragment() result = %04X", result);
return result;
@@ -140,9 +140,9 @@ void Palette::clearFragments() {
void Palette::buildColorTransTable(byte limit, int8 deltaValue, byte mask) {
byte r = 0, g = 0, b = 0;
-
+
mask &= 7;
-
+
for (int i = 0; i < 256; i++) {
if (deltaValue < 0) {
@@ -161,7 +161,7 @@ void Palette::buildColorTransTable(byte limit, int8 deltaValue, byte mask) {
b -= deltaValue;
}
}
-
+
int bestIndex = 0;
uint16 bestMatch = 0xFFFF;
@@ -174,7 +174,7 @@ void Palette::buildColorTransTable(byte limit, int8 deltaValue, byte mask) {
bestIndex = j;
}
}
-
+
_colorTransTable[i] = bestIndex;
}
diff --git a/engines/toltecs/palette.h b/engines/toltecs/palette.h
index 7bcf06e027..570f51777e 100644
--- a/engines/toltecs/palette.h
+++ b/engines/toltecs/palette.h
@@ -66,7 +66,7 @@ protected:
int16 id;
byte index, count;
};
-
+
typedef Common::Array<PaletteFragment> PaletteFragmentArray;
ToltecsEngine *_vm;
diff --git a/engines/toltecs/render.cpp b/engines/toltecs/render.cpp
index 3f5356493e..4c41e6ce00 100644
--- a/engines/toltecs/render.cpp
+++ b/engines/toltecs/render.cpp
@@ -114,7 +114,7 @@ void RenderQueue::addMask(SegmapMaskRect &mask) {
void RenderQueue::update() {
bool doFullRefresh = _vm->_screen->_fullRefresh;
-
+
_updateUta->clear();
if (!doFullRefresh) {
@@ -166,7 +166,7 @@ void RenderQueue::update() {
for (RenderQueueArray::iterator iter = _currQueue->begin(); iter != _currQueue->end(); iter++) {
const RenderQueueItem *item = &(*iter);
-
+
if (item->flags == kRefresh || doFullRefresh) {
switch (item->type) {
@@ -200,7 +200,7 @@ void RenderQueue::update() {
SWAP(_currQueue, _prevQueue);
_currQueue->clear();
-
+
}
void RenderQueue::clear() {
@@ -249,16 +249,16 @@ bool RenderQueue::hasItemChanged(const RenderQueueItem &item1, const RenderQueue
if (item1.type != item2.type)
return true;
-
+
if (item1.rect.left != item2.rect.left ||
item1.rect.top != item2.rect.top ||
item1.rect.right != item2.rect.right ||
item1.rect.bottom != item2.rect.bottom)
return true;
-
+
if (item1.type == kText && item1.text.color != item2.text.color)
return true;
-
+
return false;
}
@@ -268,7 +268,7 @@ void RenderQueue::invalidateItemsByRect(const Common::Rect &rect, const RenderQu
if (item != subItem &&
subItem->flags == kUnchanged &&
rect.intersects(subItem->rect)) {
-
+
subItem->flags = kRefresh;
invalidateItemsByRect(subItem->rect, subItem);
}
diff --git a/engines/toltecs/render.h b/engines/toltecs/render.h
index bb9ec29959..59d7a3ddb9 100644
--- a/engines/toltecs/render.h
+++ b/engines/toltecs/render.h
@@ -75,7 +75,7 @@ public:
void addMask(SegmapMaskRect &mask);
void update();
void clear();
-
+
protected:
typedef Common::List<RenderQueueItem> RenderQueueArray;
@@ -87,7 +87,7 @@ protected:
RenderQueueItem *findItemInQueue(RenderQueueArray *queue, const RenderQueueItem &item);
bool hasItemChanged(const RenderQueueItem &item1, const RenderQueueItem &item2);
void invalidateItemsByRect(const Common::Rect &rect, const RenderQueueItem *item);
-
+
void addDirtyRect(const Common::Rect &rect);
void restoreDirtyBackground();
void updateDirtyRects();
diff --git a/engines/toltecs/resource.cpp b/engines/toltecs/resource.cpp
index b95e0444b1..0b9f7c8fcd 100644
--- a/engines/toltecs/resource.cpp
+++ b/engines/toltecs/resource.cpp
@@ -66,7 +66,7 @@ void ArchiveReader::dump(uint resIndex, const char *prefix) {
byte *data = new byte[resourceSize];
Common::String fn;
-
+
if (prefix)
fn = Common::String::format("%s_%04X.0", prefix, resIndex);
else
@@ -117,11 +117,11 @@ Resource *ResourceCache::load(uint resIndex) {
resItem->data = new byte[resItem->size];
_vm->_arc->read(resItem->data, resItem->size);
_vm->_arc->closeResource();
-
+
_cache[resIndex] = resItem;
-
+
return resItem;
-
+
}
}
diff --git a/engines/toltecs/saveload.cpp b/engines/toltecs/saveload.cpp
index c24d2149b0..6c195a34c2 100644
--- a/engines/toltecs/saveload.cpp
+++ b/engines/toltecs/saveload.cpp
@@ -36,12 +36,11 @@
namespace Toltecs {
/* TODO:
- - Save with F7; Load with F9
- Saving during an animation (AnimationPlayer) is not working correctly yet
- Maybe switch to SCUMM/Tinsel serialization approach?
*/
-#define TOLTECS_SAVEGAME_VERSION 3
+#define TOLTECS_SAVEGAME_VERSION 4
ToltecsEngine::kReadSaveHeaderError ToltecsEngine::readSaveHeader(Common::SeekableReadStream *in, bool loadThumbnail, SaveHeader &header) {
@@ -93,7 +92,7 @@ void ToltecsEngine::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
@@ -141,8 +140,8 @@ void ToltecsEngine::savegame(const char *filename, const char *description) {
}
void ToltecsEngine::loadgame(const char *filename) {
- Common::InSaveFile *in;
- if (!(in = g_system->getSavefileManager()->openForLoading(filename))) {
+ Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename);
+ if (!in) {
warning("Can't open file '%s', game not loaded", filename);
return;
}
@@ -150,13 +149,13 @@ void ToltecsEngine::loadgame(const char *filename) {
SaveHeader header;
kReadSaveHeaderError errorCode = readSaveHeader(in, false, header);
-
+
if (errorCode != kRSHENoError) {
warning("Error loading savegame '%s'", filename);
delete in;
return;
}
-
+
_sound->stopAll();
_music->stopSequence();
g_engine->setTotalPlayTime(header.playTime * 1000);
@@ -182,7 +181,7 @@ void ToltecsEngine::loadgame(const char *filename) {
_mouseX = in->readUint16LE();
_mouseY = in->readUint16LE();
_mouseDisabled = in->readUint16LE();
-
+
_system->warpMouse(_mouseX, _mouseY);
_system->showMouse(_mouseDisabled == 0);
@@ -191,7 +190,7 @@ void ToltecsEngine::loadgame(const char *filename) {
_anim->loadState(in);
_screen->loadState(in);
if (header.version >= 2)
- _sound->loadState(in);
+ _sound->loadState(in, header.version);
if (header.version >= 3)
_music->loadState(in);
diff --git a/engines/toltecs/screen.cpp b/engines/toltecs/screen.cpp
index 634917a7b1..c8d6740b02 100644
--- a/engines/toltecs/screen.cpp
+++ b/engines/toltecs/screen.cpp
@@ -43,9 +43,11 @@ Screen::Screen(ToltecsEngine *vm) : _vm(vm) {
// Screen shaking
_shakeActive = false;
+ _shakeTime = 0;
_shakeCounterInit = 0;
_shakeCounter = 0;
_shakePos = 0;
+ _shakeTime = 0;
// Verb line
_verbLineNum = 0;
@@ -73,7 +75,7 @@ Screen::~Screen() {
delete[] _frontScreen;
delete[] _backScreen;
-
+
delete _renderQueue;
}
@@ -129,7 +131,7 @@ void Screen::drawGuiImage(int16 x, int16 y, uint resIndex) {
byte *dest = _frontScreen + x + (y + _vm->_cameraHeight) * 640;
//debug(0, "Screen::drawGuiImage() x = %d; y = %d; w = %d; h = %d; resIndex = %d", x, y, width, height, resIndex);
-
+
while (workHeight > 0) {
int count = 1;
byte pixel = *imageData++;
@@ -156,6 +158,7 @@ void Screen::drawGuiImage(int16 x, int16 y, uint resIndex) {
void Screen::startShakeScreen(int16 shakeCounter) {
_shakeActive = true;
+ _shakeTime = 0;
_shakeCounterInit = shakeCounter;
_shakeCounter = shakeCounter;
_shakePos = 0;
@@ -166,15 +169,19 @@ void Screen::stopShakeScreen() {
_vm->_system->setShakePos(0);
}
-void Screen::updateShakeScreen() {
- if (_shakeActive) {
+bool Screen::updateShakeScreen() {
+ // Assume shaking happens no more often than 50 times per second
+ if (_shakeActive && _vm->_system->getMillis() - _shakeTime >= 20) {
+ _shakeTime = _vm->_system->getMillis();
_shakeCounter--;
if (_shakeCounter == 0) {
_shakeCounter = _shakeCounterInit;
_shakePos ^= 8;
_vm->_system->setShakePos(_shakePos);
+ return true;
}
}
+ return false;
}
void Screen::addStaticSprite(byte *spriteItem) {
@@ -247,7 +254,7 @@ void Screen::addAnimatedSprite(int16 x, int16 y, int16 fragmentId, byte *data, i
} else {
loopNum |= 0x8000;
}
-
+
WRITE_LE_UINT16(spriteItem + 0, loopNum);
WRITE_LE_UINT16(spriteItem + 4, frameNum);
@@ -308,9 +315,9 @@ void Screen::updateVerbLine(int16 slotIndex, int16 slotOffset) {
wrapState.len2 = 0;
y = _verbLineY;
-
+
memset(wrapState.textBuffer, 0, sizeof(wrapState.textBuffer));
-
+
for (int16 i = 0; i <= _verbLineNum; i++) {
wrapState.sourceString = _vm->_script->getSlotData(_verbLineItems[i].slotIndex) + _verbLineItems[i].slotOffset;
len = wrapGuiText(_fontResIndexArray[0], _verbLineWidth, wrapState);
@@ -331,19 +338,19 @@ void Screen::updateVerbLine(int16 slotIndex, int16 slotOffset) {
wrapState.sourceString++;
wrapState.len1 -= len;
wrapState.len2 = len + 1;
-
+
drawGuiText(_verbLineX - 1 - (wrapState.width / 2), y, 0xF9, 0xFF, _fontResIndexArray[0], wrapState);
wrapState.destString = wrapState.textBuffer;
wrapState.width = 0;
len = wrapGuiText(_fontResIndexArray[0], _verbLineWidth, wrapState);
wrapState.len1 += len;
-
+
y += 9;
}
y += 9;
}
-
+
wrapState.len1 -= len;
wrapState.len2 = len;
@@ -463,13 +470,12 @@ void Screen::addTalkTextRect(Font &font, int16 x, int16 &y, int16 length, int16
textRect->x = CLIP<int16>(x - width / 2, 0, 640);
item->lineCount++;
}
-
+
y += font.getHeight() - 1;
}
void Screen::addTalkTextItemsToRenderQueue() {
-
for (int16 i = 0; i <= _talkTextItemNum; i++) {
TalkTextItem *item = &_talkTextItems[i];
byte *text = _vm->_script->getSlotData(item->slotIndex) + item->slotOffset;
@@ -482,14 +488,15 @@ void Screen::addTalkTextItemsToRenderQueue() {
if (item->duration < 0)
item->duration = 0;
+ if (!_vm->_cfgText)
+ return;
+
for (byte j = 0; j < item->lineCount; j++) {
- _renderQueue->addText(item->lines[j].x, item->lines[j].y, item->color, _fontResIndexArray[item->fontNum],
- text, item->lines[j].length);
+ _renderQueue->addText(item->lines[j].x, item->lines[j].y, item->color,
+ _fontResIndexArray[item->fontNum], text, item->lines[j].length);
text += item->lines[j].length;
}
-
}
-
}
int16 Screen::getTalkTextDuration() {
@@ -559,7 +566,7 @@ int16 Screen::wrapGuiText(uint fontResIndex, int maxWidth, GuiTextWrapState &wra
Font font(_vm->_res->load(fontResIndex)->data);
int16 len = 0;
-
+
while (*wrapState.sourceString >= 0x20 && *wrapState.sourceString < 0xF0) {
byte ch = *wrapState.sourceString;
byte charWidth;
@@ -573,9 +580,9 @@ int16 Screen::wrapGuiText(uint fontResIndex, int maxWidth, GuiTextWrapState &wra
wrapState.width += charWidth;
*wrapState.destString++ = *wrapState.sourceString++;
}
-
+
return len;
-
+
}
void Screen::drawGuiText(int16 x, int16 y, byte fontColor1, byte fontColor2, uint fontResIndex, GuiTextWrapState &wrapState) {
@@ -765,7 +772,7 @@ void Screen::loadState(Common::ReadStream *in) {
_verbLineItems[i].slotIndex = in->readUint16LE();
_verbLineItems[i].slotOffset = in->readUint16LE();
}
-
+
// Load talk text items
_talkTextX = in->readUint16LE();
_talkTextY = in->readUint16LE();
@@ -786,7 +793,7 @@ void Screen::loadState(Common::ReadStream *in) {
_talkTextItems[i].lines[j].length = in->readUint16LE();
}
}
-
+
// Load GUI bitmap
{
byte *gui = _frontScreen + _vm->_cameraHeight * 640;
diff --git a/engines/toltecs/screen.h b/engines/toltecs/screen.h
index 988f59c840..788cde50c6 100644
--- a/engines/toltecs/screen.h
+++ b/engines/toltecs/screen.h
@@ -154,15 +154,15 @@ public:
~Screen();
void unpackRle(byte *source, byte *dest, uint16 width, uint16 height);
-
+
void loadMouseCursor(uint resIndex);
-
+
void drawGuiImage(int16 x, int16 y, uint resIndex);
-
+
void startShakeScreen(int16 shakeCounter);
void stopShakeScreen();
- void updateShakeScreen();
-
+ bool updateShakeScreen();
+
// Sprite list
void addStaticSprite(byte *spriteItem);
void addAnimatedSprite(int16 x, int16 y, int16 fragmentId, byte *data, int16 *spriteArray, bool loop, int mode);
@@ -175,7 +175,7 @@ public:
// Verb line
void updateVerbLine(int16 slotIndex, int16 slotOffset);
-
+
// Talk text
void updateTalkText(int16 slotIndex, int16 slotOffset);
void addTalkTextRect(Font &font, int16 x, int16 &y, int16 length, int16 width, TalkTextItem *item);
@@ -207,7 +207,7 @@ public:
int16 slotIndex;
int16 slotOffset;
};
-
+
struct Rect {
int16 x, y, width, height;
};
@@ -215,12 +215,13 @@ public:
ToltecsEngine *_vm;
byte *_frontScreen, *_backScreen;
-
+
uint _fontResIndexArray[10];
byte _fontColor1, _fontColor2;
// Screen shaking
bool _shakeActive;
+ uint32 _shakeTime;
int16 _shakeCounterInit, _shakeCounter;
int _shakePos;
@@ -229,7 +230,7 @@ public:
VerbLineItem _verbLineItems[8];
int16 _verbLineX, _verbLineY, _verbLineWidth;
int16 _verbLineCount;
-
+
// Talk text
int16 _talkTextX, _talkTextY;
int16 _talkTextMaxWidth;
diff --git a/engines/toltecs/script.cpp b/engines/toltecs/script.cpp
index 9683831980..5e8617bc43 100644
--- a/engines/toltecs/script.cpp
+++ b/engines/toltecs/script.cpp
@@ -183,10 +183,7 @@ void ScriptInterpreter::setMainScript(uint slotIndex) {
}
void ScriptInterpreter::runScript() {
- uint32 lastScreenUpdate = 0;
-
while (!_vm->shouldQuit()) {
-
if (_vm->_movieSceneFlag)
_vm->_mouseButton = 0;
@@ -197,7 +194,7 @@ void ScriptInterpreter::runScript() {
_vm->saveGameState(_vm->_saveLoadSlot, _vm->_saveLoadDescription);
_vm->_saveLoadRequested = 0;
}
-
+
if (_switchLocalDataNear) {
_switchLocalDataNear = false;
_localData = getSlotData(_regs.reg4);
@@ -214,20 +211,10 @@ void ScriptInterpreter::runScript() {
_localData = _stack + 2;
_switchLocalDataNear = true;
}
-
+
byte opcode = readByte();
execOpcode(opcode);
-
- // Update the screen at semi-regular intervals, else the mouse
- // cursor will be jerky.
- uint32 now = _vm->_system->getMillis();
- if (now < lastScreenUpdate || now - lastScreenUpdate > 10) {
- _vm->_system->updateScreen();
- lastScreenUpdate = _vm->_system->getMillis();
- }
-
}
-
}
byte ScriptInterpreter::readByte() {
@@ -547,7 +534,7 @@ const char *getVarName(uint variable) {
int16 ScriptInterpreter::getGameVar(uint variable) {
debug(0, "ScriptInterpreter::getGameVar(%d{%s})", variable, getVarName(variable));
-
+
switch (variable) {
case 0: return _vm->_mouseDisabled;
case 1: return _vm->_mouseY;
@@ -579,7 +566,7 @@ int16 ScriptInterpreter::getGameVar(uint variable) {
void ScriptInterpreter::setGameVar(uint variable, int16 value) {
debug(0, "ScriptInterpreter::setGameVar(%d{%s}, %d)", variable, getVarName(variable), value);
-
+
switch (variable) {
case 0:
_vm->_mouseDisabled = value;
@@ -718,7 +705,7 @@ void ScriptInterpreter::saveState(Common::WriteStream *out) {
// Save stack
out->write(_stack, kScriptStackSize);
out->writeUint16LE(_savedSp);
-
+
// Save IP
out->writeUint16LE((int16)(_code - getSlotData(_regs.reg4)));
@@ -1046,29 +1033,21 @@ void ScriptInterpreter::sfHandleInput() {
Only scancodes known to be used (so far) are converted
*/
switch (_vm->_keyState.keycode) {
- case Common::KEYCODE_ESCAPE:
+ case Common::KEYCODE_ESCAPE:
keyCode = 1;
break;
case Common::KEYCODE_F10:
keyCode = 68;
break;
default:
- break;
+ break;
}
}
localWrite16(varOfs, keyCode);
}
void ScriptInterpreter::sfRunOptionsScreen() {
- _vm->_screen->loadMouseCursor(12);
- _vm->_palette->loadAddPalette(9, 224);
- _vm->_palette->setDeltaPalette(_vm->_palette->getMainPalette(), 7, 0, 31, 224);
- _vm->_screen->finishTalkTextItems();
- _vm->_screen->clearSprites();
- CursorMan.showMouse(true);
- _vm->_menuSystem->run();
- _vm->_keyState.reset();
- _switchLocalDataNear = true;
+ _vm->showMenu(kMenuIdMain);
}
/* NOTE: The opcodes sfPrecacheSprites, sfPrecacheSounds1, sfPrecacheSounds2 and
@@ -1076,7 +1055,7 @@ void ScriptInterpreter::sfRunOptionsScreen() {
of data so the game doesn't stall while playing (due to the slow speed of
CD-Drives back then). This is not needed in ScummVM since all supported
systems are fast enough to load data in-game. */
-
+
void ScriptInterpreter::sfPrecacheSprites() {
// See note above
}
@@ -1102,7 +1081,9 @@ void ScriptInterpreter::sfSaveStackPtr() {
}
void ScriptInterpreter::sfPlayMovie() {
+ CursorMan.showMouse(false);
_vm->_moviePlayer->playMovie(arg16(3));
+ CursorMan.showMouse(true);
}
} // End of namespace Toltecs
diff --git a/engines/toltecs/script.h b/engines/toltecs/script.h
index 0c1898c525..89dca4598f 100644
--- a/engines/toltecs/script.h
+++ b/engines/toltecs/script.h
@@ -56,6 +56,8 @@ public:
void saveState(Common::WriteStream *out);
void loadState(Common::ReadStream *in);
+ void setSwitchLocalDataNear(bool newValue) { _switchLocalDataNear = newValue; }
+
protected:
struct ScriptRegs {
@@ -88,13 +90,13 @@ protected:
bool _cmpBitTest;
ScriptSlot _slots[kMaxScriptSlots];
-
+
ScriptRegs _regs;
int16 _savedSp;
byte readByte();
int16 readInt16();
-
+
void execOpcode(byte opcode);
void setupScriptFunctions();
diff --git a/engines/toltecs/segmap.cpp b/engines/toltecs/segmap.cpp
index f7d806c67b..b06c0af675 100644
--- a/engines/toltecs/segmap.cpp
+++ b/engines/toltecs/segmap.cpp
@@ -48,7 +48,7 @@ void SegmentMap::load(byte *source) {
uint16 maskRectCount = READ_LE_UINT16(source);
source += 2;
uint16 maskRectDataSize = maskRectCount * 12 + 2;
-
+
debug(0, "SegmentMap::load() maskRectCount = %d", maskRectCount);
for (uint16 i = 0; i < maskRectCount; i++) {
@@ -74,25 +74,25 @@ void SegmentMap::load(byte *source) {
// Load path rects
source += 2; // skip rects array size
-
+
uint16 pathRectCount = READ_LE_UINT16(source);
source += 2;
-
+
debug(0, "SegmentMap::load() pathRectCount = %d", pathRectCount);
-
+
for (uint16 i = 0; i < pathRectCount; i++) {
SegmapPathRect pathRect;
pathRect.y1 = READ_LE_UINT16(source);
pathRect.x1 = READ_LE_UINT16(source + 2);
pathRect.y2 = pathRect.y1 + READ_LE_UINT16(source + 4);
pathRect.x2 = pathRect.x1 + READ_LE_UINT16(source + 6);
-
+
debug(0, "SegmentMap::load() (%d, %d, %d, %d)", pathRect.x1, pathRect.y1, pathRect.x2, pathRect.y2);
source += 8;
_pathRects.push_back(pathRect);
}
-
+
// Load info rects
source += 2; // skip rects array size
@@ -141,7 +141,7 @@ void SegmentMap::adjustPathPoint(int16 &x, int16 &y) {
uint32 minDistance = 0xFFFFFFFF, distance;
int16 adjustedX = 0, adjustedY = 0, x2, y2;
-
+
for (int16 rectIndex = 0; rectIndex < (int16)_pathRects.size(); rectIndex++) {
if (x >= _pathRects[rectIndex].x1 && x < _pathRects[rectIndex].x2) {
@@ -174,7 +174,7 @@ void SegmentMap::adjustPathPoint(int16 &x, int16 &y) {
}
}
-
+
x = adjustedX;
y = adjustedY;
@@ -318,7 +318,7 @@ void SegmentMap::findPath(int16 *pointsArray, int16 destX, int16 destY, int16 so
pointsArray[0] = 0;
pointsArray[1] = TO_LE_16(_pathNodesCount + 1);
}
-
+
debug(0, "SegmentMap::findPath() count = %d", FROM_LE_16(pointsArray[1]));
#if 0 // DEBUG: Draw the path we found
@@ -335,7 +335,7 @@ void SegmentMap::findPath(int16 *pointsArray, int16 destX, int16 destY, int16 so
sy = y;
}
#endif
-
+
}
int8 SegmentMap::getScalingAtPoint(int16 x, int16 y) {
diff --git a/engines/toltecs/segmap.h b/engines/toltecs/segmap.h
index 30182a6b71..dda0edeb88 100644
--- a/engines/toltecs/segmap.h
+++ b/engines/toltecs/segmap.h
@@ -61,14 +61,14 @@ public:
void getRgbModifiertAtPoint(int16 x, int16 y, int16 id, byte &r, byte &g, byte &b);
void addMasksToRenderQueue();
-
+
//protected:
public: // for debugging purposes
struct SegmapPathRect {
int16 x1, y1, x2, y2;
};
-
+
struct SegmapInfoRect {
int16 y, x;
int16 height, width;
@@ -78,11 +78,11 @@ public: // for debugging purposes
return py >= y && py <= y + height && px >= x && px <= x + width;
}
};
-
+
struct PathPoint {
int16 y, x;
};
-
+
typedef Common::Array<SegmapMaskRect> SegmapMaskRectArray;
typedef Common::Array<SegmapPathRect> SegmapPathRectArray;
typedef Common::Array<SegmapInfoRect> SegmapInfoRectArray;
diff --git a/engines/toltecs/sound.cpp b/engines/toltecs/sound.cpp
index c9ef00e31b..4b281392e5 100644
--- a/engines/toltecs/sound.cpp
+++ b/engines/toltecs/sound.cpp
@@ -34,48 +34,38 @@ namespace Toltecs {
Sound::Sound(ToltecsEngine *vm) : _vm(vm) {
for (int i = 0; i < kMaxChannels; i++) {
- channels[i].type = kChannelTypeEmpty;
- channels[i].resIndex = -1;
+ clearChannel(i);
}
}
Sound::~Sound() {
}
+void Sound::clearChannel(int channel) {
+ channels[channel].type = kChannelTypeEmpty;
+ channels[channel].resIndex = -1;
+ channels[channel].volume = 0;
+ channels[channel].panning = 0;
+}
+
void Sound::playSpeech(int16 resIndex) {
debug(0, "playSpeech(%d)", resIndex);
- internalPlaySound(resIndex, kChannelTypeSpeech, 50 /*TODO*/, 0);
+
+ if (_vm->_cfgVoices)
+ internalPlaySound(resIndex, kChannelTypeSpeech, 50 /*TODO*/, 0);
}
void Sound::playSound(int16 resIndex, int16 type, int16 volume) {
-
- // TODO: Use the right volumes
-
debug(0, "playSound(%d, %d, %d)", resIndex, type, volume);
-
- if (volume == -1 || type == -2) {
- if (type == kChannelTypeBackground) {
- internalPlaySound(resIndex, type, 50 /*TODO*/, 0);
- } else {
- internalPlaySound(resIndex, type, 100 /*TODO*/, 0);
- }
- } else {
- internalPlaySound(resIndex, type, 100 /*TODO*/, 0);
- }
+ internalPlaySound(resIndex, type, volume, 0);
}
void Sound::playSoundAtPos(int16 resIndex, int16 x, int16 y) {
-
debug(0, "playSoundAtPos(%d, %d, %d)", resIndex, x, y);
- int16 volume, panning = 0, deltaX = 0;
- int8 scaling = _vm->_segmap->getScalingAtPoint(x, y);
-
- if (scaling >= 0)
- volume = 50 + ABS(scaling) / 2;
- else
- volume = 50 - ABS(scaling) / 2;
+ int16 volume = 50 + ABS(_vm->_segmap->getScalingAtPoint(x, y)) / 2;
+ int16 panning = 0, deltaX = 0;
if (_vm->_cameraX > x)
deltaX = _vm->_cameraX - x;
@@ -85,32 +75,31 @@ void Sound::playSoundAtPos(int16 resIndex, int16 x, int16 y) {
deltaX = 600;
volume = ((100 - deltaX / 6) * volume) / 100;
-
+
if (_vm->_cameraX + 320 != x) {
panning = CLIP(x - (_vm->_cameraX + 320), -381, 381) / 3;
}
internalPlaySound(resIndex, 1, volume, panning);
-
}
void Sound::internalPlaySound(int16 resIndex, int16 type, int16 volume, int16 panning) {
+ // Change the game's sound volume (0 - 100) to Scummvm's scale (0 - 255)
+ volume = (volume == -1) ? 255 : volume * 255 / 100;
if (resIndex == -1) {
// Stop all sounds
_vm->_mixer->stopAll();
_vm->_screen->keepTalkTextItemsAlive();
for (int i = 0; i < kMaxChannels; i++) {
- channels[i].type = kChannelTypeEmpty;
- channels[i].resIndex = -1;
+ clearChannel(i);
}
} else if (type == -2) {
// Stop sounds with specified resIndex
for (int i = 0; i < kMaxChannels; i++) {
if (channels[i].resIndex == resIndex) {
_vm->_mixer->stopHandle(channels[i].handle);
- channels[i].type = kChannelTypeEmpty;
- channels[i].resIndex = -1;
+ clearChannel(i);
}
}
} else {
@@ -119,7 +108,7 @@ void Sound::internalPlaySound(int16 resIndex, int16 type, int16 volume, int16 pa
// Stop speech and play new sound
stopSpeech();
}
-
+
// Play new sound in empty channel
int freeChannel = -1;
for (int i = 0; i < kMaxChannels; i++) {
@@ -128,7 +117,7 @@ void Sound::internalPlaySound(int16 resIndex, int16 type, int16 volume, int16 pa
break;
}
}
-
+
// If all channels are in use no new sound will be played
if (freeChannel >= 0) {
Resource *soundResource = _vm->_res->load(resIndex);
@@ -141,19 +130,17 @@ void Sound::internalPlaySound(int16 resIndex, int16 type, int16 volume, int16 pa
channels[freeChannel].type = type;
channels[freeChannel].resIndex = resIndex;
+ channels[freeChannel].volume = volume;
+ channels[freeChannel].panning = panning;
- Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType;
- /*
- switch (type) {
- }
- */
+ Audio::Mixer::SoundType soundType = getScummVMSoundType((SoundChannelType)type);
_vm->_mixer->playStream(soundType, &channels[freeChannel].handle,
- stream, -1, volume, panning);
+ stream, -1, volume, panning);
}
}
-
+
}
void Sound::updateSpeech() {
@@ -170,8 +157,7 @@ void Sound::stopSpeech() {
if (channels[i].type == kChannelTypeSpeech) {
_vm->_mixer->stopHandle(channels[i].handle);
_vm->_screen->keepTalkTextItemsAlive();
- channels[i].type = kChannelTypeEmpty;
- channels[i].resIndex = -1;
+ clearChannel(i);
}
}
}
@@ -180,8 +166,7 @@ void Sound::stopAll() {
for (int i = 0; i < kMaxChannels; i++) {
_vm->_mixer->stopHandle(channels[i].handle);
_vm->_screen->keepTalkTextItemsAlive();
- channels[i].type = kChannelTypeEmpty;
- channels[i].resIndex = -1;
+ clearChannel(i);
}
}
@@ -189,13 +174,22 @@ void Sound::saveState(Common::WriteStream *out) {
for (int i = 0; i < kMaxChannels; i++) {
out->writeSint16LE(channels[i].type);
out->writeSint16LE(channels[i].resIndex);
+ out->writeSint16LE(channels[i].volume);
+ out->writeSint16LE(channels[i].panning);
}
}
-void Sound::loadState(Common::ReadStream *in) {
+void Sound::loadState(Common::ReadStream *in, int version) {
for (int i = 0; i < kMaxChannels; i++) {
channels[i].type = in->readSint16LE();
channels[i].resIndex = in->readSint16LE();
+ if (version < 4) {
+ channels[i].volume = (channels[i].type == kChannelTypeBackground) ? 50 : 100;
+ channels[i].panning = 0;
+ } else {
+ channels[i].volume = in->readSint16LE();
+ channels[i].panning = in->readSint16LE();
+ }
if (channels[i].type != kChannelTypeEmpty) {
Resource *soundResource = _vm->_res->load(channels[i].resIndex);
@@ -206,19 +200,26 @@ void Sound::loadState(Common::ReadStream *in) {
DisposeAfterUse::NO),
channels[i].type == kChannelTypeBackground ? 0 : 1);
- Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType;
- /*
- switch (type) {
- }
- */
-
- // TODO: Volume and panning
- int16 volume = (channels[i].type == kChannelTypeBackground) ? 50 : 100;
+ Audio::Mixer::SoundType soundType = getScummVMSoundType((SoundChannelType)channels[i].type);
_vm->_mixer->playStream(soundType, &channels[i].handle,
- stream, -1, volume, /*panning*/0);
+ stream, -1, channels[i].volume, channels[i].panning);
}
}
}
+Audio::Mixer::SoundType Sound::getScummVMSoundType(SoundChannelType type) const {
+ switch (type) {
+ case kChannelTypeBackground:
+ case kChannelTypeSfx:
+ return Audio::Mixer::kSFXSoundType;
+ case kChannelTypeSpeech:
+ return Audio::Mixer::kSpeechSoundType;
+ break;
+ default:
+ return Audio::Mixer::kSFXSoundType;
+ break;
+ }
+}
+
} // End of namespace Toltecs
diff --git a/engines/toltecs/sound.h b/engines/toltecs/sound.h
index e292d22c0f..48a6cd1318 100644
--- a/engines/toltecs/sound.h
+++ b/engines/toltecs/sound.h
@@ -42,6 +42,8 @@ enum SoundChannelType {
struct SoundChannel {
int16 resIndex;
int16 type;
+ int16 volume;
+ int16 panning;
Audio::SoundHandle handle;
};
@@ -60,15 +62,16 @@ public:
void stopAll();
void saveState(Common::WriteStream *out);
- void loadState(Common::ReadStream *in);
+ void loadState(Common::ReadStream *in, int version);
protected:
ToltecsEngine *_vm;
SoundChannel channels[kMaxChannels];
+ void clearChannel(int channel);
void internalPlaySound(int16 resIndex, int16 type, int16 volume, int16 panning);
-
+ Audio::Mixer::SoundType getScummVMSoundType(SoundChannelType type) const;
};
diff --git a/engines/toltecs/sprite.cpp b/engines/toltecs/sprite.cpp
index 7a02663793..6101eb7d85 100644
--- a/engines/toltecs/sprite.cpp
+++ b/engines/toltecs/sprite.cpp
@@ -199,7 +199,7 @@ bool Screen::createSpriteDrawItem(const DrawRequest &drawRequest, SpriteDrawItem
sprite.frameNum = frameNum;
spriteData = _vm->_res->load(drawRequest.resIndex)->data;
-
+
if (drawRequest.flags & 0x1000) {
sprite.flags |= 4;
}
@@ -207,7 +207,7 @@ bool Screen::createSpriteDrawItem(const DrawRequest &drawRequest, SpriteDrawItem
if (drawRequest.flags & 0x2000) {
sprite.flags |= 0x10;
}
-
+
if (drawRequest.flags & 0x4000) {
sprite.flags |= 0x40;
}
@@ -218,7 +218,7 @@ bool Screen::createSpriteDrawItem(const DrawRequest &drawRequest, SpriteDrawItem
if (spriteFrameEntry.w == 0 || spriteFrameEntry.h == 0)
return false;
-
+
sprite.offset = spriteFrameEntry.offset;
sprite.width = spriteFrameEntry.w;
@@ -263,12 +263,12 @@ bool Screen::createSpriteDrawItem(const DrawRequest &drawRequest, SpriteDrawItem
xoffs -= (xoffs * scaleValue) / 100;
yoffs -= (yoffs * scaleValue) / 100;
}
-
+
}
-
+
sprite.x -= xoffs;
sprite.y -= yoffs;
-
+
sprite.yerror = sprite.ydelta;
// Now we check if the sprite needs to be clipped
@@ -283,7 +283,7 @@ bool Screen::createSpriteDrawItem(const DrawRequest &drawRequest, SpriteDrawItem
sprite.height -= clipHeight;
if (sprite.height <= 0)
return false;
-
+
sprite.y = _vm->_cameraY;
// If the sprite is scaled
@@ -311,7 +311,7 @@ bool Screen::createSpriteDrawItem(const DrawRequest &drawRequest, SpriteDrawItem
}
sprite.yerror = chopHeight;
}
-
+
spriteFrameData = spriteData + sprite.offset;
// Now the sprite's offset is adjusted to point to the starting line
if ((sprite.flags & 0x10) == 0) {
@@ -439,7 +439,7 @@ void Screen::drawSpriteCore(byte *dest, SpriteFilter &reader, const SpriteDrawIt
SpriteReaderStatus status;
PixelPacket packet;
-
+
byte *destp = dest;
int16 skipX = sprite.skipX;
@@ -459,7 +459,7 @@ void Screen::drawSpriteCore(byte *dest, SpriteFilter &reader, const SpriteDrawIt
status = reader.readPacket(packet);
}
}
-
+
if (w - packet.count < 0)
packet.count = w;
diff --git a/engines/toltecs/toltecs.cpp b/engines/toltecs/toltecs.cpp
index 6d6c37dffd..9f3a10a03b 100644
--- a/engines/toltecs/toltecs.cpp
+++ b/engines/toltecs/toltecs.cpp
@@ -62,11 +62,6 @@ struct GameSettings {
};
ToltecsEngine::ToltecsEngine(OSystem *syst, const ToltecsGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {
-
- // Setup mixer
- _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
-
_rnd = new Common::RandomSource("toltecs");
}
@@ -85,7 +80,7 @@ Common::Error ToltecsEngine::run() {
_flag01 = 0;
_saveLoadRequested = 0;
-
+
_cameraX = 0;
_cameraY = 0;
_newCameraX = 0;
@@ -96,7 +91,7 @@ Common::Error ToltecsEngine::run() {
_sceneWidth = 0;
_sceneHeight = 0;
-
+
_doSpeech = true;
_doText = true;
@@ -126,17 +121,27 @@ Common::Error ToltecsEngine::run() {
_moviePlayer = new MoviePlayer(this);
_music = new Music(_arc);
_menuSystem = new MenuSystem(this);
-
+
_sound = new Sound(this);
+ _cfgText = ConfMan.getBool("subtitles");
+ _cfgVoices = !ConfMan.getBool("speech_mute");
+
+ bool mute = false;
+ if (ConfMan.hasKey("mute"))
+ mute = ConfMan.getBool("mute");
+
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, mute ? 0 : ConfMan.getInt("speech_volume"));
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, mute ? 0 : ConfMan.getInt("music_volume"));
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, mute ? 0 : ConfMan.getInt("sfx_volume"));
syncSoundSettings();
CursorMan.showMouse(true);
setupSysStrings();
-//#define TEST_MENU
-#ifdef TEST_MENU
+#if 0
+ // Menu test
_screen->registerFont(0, 0x0D);
_screen->registerFont(1, 0x0E);
_screen->loadMouseCursor(12);
@@ -181,7 +186,7 @@ Common::Error ToltecsEngine::run() {
delete _music;
delete _moviePlayer;
delete _menuSystem;
-
+
delete _sound;
return Common::kNoError;
@@ -245,7 +250,7 @@ void ToltecsEngine::loadScene(uint resIndex) {
_screen->_fullRefresh = true;
_screen->_renderQueue->clear();
-
+
}
void ToltecsEngine::updateScreen() {
@@ -306,6 +311,7 @@ void ToltecsEngine::drawScreen() {
}
_system->updateScreen();
+ _system->delayMillis(10);
updateCamera();
}
@@ -321,15 +327,14 @@ void ToltecsEngine::updateInput() {
//debug("key: flags = %02X; keycode = %d", _keyState.flags, _keyState.keycode);
- // FIXME: This is just for debugging
switch (event.kbd.keycode) {
- case Common::KEYCODE_F7:
- savegame("toltecs.001", "Quicksave");
+ case Common::KEYCODE_F5:
+ showMenu(kMenuIdSave);
break;
- case Common::KEYCODE_F9:
- loadgame("toltecs.001");
+ case Common::KEYCODE_F7:
+ showMenu(kMenuIdLoad);
break;
- case Common::KEYCODE_ESCAPE:
+ case Common::KEYCODE_SPACE:
// Skip current dialog line, if a dialog is active
if (_screen->getTalkTextDuration() > 0) {
_sound->stopSpeech();
@@ -422,7 +427,7 @@ void ToltecsEngine::setCamera(int16 x, int16 y) {
_screen->finishTalkTextItems();
_screen->clearSprites();
-
+
_cameraX = x;
_newCameraX = x;
@@ -491,9 +496,9 @@ void ToltecsEngine::updateCamera() {
}
void ToltecsEngine::talk(int16 slotIndex, int16 slotOffset) {
-
+
byte *scanData = _script->getSlotData(slotIndex) + slotOffset;
-
+
while (*scanData < 0xF0) {
if (*scanData == 0x19) {
scanData++;
@@ -506,7 +511,7 @@ void ToltecsEngine::talk(int16 slotIndex, int16 slotOffset) {
}
scanData++;
}
-
+
if (*scanData == 0xFE) {
if (_doSpeech) {
int16 resIndex = READ_LE_UINT16(scanData + 1);
@@ -540,7 +545,7 @@ void ToltecsEngine::walk(byte *walkData) {
walkInfo.xerror = READ_LE_UINT16(walkData + 14);
walkInfo.mulValue = READ_LE_UINT16(walkData + 16);
walkInfo.scaling = READ_LE_UINT16(walkData + 18);
-
+
walkInfo.scaling = -_segmap->getScalingAtPoint(walkInfo.x, walkInfo.y);
if (walkInfo.y1 < walkInfo.y2)
@@ -548,7 +553,7 @@ void ToltecsEngine::walk(byte *walkData) {
else
ystep = 1;
ydelta = ABS(walkInfo.y1 - walkInfo.y2) * _walkSpeedY;
-
+
if (walkInfo.x1 < walkInfo.x2)
xstep = -1;
else
@@ -611,11 +616,11 @@ void ToltecsEngine::walk(byte *walkData) {
}
-int16 ToltecsEngine::findRectAtPoint(byte *rectData, int16 x, int16 y, int16 index, int16 itemSize,
+int16 ToltecsEngine::findRectAtPoint(byte *rectData, int16 x, int16 y, int16 index, int16 itemSize,
byte *rectDataEnd) {
rectData += index * itemSize;
-
+
while (rectData < rectDataEnd) {
int16 rectY = READ_LE_UINT16(rectData);
if (rectY == -10)
@@ -633,9 +638,32 @@ int16 ToltecsEngine::findRectAtPoint(byte *rectData, int16 x, int16 y, int16 ind
index++;
rectData += itemSize;
}
-
+
return -1;
+}
+
+void ToltecsEngine::showMenu(MenuID menuId) {
+ _screen->loadMouseCursor(12);
+ _palette->loadAddPalette(9, 224);
+ _palette->setDeltaPalette(_palette->getMainPalette(), 7, 0, 31, 224);
+ _screen->finishTalkTextItems();
+ _screen->clearSprites();
+ CursorMan.showMouse(true);
+ _menuSystem->run(menuId);
+ _keyState.reset();
+ _script->setSwitchLocalDataNear(true);
+}
+
+void ToltecsEngine::syncSoundSettings() {
+ Engine::syncSoundSettings();
+
+ bool mute = false;
+ if (ConfMan.hasKey("mute"))
+ mute = ConfMan.getBool("mute");
+ _cfgVoicesVolume = (mute ? 0 : ConfMan.getInt("speech_volume")) * 20 / Audio::Mixer::kMaxChannelVolume;
+ _cfgMusicVolume = (mute ? 0 : ConfMan.getInt("music_volume")) * 20 / Audio::Mixer::kMaxChannelVolume;
+ _cfgSoundFXVolume = (mute ? 0 : ConfMan.getInt("sfx_volume")) * 20 / Audio::Mixer::kMaxChannelVolume;
}
} // End of namespace Toltecs
diff --git a/engines/toltecs/toltecs.h b/engines/toltecs/toltecs.h
index efa1f9d13a..b95a4f77cb 100644
--- a/engines/toltecs/toltecs.h
+++ b/engines/toltecs/toltecs.h
@@ -81,6 +81,14 @@ enum SysString {
kSysStrCount
};
+enum MenuID {
+ kMenuIdNone,
+ kMenuIdMain,
+ kMenuIdSave,
+ kMenuIdLoad,
+ kMenuIdVolumes
+};
+
class ToltecsEngine : public ::Engine {
Common::KeyState _keyPressed;
@@ -99,6 +107,7 @@ public:
uint32 getFeatures() const;
Common::Language getLanguage() const;
const Common::String& getTargetName() const { return _targetName; }
+ void syncSoundSettings();
void setupSysStrings();
void requestSavegame(int slotNum, Common::String &description);
@@ -119,14 +128,18 @@ public:
void scrollCameraLeft(int16 delta);
void scrollCameraRight(int16 delta);
void updateCamera();
-
+
+ void showMenu(MenuID menuId);
+
void talk(int16 slotIndex, int16 slotOffset);
void walk(byte *walkData);
-
- int16 findRectAtPoint(byte *rectData, int16 x, int16 y, int16 index, int16 itemSize,
+
+ int16 findRectAtPoint(byte *rectData, int16 x, int16 y, int16 index, int16 itemSize,
byte *rectDataEnd);
+ int _cfgVoicesVolume, _cfgMusicVolume, _cfgSoundFXVolume;
+ bool _cfgText, _cfgVoices;
public:
AnimationPlayer *_anim;
@@ -150,7 +163,7 @@ public:
uint _sceneResIndex;
int16 _sceneWidth, _sceneHeight;
-
+
int _counter01, _counter02;
bool _movieSceneFlag;
byte _flag01;
@@ -161,7 +174,7 @@ public:
int16 _guiHeight;
bool _doSpeech, _doText;
-
+
int16 _walkSpeedY, _walkSpeedX;
Common::KeyState _keyState;
diff --git a/engines/tony/custom.cpp b/engines/tony/custom.cpp
index f0a9197c6d..23c655e35a 100644
--- a/engines/tony/custom.cpp
+++ b/engines/tony/custom.cpp
@@ -41,7 +41,7 @@
namespace Tony {
-const char *ambianceFile[] = {
+static const char *const kAmbianceFile[] = {
"None",
"1.ADP", // Grilli.WAV
"2.ADP", // Grilli-Ovattati.WAV
@@ -52,66 +52,38 @@ const char *ambianceFile[] = {
"6.ADP" // Mare1.WAV half volume
};
-struct MusicFileEntry {
- const char *name;
- int sync;
-};
-
-const MusicFileEntry musicFiles[] = {
- {"00.ADP", 0}, {"01.ADP", 0},
- {"02.ADP", 0}, {"03.ADP", 0},
- {"04.ADP", 0}, {"05.ADP", 0},
- {"06.ADP", 0}, {"07.ADP", 0},
- {"08.ADP", 2450}, {"09.ADP", 0},
- {"10.ADP", 0}, {"11.ADP", 0},
- {"12.ADP", 0}, {"13.ADP", 0},
- {"14.ADP", 0}, {"15.ADP", 0},
- {"16.ADP", 0}, {"17.ADP", 0},
- {"18.ADP", 0}, {"19.ADP", 0},
- {"20.ADP", 0}, {"21.ADP", 0},
- {"22.ADP", 0}, {"23.ADP", 0},
- {"24.ADP", 0}, {"25.ADP", 0},
- {"26.ADP", 0}, {"27.ADP", 0},
- {"28.ADP", 1670}, {"29.ADP", 0},
- {"30.ADP", 0}, {"31.ADP", 0},
- {"32.ADP", 2900}, {"33.ADP", 0},
- {"34.ADP", 0}, {"35.ADP", 0},
- {"36.ADP", 0}, {"37.ADP", 0},
- {"38.ADP", 0}, {"39.ADP", 0},
- {"40.ADP", 0}, {"41.ADP", 1920},
- {"42.ADP", 1560}, {"43.ADP", 1920},
- {"44.ADP", 1920}, {"45.ADP", 1920},
- {"46.ADP", 1920}, {"47.ADP", 1920},
- {"48.ADP", 1920}, {"49.ADP", 1920},
- {"50.ADP", 1920}, {"51.ADP", 1920},
- {"52.ADP", 1920}, {"53.ADP", 0},
- {"54.ADP", 0}, {"55.ADP", 0},
- {"56.ADP", 0}, {"57.ADP", 0},
- {"58.ADP", 0}, {"59.ADP", 0}
+static const MusicFileEntry kMusicFiles[] = {
+ {"00.ADP", 0}, {"01.ADP", 0}, {"02.ADP", 0}, {"03.ADP", 0},
+ {"04.ADP", 0}, {"05.ADP", 0}, {"06.ADP", 0}, {"07.ADP", 0},
+ {"08.ADP", 2450}, {"09.ADP", 0}, {"10.ADP", 0}, {"11.ADP", 0},
+ {"12.ADP", 0}, {"13.ADP", 0}, {"14.ADP", 0}, {"15.ADP", 0},
+ {"16.ADP", 0}, {"17.ADP", 0}, {"18.ADP", 0}, {"19.ADP", 0},
+ {"20.ADP", 0}, {"21.ADP", 0}, {"22.ADP", 0}, {"23.ADP", 0},
+ {"24.ADP", 0}, {"25.ADP", 0}, {"26.ADP", 0}, {"27.ADP", 0},
+ {"28.ADP", 1670}, {"29.ADP", 0}, {"30.ADP", 0}, {"31.ADP", 0},
+ {"32.ADP", 2900}, {"33.ADP", 0}, {"34.ADP", 0}, {"35.ADP", 0},
+ {"36.ADP", 0}, {"37.ADP", 0}, {"38.ADP", 0}, {"39.ADP", 0},
+ {"40.ADP", 0}, {"41.ADP", 1920}, {"42.ADP", 1560}, {"43.ADP", 1920},
+ {"44.ADP", 1920}, {"45.ADP", 1920}, {"46.ADP", 1920}, {"47.ADP", 1920},
+ {"48.ADP", 1920}, {"49.ADP", 1920}, {"50.ADP", 1920}, {"51.ADP", 1920},
+ {"52.ADP", 1920}, {"53.ADP", 0}, {"54.ADP", 0}, {"55.ADP", 0},
+ {"56.ADP", 0}, {"57.ADP", 0}, {"58.ADP", 0}, {"59.ADP", 0}
};
-const char *jingleFileNames[] = {
- "S00.ADP", "S01.ADP",
- "S02.ADP", "S03.ADP",
- "S04.ADP", "S05.ADP",
- "S06.ADP", "S07.ADP",
- "S08.ADP", "S09.ADP",
- "S10.ADP", "S11.ADP",
- "S12.ADP", "S13.ADP",
- "S14.ADP", "S15.ADP",
- "S16.ADP", "S17.ADP",
- "S18.ADP"
+static const char *const kJingleFileNames[] = {
+ "S00.ADP", "S01.ADP", "S02.ADP", "S03.ADP", "S04.ADP",
+ "S05.ADP", "S06.ADP", "S07.ADP", "S08.ADP", "S09.ADP",
+ "S10.ADP", "S11.ADP", "S12.ADP", "S13.ADP", "S14.ADP",
+ "S15.ADP", "S16.ADP", "S17.ADP", "S18.ADP"
};
-
-void ReapplyChangedHotspot() {
- int i;
- for (i = 0; i < GLOBALS._curChangedHotspot; i++)
+void reapplyChangedHotspot() {
+ for (int i = 0; i < GLOBALS._curChangedHotspot; i++)
GLOBALS._loc->getItemFromCode(GLOBALS._changedHotspot[i]._dwCode)->changeHotspot(RMPoint(GLOBALS._changedHotspot[i]._nX, GLOBALS._changedHotspot[i]._nY));
}
-void SaveChangedHotspot(Common::OutSaveFile *f) {
+void saveChangedHotspot(Common::OutSaveFile *f) {
f->writeByte(GLOBALS._curChangedHotspot);
if (GLOBALS._curChangedHotspot > 0) {
for (int i = 0; i < GLOBALS._curChangedHotspot; ++i)
@@ -119,7 +91,7 @@ void SaveChangedHotspot(Common::OutSaveFile *f) {
}
}
-void LoadChangedHotspot(Common::InSaveFile *f) {
+void loadChangedHotspot(Common::InSaveFile *f) {
GLOBALS._curChangedHotspot = f->readByte();
if (GLOBALS._curChangedHotspot > 0) {
@@ -128,7 +100,6 @@ void LoadChangedHotspot(Common::InSaveFile *f) {
}
}
-
/**
* Classes required for custom functions
*
@@ -139,14 +110,14 @@ void LoadChangedHotspot(Common::InSaveFile *f) {
* AddInventory -> theEngine.AddInventory()
*/
-void MCharResetCodes() {
+void mCharResetCodes() {
for (int i = 0; i < 10; i++)
GLOBALS._mCharacter[i]._item = GLOBALS._loc->getItemFromCode(GLOBALS._mCharacter[i]._code);
for (int i = 0; i < 10; i++)
GLOBALS._character[i]._item = GLOBALS._loc->getItemFromCode(GLOBALS._character[i]._code);
}
-void CharsSaveAll(Common::OutSaveFile *f) {
+void charsSaveAll(Common::OutSaveFile *f) {
for (int i = 0; i < 10; i++) {
f->writeByte(GLOBALS._isMChar[i]);
if (GLOBALS._isMChar[i]) {
@@ -157,7 +128,7 @@ void CharsSaveAll(Common::OutSaveFile *f) {
}
}
-void CharsLoadAll(Common::InSaveFile *f) {
+void charsLoadAll(Common::InSaveFile *f) {
for (int i = 0; i < 10; i++) {
GLOBALS._isMChar[i] = f->readByte();
if (GLOBALS._isMChar[i])
@@ -167,28 +138,28 @@ void CharsLoadAll(Common::InSaveFile *f) {
}
}
-DECLARE_CUSTOM_FUNCTION(FaceToMe)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void faceToMe(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_STANDDOWN);
}
-DECLARE_CUSTOM_FUNCTION(BackToMe)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void backToMe(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_STANDUP);
}
-DECLARE_CUSTOM_FUNCTION(LeftToMe)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void leftToMe(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_STANDLEFT);
}
-DECLARE_CUSTOM_FUNCTION(RightToMe)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void rightToMe(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_STANDRIGHT);
}
-DECLARE_CUSTOM_FUNCTION(TonySetPerorate)(CORO_PARAM, uint32 bStatus, uint32, uint32, uint32) {
+void tonySetPerorate(CORO_PARAM, uint32 bStatus, uint32, uint32, uint32) {
g_vm->getEngine()->setPerorate(bStatus);
}
-DECLARE_CUSTOM_FUNCTION(MySleep)(CORO_PARAM, uint32 dwTime, uint32, uint32, uint32) {
+void mySleep(CORO_PARAM, uint32 dwTime, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
int i;
CORO_END_CONTEXT(_ctx);
@@ -201,12 +172,12 @@ DECLARE_CUSTOM_FUNCTION(MySleep)(CORO_PARAM, uint32 dwTime, uint32, uint32, uint
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(SetAlwaysDisplay)(CORO_PARAM, uint32 val, uint32, uint32, uint32) {
+void setAlwaysDisplay(CORO_PARAM, uint32 val, uint32, uint32, uint32) {
GLOBALS._bAlwaysDisplay = (val != 0);
}
-DECLARE_CUSTOM_FUNCTION(SetPointer)(CORO_PARAM, uint32 dwPointer, uint32, uint32, uint32) {
+void setPointer(CORO_PARAM, uint32 dwPointer, uint32, uint32, uint32) {
switch (dwPointer) {
case 1:
GLOBALS._pointer->setSpecialPointer(GLOBALS._pointer->PTR_ARROWUP);
@@ -230,7 +201,7 @@ DECLARE_CUSTOM_FUNCTION(SetPointer)(CORO_PARAM, uint32 dwPointer, uint32, uint32
}
}
-VoiceHeader *SearchVoiceHeader(uint32 codehi, uint32 codelo) {
+VoiceHeader *searchVoiceHeader(uint32 codehi, uint32 codelo) {
int code = (codehi << 16) | codelo;
if (g_vm->_voices.size() == 0)
@@ -245,7 +216,7 @@ VoiceHeader *SearchVoiceHeader(uint32 codehi, uint32 codelo) {
}
-DECLARE_CUSTOM_FUNCTION(SendTonyMessage)(CORO_PARAM, uint32 dwMessage, uint32 nX, uint32 nY, uint32) {
+void sendTonyMessage(CORO_PARAM, uint32 dwMessage, uint32 nX, uint32 nY, uint32) {
CORO_BEGIN_CONTEXT;
RMMessage msg;
int i;
@@ -266,7 +237,7 @@ DECLARE_CUSTOM_FUNCTION(SendTonyMessage)(CORO_PARAM, uint32 dwMessage, uint32 nX
if (!_ctx->msg.isValid())
return;
- _ctx->curVoc = SearchVoiceHeader(0, dwMessage);
+ _ctx->curVoc = searchVoiceHeader(0, dwMessage);
_ctx->voice = NULL;
if (_ctx->curVoc) {
// Is positioned within the database of entries beginning at the first
@@ -362,12 +333,12 @@ DECLARE_CUSTOM_FUNCTION(SendTonyMessage)(CORO_PARAM, uint32 dwMessage, uint32 nX
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(ChangeBoxStatus)(CORO_PARAM, uint32 nLoc, uint32 nBox, uint32 nStatus, uint32) {
+void changeBoxStatus(CORO_PARAM, uint32 nLoc, uint32 nBox, uint32 nStatus, uint32) {
GLOBALS._boxes->changeBoxStatus(nLoc, nBox, nStatus);
}
-DECLARE_CUSTOM_FUNCTION(CustLoadLocation)(CORO_PARAM, uint32 nLoc, uint32 tX, uint32 tY, uint32 bUseStartPos) {
+void custLoadLocation(CORO_PARAM, uint32 nLoc, uint32 tX, uint32 tY, uint32 bUseStartPos) {
CORO_BEGIN_CONTEXT;
uint32 h;
CORO_END_CONTEXT(_ctx);
@@ -390,7 +361,7 @@ DECLARE_CUSTOM_FUNCTION(CustLoadLocation)(CORO_PARAM, uint32 nLoc, uint32 tX, ui
}
-DECLARE_CUSTOM_FUNCTION(SendFullscreenMsgStart)(CORO_PARAM, uint32 nMsg, uint32 nFont, uint32, uint32) {
+void sendFullscreenMsgStart(CORO_PARAM, uint32 nMsg, uint32 nFont, uint32, uint32) {
CORO_BEGIN_CONTEXT;
RMMessage *msg;
RMGfxClearTask clear;
@@ -449,7 +420,7 @@ DECLARE_CUSTOM_FUNCTION(SendFullscreenMsgStart)(CORO_PARAM, uint32 nMsg, uint32
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(ClearScreen)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void clearScreen(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
char buf[256];
RMGfxClearTask clear;
@@ -469,33 +440,33 @@ DECLARE_CUSTOM_FUNCTION(ClearScreen)(CORO_PARAM, uint32, uint32, uint32, uint32)
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(SendFullscreenMsgEnd)(CORO_PARAM, uint32 bNotEnableTony, uint32, uint32, uint32) {
+void sendFullscreenMsgEnd(CORO_PARAM, uint32 bNotEnableTony, uint32, uint32, uint32) {
g_vm->getEngine()->loadLocation(GLOBALS._fullScreenMessageLoc, RMPoint(GLOBALS._fullScreenMessagePt._x, GLOBALS._fullScreenMessagePt._y), RMPoint(-1, -1));
if (!bNotEnableTony)
GLOBALS._tony->show();
- MCharResetCodes();
- ReapplyChangedHotspot();
+ mCharResetCodes();
+ reapplyChangedHotspot();
}
-DECLARE_CUSTOM_FUNCTION(SendFullscreenMessage)(CORO_PARAM, uint32 nMsg, uint32 nFont, uint32, uint32) {
+void sendFullscreenMessage(CORO_PARAM, uint32 nMsg, uint32 nFont, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
- CORO_INVOKE_4(SendFullscreenMsgStart, nMsg, nFont, 0, 0);
- CORO_INVOKE_4(SendFullscreenMsgEnd, 0, 0, 0, 0);
+ CORO_INVOKE_4(sendFullscreenMsgStart, nMsg, nFont, 0, 0);
+ CORO_INVOKE_4(sendFullscreenMsgEnd, 0, 0, 0, 0);
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(NoBullsEye)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void noBullsEye(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._bNoBullsEye = true;
}
-DECLARE_CUSTOM_FUNCTION(CloseLocation)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void closeLocation(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -515,7 +486,7 @@ DECLARE_CUSTOM_FUNCTION(CloseLocation)(CORO_PARAM, uint32, uint32, uint32, uint3
}
-DECLARE_CUSTOM_FUNCTION(ChangeLocation)(CORO_PARAM, uint32 nLoc, uint32 tX, uint32 tY, uint32 bUseStartPos) {
+void changeLocation(CORO_PARAM, uint32 nLoc, uint32 tX, uint32 tY, uint32 bUseStartPos) {
CORO_BEGIN_CONTEXT;
uint32 h;
CORO_END_CONTEXT(_ctx);
@@ -543,7 +514,7 @@ DECLARE_CUSTOM_FUNCTION(ChangeLocation)(CORO_PARAM, uint32 nLoc, uint32 tX, uint
if (GLOBALS._lastTappeto != GLOBALS._ambiance[nLoc]) {
GLOBALS._lastTappeto = GLOBALS._ambiance[nLoc];
if (GLOBALS._lastTappeto != 0)
- g_vm->playMusic(4, ambianceFile[GLOBALS._lastTappeto], 0, true, 2000);
+ g_vm->playMusic(4, kAmbianceFile[GLOBALS._lastTappeto], 0, true, 2000);
}
if (!GLOBALS._bNoBullsEye) {
@@ -566,51 +537,49 @@ DECLARE_CUSTOM_FUNCTION(ChangeLocation)(CORO_PARAM, uint32 nLoc, uint32 tX, uint
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(SetLocStartPosition)(CORO_PARAM, uint32 nLoc, uint32 lX, uint32 lY, uint32) {
+void setLocStartPosition(CORO_PARAM, uint32 nLoc, uint32 lX, uint32 lY, uint32) {
GLOBALS._startLocPos[nLoc].set(lX, lY);
}
-DECLARE_CUSTOM_FUNCTION(SaveTonyPosition)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void saveTonyPosition(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._saveTonyPos = GLOBALS._tony->position();
GLOBALS._saveTonyLoc = GLOBALS._loc->TEMPGetNumLoc();
}
-DECLARE_CUSTOM_FUNCTION(RestoreTonyPosition)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void restoreTonyPosition(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
- CORO_INVOKE_4(ChangeLocation, GLOBALS._saveTonyLoc, GLOBALS._saveTonyPos._x, GLOBALS._saveTonyPos._y, 0);
+ CORO_INVOKE_4(changeLocation, GLOBALS._saveTonyLoc, GLOBALS._saveTonyPos._x, GLOBALS._saveTonyPos._y, 0);
- MCharResetCodes();
+ mCharResetCodes();
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(DisableInput)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void disableInput(CORO_PARAM, uint32, uint32, uint32, uint32) {
g_vm->getEngine()->disableInput();
}
-DECLARE_CUSTOM_FUNCTION(EnableInput)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void enableInput(CORO_PARAM, uint32, uint32, uint32, uint32) {
g_vm->getEngine()->enableInput();
}
-DECLARE_CUSTOM_FUNCTION(StopTony)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void stopTony(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._tony->stopNoAction(coroParam);
}
-DECLARE_CUSTOM_FUNCTION(CustEnableGUI)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void custEnableGUI(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS.EnableGUI();
}
-DECLARE_CUSTOM_FUNCTION(CustDisableGUI)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void custDisableGUI(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS.DisableGUI();
}
-
-
-void TonyGenericTake1(CORO_PARAM, uint32 nDirection) {
+void tonyGenericTake1(CORO_PARAM, uint32 nDirection) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -624,7 +593,7 @@ void TonyGenericTake1(CORO_PARAM, uint32 nDirection) {
CORO_END_CODE;
}
-void TonyGenericTake2(CORO_PARAM, uint32 nDirection) {
+void tonyGenericTake2(CORO_PARAM, uint32 nDirection) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -640,7 +609,7 @@ void TonyGenericTake2(CORO_PARAM, uint32 nDirection) {
CORO_END_CODE;
}
-void TonyGenericPut1(CORO_PARAM, uint32 nDirection) {
+void tonyGenericPut1(CORO_PARAM, uint32 nDirection) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -654,7 +623,7 @@ void TonyGenericPut1(CORO_PARAM, uint32 nDirection) {
CORO_END_CODE;
}
-void TonyGenericPut2(CORO_PARAM, uint32 nDirection) {
+void tonyGenericPut2(CORO_PARAM, uint32 nDirection) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -671,71 +640,65 @@ void TonyGenericPut2(CORO_PARAM, uint32 nDirection) {
}
-DECLARE_CUSTOM_FUNCTION(TonyTakeUp1)(CORO_PARAM, uint32, uint32, uint32, uint32) {
- TonyGenericTake1(coroParam, 0);
+void tonyTakeUp1(CORO_PARAM, uint32, uint32, uint32, uint32) {
+ tonyGenericTake1(coroParam, 0);
}
-DECLARE_CUSTOM_FUNCTION(TonyTakeMid1)(CORO_PARAM, uint32, uint32, uint32, uint32) {
- TonyGenericTake1(coroParam, 1);
+void tonyTakeMid1(CORO_PARAM, uint32, uint32, uint32, uint32) {
+ tonyGenericTake1(coroParam, 1);
}
-DECLARE_CUSTOM_FUNCTION(TonyTakeDown1)(CORO_PARAM, uint32, uint32, uint32, uint32) {
- TonyGenericTake1(coroParam, 2);
+void tonyTakeDown1(CORO_PARAM, uint32, uint32, uint32, uint32) {
+ tonyGenericTake1(coroParam, 2);
}
-
-
-DECLARE_CUSTOM_FUNCTION(TonyTakeUp2)(CORO_PARAM, uint32, uint32, uint32, uint32) {
- TonyGenericTake2(coroParam, 0);
+void tonyTakeUp2(CORO_PARAM, uint32, uint32, uint32, uint32) {
+ tonyGenericTake2(coroParam, 0);
}
-DECLARE_CUSTOM_FUNCTION(TonyTakeMid2)(CORO_PARAM, uint32, uint32, uint32, uint32) {
- TonyGenericTake2(coroParam, 1);
+void tonyTakeMid2(CORO_PARAM, uint32, uint32, uint32, uint32) {
+ tonyGenericTake2(coroParam, 1);
}
-DECLARE_CUSTOM_FUNCTION(TonyTakeDown2)(CORO_PARAM, uint32, uint32, uint32, uint32) {
- TonyGenericTake2(coroParam, 2);
+void tonyTakeDown2(CORO_PARAM, uint32, uint32, uint32, uint32) {
+ tonyGenericTake2(coroParam, 2);
}
-
-
-DECLARE_CUSTOM_FUNCTION(TonyPutUp1)(CORO_PARAM, uint32, uint32, uint32, uint32) {
- TonyGenericPut1(coroParam, 0);
+void tonyPutUp1(CORO_PARAM, uint32, uint32, uint32, uint32) {
+ tonyGenericPut1(coroParam, 0);
}
-
-DECLARE_CUSTOM_FUNCTION(TonyPutMid1)(CORO_PARAM, uint32, uint32, uint32, uint32) {
- TonyGenericPut1(coroParam, 1);
+void tonyPutMid1(CORO_PARAM, uint32, uint32, uint32, uint32) {
+ tonyGenericPut1(coroParam, 1);
}
-DECLARE_CUSTOM_FUNCTION(TonyPutDown1)(CORO_PARAM, uint32, uint32, uint32, uint32) {
- TonyGenericPut1(coroParam, 2);
+void tonyPutDown1(CORO_PARAM, uint32, uint32, uint32, uint32) {
+ tonyGenericPut1(coroParam, 2);
}
-DECLARE_CUSTOM_FUNCTION(TonyPutUp2)(CORO_PARAM, uint32, uint32, uint32, uint32) {
- TonyGenericPut2(coroParam, 0);
+void tonyPutUp2(CORO_PARAM, uint32, uint32, uint32, uint32) {
+ tonyGenericPut2(coroParam, 0);
}
-
-DECLARE_CUSTOM_FUNCTION(TonyPutMid2)(CORO_PARAM, uint32, uint32, uint32, uint32) {
- TonyGenericPut2(coroParam, 1);
+void tonyPutMid2(CORO_PARAM, uint32, uint32, uint32, uint32) {
+ tonyGenericPut2(coroParam, 1);
}
-DECLARE_CUSTOM_FUNCTION(TonyPutDown2)(CORO_PARAM, uint32, uint32, uint32, uint32) {
- TonyGenericPut2(coroParam, 2);
+void tonyPutDown2(CORO_PARAM, uint32, uint32, uint32, uint32) {
+ tonyGenericPut2(coroParam, 2);
}
-DECLARE_CUSTOM_FUNCTION(TonyOnTheFloor)(CORO_PARAM, uint32 dwParte, uint32, uint32, uint32) {
+void tonyOnTheFloor(CORO_PARAM, uint32 dwParte, uint32, uint32, uint32) {
if (dwParte == 0)
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_ONTHEFLOORLEFT);
else
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_ONTHEFLOORRIGHT);
}
-DECLARE_CUSTOM_FUNCTION(TonyGetUp)(CORO_PARAM, uint32 dwParte, uint32, uint32, uint32) {
+void tonyGetUp(CORO_PARAM, uint32 dwParte, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -752,11 +715,11 @@ DECLARE_CUSTOM_FUNCTION(TonyGetUp)(CORO_PARAM, uint32 dwParte, uint32, uint32, u
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(TonyShepherdess)(CORO_PARAM, uint32 bIsPast, uint32, uint32, uint32) {
+void tonyShepherdess(CORO_PARAM, uint32 bIsPast, uint32, uint32, uint32) {
GLOBALS._tony->setShepherdess(bIsPast);
}
-DECLARE_CUSTOM_FUNCTION(TonyWhistle)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void tonyWhistle(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -771,98 +734,97 @@ DECLARE_CUSTOM_FUNCTION(TonyWhistle)(CORO_PARAM, uint32, uint32, uint32, uint32)
CORO_END_CODE;
}
-
-void TonySetNumTexts(uint32 dwText) {
+void tonySetNumTexts(uint32 dwText) {
GLOBALS._dwTonyNumTexts = dwText;
GLOBALS._bTonyInTexts = false;
}
-DECLARE_CUSTOM_FUNCTION(TonyLaugh)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
- TonySetNumTexts(dwText);
+void tonyLaugh(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
+ tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_LAUGH;
}
-DECLARE_CUSTOM_FUNCTION(TonyGiggle)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
- TonySetNumTexts(dwText);
+void tonyGiggle(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
+ tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_LAUGH2;
}
-DECLARE_CUSTOM_FUNCTION(TonyHips)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
- TonySetNumTexts(dwText);
+void tonyHips(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
+ tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_HIPS;
}
-DECLARE_CUSTOM_FUNCTION(TonySing)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
- TonySetNumTexts(dwText);
+void tonySing(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
+ tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_SING;
}
-DECLARE_CUSTOM_FUNCTION(TonyIndicate)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
- TonySetNumTexts(dwText);
+void tonyIndicate(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
+ tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_INDICATE;
}
-DECLARE_CUSTOM_FUNCTION(TonyScaredWithHands)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
- TonySetNumTexts(dwText);
+void tonyScaredWithHands(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
+ tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_SCARED;
}
-DECLARE_CUSTOM_FUNCTION(TonyScaredWithoutHands)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
- TonySetNumTexts(dwText);
+void tonyScaredWithoutHands(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
+ tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_SCARED2;
}
-DECLARE_CUSTOM_FUNCTION(TonyWithHammer)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
- TonySetNumTexts(dwText);
+void tonyWithHammer(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
+ tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHHAMMER;
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_WITHHAMMER);
}
-DECLARE_CUSTOM_FUNCTION(TonyWithGlasses)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
- TonySetNumTexts(dwText);
+void tonyWithGlasses(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
+ tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHGLASSES;
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_WITHGLASSES);
}
-DECLARE_CUSTOM_FUNCTION(TonyWithWorm)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
- TonySetNumTexts(dwText);
+void tonyWithWorm(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
+ tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHWORM;
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_WITHWORM);
}
-DECLARE_CUSTOM_FUNCTION(TonyWithRope)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
- TonySetNumTexts(dwText);
+void tonyWithRope(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
+ tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHROPE;
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_WITHROPE);
}
-DECLARE_CUSTOM_FUNCTION(TonyWithSecretary)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
- TonySetNumTexts(dwText);
+void tonyWithSecretary(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
+ tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHSECRETARY;
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_WITHSECRETARY);
}
-DECLARE_CUSTOM_FUNCTION(TonyWithRabbitANIM)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
- TonySetNumTexts(dwText);
+void tonyWithRabbitANIM(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
+ tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHRABBIT;
}
-DECLARE_CUSTOM_FUNCTION(TonyWithRecipeANIM)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
- TonySetNumTexts(dwText);
+void tonyWithRecipeANIM(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
+ tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHRECIPE;
}
-DECLARE_CUSTOM_FUNCTION(TonyWithCardsANIM)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
- TonySetNumTexts(dwText);
+void tonyWithCardsANIM(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
+ tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHCARDS;
}
-DECLARE_CUSTOM_FUNCTION(TonyWithSnowmanANIM)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
- TonySetNumTexts(dwText);
+void tonyWithSnowmanANIM(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
+ tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_WITHSNOWMAN;
}
-DECLARE_CUSTOM_FUNCTION(TonyWithSnowmanStart)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void tonyWithSnowmanStart(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -875,7 +837,7 @@ DECLARE_CUSTOM_FUNCTION(TonyWithSnowmanStart)(CORO_PARAM, uint32, uint32, uint32
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(TonyWithSnowmanEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void tonyWithSnowmanEnd(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -888,7 +850,7 @@ DECLARE_CUSTOM_FUNCTION(TonyWithSnowmanEnd)(CORO_PARAM, uint32, uint32, uint32,
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(TonyWithRabbitStart)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void tonyWithRabbitStart(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -901,7 +863,7 @@ DECLARE_CUSTOM_FUNCTION(TonyWithRabbitStart)(CORO_PARAM, uint32, uint32, uint32,
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(TonyWithRabbitEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void tonyWithRabbitEnd(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -914,7 +876,7 @@ DECLARE_CUSTOM_FUNCTION(TonyWithRabbitEnd)(CORO_PARAM, uint32, uint32, uint32, u
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(TonyWithRecipeStart)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void tonyWithRecipeStart(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -927,7 +889,7 @@ DECLARE_CUSTOM_FUNCTION(TonyWithRecipeStart)(CORO_PARAM, uint32, uint32, uint32,
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(TonyWithRecipeEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void tonyWithRecipeEnd(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -940,7 +902,7 @@ DECLARE_CUSTOM_FUNCTION(TonyWithRecipeEnd)(CORO_PARAM, uint32, uint32, uint32, u
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(TonyWithCardsStart)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void tonyWithCardsStart(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -953,7 +915,7 @@ DECLARE_CUSTOM_FUNCTION(TonyWithCardsStart)(CORO_PARAM, uint32, uint32, uint32,
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(TonyWithCardsEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void tonyWithCardsEnd(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -966,7 +928,7 @@ DECLARE_CUSTOM_FUNCTION(TonyWithCardsEnd)(CORO_PARAM, uint32, uint32, uint32, ui
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(TonyWithNotebookStart)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void tonyWithNotebookStart(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -979,7 +941,7 @@ DECLARE_CUSTOM_FUNCTION(TonyWithNotebookStart)(CORO_PARAM, uint32, uint32, uint3
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(TonyWithNotebookEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void tonyWithNotebookEnd(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -992,7 +954,7 @@ DECLARE_CUSTOM_FUNCTION(TonyWithNotebookEnd)(CORO_PARAM, uint32, uint32, uint32,
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(TonyWithMegaphoneStart)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void tonyWithMegaphoneStart(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -1005,7 +967,7 @@ DECLARE_CUSTOM_FUNCTION(TonyWithMegaphoneStart)(CORO_PARAM, uint32, uint32, uint
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(TonyWithMegaphoneEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void tonyWithMegaphoneEnd(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -1018,7 +980,7 @@ DECLARE_CUSTOM_FUNCTION(TonyWithMegaphoneEnd)(CORO_PARAM, uint32, uint32, uint32
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(TonyWithBeardStart)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void tonyWithBeardStart(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -1031,7 +993,7 @@ DECLARE_CUSTOM_FUNCTION(TonyWithBeardStart)(CORO_PARAM, uint32, uint32, uint32,
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(TonyWithBeardEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void tonyWithBeardEnd(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -1044,7 +1006,7 @@ DECLARE_CUSTOM_FUNCTION(TonyWithBeardEnd)(CORO_PARAM, uint32, uint32, uint32, ui
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(TonyScaredStart)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void tonyScaredStart(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -1057,7 +1019,7 @@ DECLARE_CUSTOM_FUNCTION(TonyScaredStart)(CORO_PARAM, uint32, uint32, uint32, uin
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(TonyScaredEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void tonyScaredEnd(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -1071,12 +1033,12 @@ DECLARE_CUSTOM_FUNCTION(TonyScaredEnd)(CORO_PARAM, uint32, uint32, uint32, uint3
}
-DECLARE_CUSTOM_FUNCTION(TonyDisgusted)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
- TonySetNumTexts(dwText);
+void tonyDisgusted(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
+ tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_DISGUSTED;
}
-DECLARE_CUSTOM_FUNCTION(TonySniffLeft)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void tonySniffLeft(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -1084,12 +1046,12 @@ DECLARE_CUSTOM_FUNCTION(TonySniffLeft)(CORO_PARAM, uint32, uint32, uint32, uint3
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_SNIFF_LEFT);
CORO_INVOKE_0(GLOBALS._tony->waitForEndPattern);
- CORO_INVOKE_4(LeftToMe, 0, 0, 0, 0);
+ CORO_INVOKE_4(leftToMe, 0, 0, 0, 0);
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(TonySniffRight)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void tonySniffRight(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -1097,17 +1059,17 @@ DECLARE_CUSTOM_FUNCTION(TonySniffRight)(CORO_PARAM, uint32, uint32, uint32, uint
GLOBALS._tony->setPattern(GLOBALS._tony->PAT_SNIFF_RIGHT);
CORO_INVOKE_0(GLOBALS._tony->waitForEndPattern);
- CORO_INVOKE_4(RightToMe, 0, 0, 0, 0);
+ CORO_INVOKE_4(rightToMe, 0, 0, 0, 0);
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(TonySarcastic)(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
- TonySetNumTexts(dwText);
+void tonySarcastic(CORO_PARAM, uint32 dwText, uint32, uint32, uint32) {
+ tonySetNumTexts(dwText);
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_SARCASTIC;
}
-DECLARE_CUSTOM_FUNCTION(TonyMacbeth)(CORO_PARAM, uint32 nPos, uint32, uint32, uint32) {
+void tonyMacbeth(CORO_PARAM, uint32 nPos, uint32, uint32, uint32) {
switch (nPos) {
case 1:
GLOBALS._nTonyNextTalkType = GLOBALS._tony->TALK_MACBETH1;
@@ -1140,15 +1102,15 @@ DECLARE_CUSTOM_FUNCTION(TonyMacbeth)(CORO_PARAM, uint32 nPos, uint32, uint32, ui
}
-DECLARE_CUSTOM_FUNCTION(EnableTony)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void enableTony(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._tony->show();
}
-DECLARE_CUSTOM_FUNCTION(DisableTony)(CORO_PARAM, uint32 bShowShadow, uint32, uint32, uint32) {
+void disableTony(CORO_PARAM, uint32 bShowShadow, uint32, uint32, uint32) {
GLOBALS._tony->hide(bShowShadow);
}
-DECLARE_CUSTOM_FUNCTION(WaitForPatternEnd)(CORO_PARAM, uint32 nItem, uint32, uint32, uint32) {
+void waitForPatternEnd(CORO_PARAM, uint32 nItem, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
RMItem *item;
CORO_END_CONTEXT(_ctx);
@@ -1164,11 +1126,11 @@ DECLARE_CUSTOM_FUNCTION(WaitForPatternEnd)(CORO_PARAM, uint32 nItem, uint32, uin
}
-DECLARE_CUSTOM_FUNCTION(SetTonyPosition)(CORO_PARAM, uint32 nX, uint32 nY, uint32 nLoc, uint32) {
+void setTonyPosition(CORO_PARAM, uint32 nX, uint32 nY, uint32 nLoc, uint32) {
GLOBALS._tony->setPosition(RMPoint(nX, nY), nLoc);
}
-DECLARE_CUSTOM_FUNCTION(MoveTonyAndWait)(CORO_PARAM, uint32 nX, uint32 nY, uint32, uint32) {
+void moveTonyAndWait(CORO_PARAM, uint32 nX, uint32 nY, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -1187,11 +1149,11 @@ DECLARE_CUSTOM_FUNCTION(MoveTonyAndWait)(CORO_PARAM, uint32 nX, uint32 nY, uint3
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(MoveTony)(CORO_PARAM, uint32 nX, uint32 nY, uint32, uint32) {
+void moveTony(CORO_PARAM, uint32 nX, uint32 nY, uint32, uint32) {
GLOBALS._tony->move(coroParam, RMPoint(nX, nY));
}
-DECLARE_CUSTOM_FUNCTION(ScrollLocation)(CORO_PARAM, uint32 nX, uint32 nY, uint32 sX, uint32 sY) {
+void scrollLocation(CORO_PARAM, uint32 nX, uint32 nY, uint32 sX, uint32 sY) {
CORO_BEGIN_CONTEXT;
int lx, ly;
RMPoint pt;
@@ -1239,7 +1201,7 @@ DECLARE_CUSTOM_FUNCTION(ScrollLocation)(CORO_PARAM, uint32 nX, uint32 nY, uint32
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(SyncScrollLocation)(CORO_PARAM, uint32 nX, uint32 nY, uint32 sX, uint32 sY) {
+void syncScrollLocation(CORO_PARAM, uint32 nX, uint32 nY, uint32 sX, uint32 sY) {
CORO_BEGIN_CONTEXT;
int lx, ly;
RMPoint pt, startpt;
@@ -1321,7 +1283,7 @@ DECLARE_CUSTOM_FUNCTION(SyncScrollLocation)(CORO_PARAM, uint32 nX, uint32 nY, ui
}
-DECLARE_CUSTOM_FUNCTION(ChangeHotspot)(CORO_PARAM, uint32 dwCode, uint32 nX, uint32 nY, uint32) {
+void changeHotspot(CORO_PARAM, uint32 dwCode, uint32 nX, uint32 nY, uint32) {
int i;
for (i = 0; i < GLOBALS._curChangedHotspot; i++) {
@@ -1343,15 +1305,15 @@ DECLARE_CUSTOM_FUNCTION(ChangeHotspot)(CORO_PARAM, uint32 dwCode, uint32 nX, uin
}
-DECLARE_CUSTOM_FUNCTION(AutoSave)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void autoSave(CORO_PARAM, uint32, uint32, uint32, uint32) {
g_vm->autoSave(coroParam);
}
-DECLARE_CUSTOM_FUNCTION(AbortGame)(CORO_PARAM, uint32, uint32, uint32, uint32) {
- g_vm->abortGame();
+void abortGame(CORO_PARAM, uint32, uint32, uint32, uint32) {
+ error("script called abortGame");
}
-DECLARE_CUSTOM_FUNCTION(ShakeScreen)(CORO_PARAM, uint32 nScosse, uint32, uint32, uint32) {
+void shakeScreen(CORO_PARAM, uint32 nScosse, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
uint32 i;
uint32 curTime;
@@ -1389,7 +1351,7 @@ DECLARE_CUSTOM_FUNCTION(ShakeScreen)(CORO_PARAM, uint32 nScosse, uint32, uint32,
* Characters
*/
-DECLARE_CUSTOM_FUNCTION(CharSetCode)(CORO_PARAM, uint32 nChar, uint32 nCode, uint32, uint32) {
+void charSetCode(CORO_PARAM, uint32 nChar, uint32 nCode, uint32, uint32) {
assert(nChar < 16);
GLOBALS._character[nChar]._code = nCode;
GLOBALS._character[nChar]._item = GLOBALS._loc->getItemFromCode(nCode);
@@ -1404,26 +1366,26 @@ DECLARE_CUSTOM_FUNCTION(CharSetCode)(CORO_PARAM, uint32 nChar, uint32 nCode, uin
GLOBALS._isMChar[nChar] = false;
}
-DECLARE_CUSTOM_FUNCTION(CharSetColor)(CORO_PARAM, uint32 nChar, uint32 r, uint32 g, uint32 b) {
+void charSetColor(CORO_PARAM, uint32 nChar, uint32 r, uint32 g, uint32 b) {
assert(nChar < 16);
GLOBALS._character[nChar]._r = r;
GLOBALS._character[nChar]._g = g;
GLOBALS._character[nChar]._b = b;
}
-DECLARE_CUSTOM_FUNCTION(CharSetTalkPattern)(CORO_PARAM, uint32 nChar, uint32 tp, uint32 sp, uint32) {
+void charSetTalkPattern(CORO_PARAM, uint32 nChar, uint32 tp, uint32 sp, uint32) {
assert(nChar < 16);
GLOBALS._character[nChar]._talkPattern = tp;
GLOBALS._character[nChar]._standPattern = sp;
}
-DECLARE_CUSTOM_FUNCTION(CharSetStartEndTalkPattern)(CORO_PARAM, uint32 nChar, uint32 sp, uint32 ep, uint32) {
+void charSetStartEndTalkPattern(CORO_PARAM, uint32 nChar, uint32 sp, uint32 ep, uint32) {
assert(nChar < 16);
GLOBALS._character[nChar]._startTalkPattern = sp;
GLOBALS._character[nChar]._endTalkPattern = ep;
}
-DECLARE_CUSTOM_FUNCTION(CharSendMessage)(CORO_PARAM, uint32 nChar, uint32 dwMessage, uint32 bIsBack, uint32) {
+void charSendMessage(CORO_PARAM, uint32 nChar, uint32 dwMessage, uint32 bIsBack, uint32) {
CORO_BEGIN_CONTEXT;
RMMessage *msg;
int i;
@@ -1450,7 +1412,7 @@ DECLARE_CUSTOM_FUNCTION(CharSendMessage)(CORO_PARAM, uint32 nChar, uint32 dwMess
GLOBALS._character[nChar]._item->setPattern(GLOBALS._character[nChar]._talkPattern);
- _ctx->curVoc = SearchVoiceHeader(0, dwMessage);
+ _ctx->curVoc = searchVoiceHeader(0, dwMessage);
_ctx->voice = NULL;
if (_ctx->curVoc) {
// Position within the database of entries, beginning at the first
@@ -1530,15 +1492,15 @@ DECLARE_CUSTOM_FUNCTION(CharSendMessage)(CORO_PARAM, uint32 nChar, uint32 dwMess
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(AddInventory)(CORO_PARAM, uint32 dwCode, uint32, uint32, uint32) {
+void addInventory(CORO_PARAM, uint32 dwCode, uint32, uint32, uint32) {
GLOBALS._inventory->addItem(dwCode);
}
-DECLARE_CUSTOM_FUNCTION(RemoveInventory)(CORO_PARAM, uint32 dwCode, uint32, uint32, uint32) {
+void removeInventory(CORO_PARAM, uint32 dwCode, uint32, uint32, uint32) {
GLOBALS._inventory->removeItem(dwCode);
}
-DECLARE_CUSTOM_FUNCTION(ChangeInventoryStatus)(CORO_PARAM, uint32 dwCode, uint32 dwStatus, uint32, uint32) {
+void changeInventoryStatus(CORO_PARAM, uint32 dwCode, uint32 dwStatus, uint32, uint32) {
GLOBALS._inventory->changeItemStatus(dwCode, dwStatus);
}
@@ -1547,7 +1509,7 @@ DECLARE_CUSTOM_FUNCTION(ChangeInventoryStatus)(CORO_PARAM, uint32 dwCode, uint32
* Master Characters
*/
-DECLARE_CUSTOM_FUNCTION(MCharSetCode)(CORO_PARAM, uint32 nChar, uint32 nCode, uint32, uint32) {
+void mCharSetCode(CORO_PARAM, uint32 nChar, uint32 nCode, uint32, uint32) {
assert(nChar < 10);
GLOBALS._mCharacter[nChar]._code = nCode;
if (nCode == 0)
@@ -1569,56 +1531,52 @@ DECLARE_CUSTOM_FUNCTION(MCharSetCode)(CORO_PARAM, uint32 nChar, uint32 nCode, ui
GLOBALS._isMChar[nChar] = true;
}
-DECLARE_CUSTOM_FUNCTION(MCharResetCode)(CORO_PARAM, uint32 nChar, uint32, uint32, uint32) {
+void mCharResetCode(CORO_PARAM, uint32 nChar, uint32, uint32, uint32) {
GLOBALS._mCharacter[nChar]._item = GLOBALS._loc->getItemFromCode(GLOBALS._mCharacter[nChar]._code);
}
-DECLARE_CUSTOM_FUNCTION(MCharSetPosition)(CORO_PARAM, uint32 nChar, uint32 nX, uint32 nY, uint32) {
+void mCharSetPosition(CORO_PARAM, uint32 nChar, uint32 nX, uint32 nY, uint32) {
assert(nChar < 10);
GLOBALS._mCharacter[nChar]._x = nX;
GLOBALS._mCharacter[nChar]._y = nY;
}
-
-DECLARE_CUSTOM_FUNCTION(MCharSetColor)(CORO_PARAM, uint32 nChar, uint32 r, uint32 g, uint32 b) {
+void mCharSetColor(CORO_PARAM, uint32 nChar, uint32 r, uint32 g, uint32 b) {
assert(nChar < 10);
GLOBALS._mCharacter[nChar]._r = r;
GLOBALS._mCharacter[nChar]._g = g;
GLOBALS._mCharacter[nChar]._b = b;
}
-
-DECLARE_CUSTOM_FUNCTION(MCharSetNumTalksInGroup)(CORO_PARAM, uint32 nChar, uint32 nGroup, uint32 nTalks, uint32) {
+void mCharSetNumTalksInGroup(CORO_PARAM, uint32 nChar, uint32 nGroup, uint32 nTalks, uint32) {
assert(nChar < 10);
assert(nGroup < 10);
GLOBALS._mCharacter[nChar]._numTalks[nGroup] = nTalks;
}
-
-DECLARE_CUSTOM_FUNCTION(MCharSetCurrentGroup)(CORO_PARAM, uint32 nChar, uint32 nGroup, uint32, uint32) {
+void mCharSetCurrentGroup(CORO_PARAM, uint32 nChar, uint32 nGroup, uint32, uint32) {
assert(nChar < 10);
assert(nGroup < 10);
GLOBALS._mCharacter[nChar]._curGroup = nGroup;
}
-DECLARE_CUSTOM_FUNCTION(MCharSetNumTexts)(CORO_PARAM, uint32 nChar, uint32 nTexts, uint32, uint32) {
+void mCharSetNumTexts(CORO_PARAM, uint32 nChar, uint32 nTexts, uint32, uint32) {
assert(nChar < 10);
GLOBALS._mCharacter[nChar]._numTexts = nTexts - 1;
GLOBALS._mCharacter[nChar]._bInTexts = false;
}
-DECLARE_CUSTOM_FUNCTION(MCharSetAlwaysBack)(CORO_PARAM, uint32 nChar, uint32 bAlwaysBack, uint32, uint32) {
+void mCharSetAlwaysBack(CORO_PARAM, uint32 nChar, uint32 bAlwaysBack, uint32, uint32) {
assert(nChar < 10);
GLOBALS._mCharacter[nChar]._bAlwaysBack = bAlwaysBack;
}
-
-DECLARE_CUSTOM_FUNCTION(MCharSendMessage)(CORO_PARAM, uint32 nChar, uint32 dwMessage, uint32 bIsBack, uint32 nFont) {
+void mCharSendMessage(CORO_PARAM, uint32 nChar, uint32 dwMessage, uint32 bIsBack, uint32 nFont) {
CORO_BEGIN_CONTEXT;
RMMessage *msg;
int i;
@@ -1658,11 +1616,10 @@ DECLARE_CUSTOM_FUNCTION(MCharSendMessage)(CORO_PARAM, uint32 nChar, uint32 dwMes
}
}
- _ctx->curVoc = SearchVoiceHeader(0, dwMessage);
+ _ctx->curVoc = searchVoiceHeader(0, dwMessage);
_ctx->voice = NULL;
if (_ctx->curVoc) {
// Position within the database of entries, beginning at the first
- // fseek(g_vm->m_vdbFP, curVoc->offset, SEEK_SET);
g_vm->_vdbFP.seek(_ctx->curVoc->_offset);
_ctx->curOffset = _ctx->curVoc->_offset;
}
@@ -1744,9 +1701,7 @@ DECLARE_CUSTOM_FUNCTION(MCharSendMessage)(CORO_PARAM, uint32 nChar, uint32 dwMes
* Dialogs
*/
-int g_curDialog;
-
-DECLARE_CUSTOM_FUNCTION(SendDialogMessage)(CORO_PARAM, uint32 nPers, uint32 nMsg, uint32, uint32) {
+void sendDialogMessage(CORO_PARAM, uint32 nPers, uint32 nMsg, uint32, uint32) {
CORO_BEGIN_CONTEXT;
char *string;
RMTextDialog *text;
@@ -1766,7 +1721,7 @@ DECLARE_CUSTOM_FUNCTION(SendDialogMessage)(CORO_PARAM, uint32 nPers, uint32 nMsg
if (nPers != 0 && GLOBALS._isMChar[nPers] && GLOBALS._mCharacter[nPers]._bAlwaysBack)
_ctx->bIsBack = true;
- _ctx->curVoc = SearchVoiceHeader(g_curDialog, nMsg);
+ _ctx->curVoc = searchVoiceHeader(GLOBALS._curDialog, nMsg);
_ctx->voice = NULL;
if (_ctx->curVoc) {
@@ -1927,7 +1882,7 @@ DECLARE_CUSTOM_FUNCTION(SendDialogMessage)(CORO_PARAM, uint32 nPers, uint32 nMsg
// @@@@ This cannot be skipped!!!!!!!!!!!!!!!!!!!
-DECLARE_CUSTOM_FUNCTION(StartDialog)(CORO_PARAM, uint32 nDialog, uint32 nStartGroup, uint32, uint32) {
+void startDialog(CORO_PARAM, uint32 nDialog, uint32 nStartGroup, uint32, uint32) {
CORO_BEGIN_CONTEXT;
uint32 nChoice;
uint32 *sl;
@@ -1939,7 +1894,7 @@ DECLARE_CUSTOM_FUNCTION(StartDialog)(CORO_PARAM, uint32 nDialog, uint32 nStartGr
CORO_BEGIN_CODE(_ctx);
- g_curDialog = nDialog;
+ GLOBALS._curDialog = nDialog;
// Call MPAL to start the dialog
mpalQueryDoDialog(nDialog, nStartGroup);
@@ -2010,7 +1965,7 @@ DECLARE_CUSTOM_FUNCTION(StartDialog)(CORO_PARAM, uint32 nDialog, uint32 nStartGr
* Sync between idle and mpal
*/
-DECLARE_CUSTOM_FUNCTION(TakeOwnership)(CORO_PARAM, uint32 num, uint32, uint32, uint32) {
+void takeOwnership(CORO_PARAM, uint32 num, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -2028,14 +1983,16 @@ DECLARE_CUSTOM_FUNCTION(TakeOwnership)(CORO_PARAM, uint32 num, uint32, uint32, u
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(ReleaseOwnership)(CORO_PARAM, uint32 num, uint32, uint32, uint32) {
+void releaseOwnership(CORO_PARAM, uint32 num, uint32, uint32, uint32) {
if (!GLOBALS._mut[num]._lockCount) {
warning("ReleaseOwnership tried to release mutex %d, which isn't held", num);
return;
}
- if (GLOBALS._mut[num]._ownerPid != (uint32)CoroScheduler.getCurrentPID())
- error("ReleaseOwnership tried to release mutex %d, which is held by a different process", num);
+ if (GLOBALS._mut[num]._ownerPid != (uint32)CoroScheduler.getCurrentPID()) {
+ warning("ReleaseOwnership tried to release mutex %d, which is held by a different process", num);
+ return;
+ }
GLOBALS._mut[num]._lockCount--;
if (!GLOBALS._mut[num]._lockCount) {
@@ -2058,7 +2015,7 @@ DECLARE_CUSTOM_FUNCTION(ReleaseOwnership)(CORO_PARAM, uint32 num, uint32, uint32
*
*/
-void ThreadFadeInMusic(CORO_PARAM, const void *nMusic) {
+void threadFadeInMusic(CORO_PARAM, const void *nMusic) {
CORO_BEGIN_CONTEXT;
int i;
CORO_END_CONTEXT(_ctx);
@@ -2067,7 +2024,7 @@ void ThreadFadeInMusic(CORO_PARAM, const void *nMusic) {
CORO_BEGIN_CODE(_ctx);
- debug("Start FadeIn Music");
+ debugC(DEBUG_INTERMEDIATE, kTonyDebugSound, "Start FadeIn Music");
for (_ctx->i = 0; _ctx->i < 16; _ctx->i++) {
g_vm->setMusicVolume(nChannel, _ctx->i * 4);
@@ -2076,14 +2033,14 @@ void ThreadFadeInMusic(CORO_PARAM, const void *nMusic) {
}
g_vm->setMusicVolume(nChannel, 64);
- debug("End FadeIn Music");
+ debugC(DEBUG_INTERMEDIATE, kTonyDebugSound, "End FadeIn Music");
CORO_KILL_SELF();
CORO_END_CODE;
}
-void ThreadFadeOutMusic(CORO_PARAM, const void *nMusic) {
+void threadFadeOutMusic(CORO_PARAM, const void *nMusic) {
CORO_BEGIN_CONTEXT;
int i;
int startVolume;
@@ -2114,52 +2071,52 @@ void ThreadFadeOutMusic(CORO_PARAM, const void *nMusic) {
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(FadeInSoundEffect)(CORO_PARAM, uint32, uint32, uint32, uint32) {
- CoroScheduler.createProcess(ThreadFadeInMusic, &GLOBALS._curSoundEffect, sizeof(int));
+void fadeInSoundEffect(CORO_PARAM, uint32, uint32, uint32, uint32) {
+ CoroScheduler.createProcess(threadFadeInMusic, &GLOBALS._curSoundEffect, sizeof(int));
}
-DECLARE_CUSTOM_FUNCTION(FadeOutSoundEffect)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void fadeOutSoundEffect(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._bFadeOutStop = false;
- CoroScheduler.createProcess(ThreadFadeOutMusic, &GLOBALS._curSoundEffect, sizeof(int));
+ CoroScheduler.createProcess(threadFadeOutMusic, &GLOBALS._curSoundEffect, sizeof(int));
}
-DECLARE_CUSTOM_FUNCTION(FadeOutJingle)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void fadeOutJingle(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._bFadeOutStop = false;
int channel = 2;
- CoroScheduler.createProcess(ThreadFadeOutMusic, &channel, sizeof(int));
+ CoroScheduler.createProcess(threadFadeOutMusic, &channel, sizeof(int));
}
-DECLARE_CUSTOM_FUNCTION(FadeInJingle)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void fadeInJingle(CORO_PARAM, uint32, uint32, uint32, uint32) {
int channel = 2;
- CoroScheduler.createProcess(ThreadFadeInMusic, &channel, sizeof(int));
+ CoroScheduler.createProcess(threadFadeInMusic, &channel, sizeof(int));
}
-DECLARE_CUSTOM_FUNCTION(StopSoundEffect)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void stopSoundEffect(CORO_PARAM, uint32, uint32, uint32, uint32) {
g_vm->stopMusic(GLOBALS._curSoundEffect);
}
-DECLARE_CUSTOM_FUNCTION(StopJingle)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void stopJingle(CORO_PARAM, uint32, uint32, uint32, uint32) {
g_vm->stopMusic(2);
}
-DECLARE_CUSTOM_FUNCTION(MuteSoundEffect)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void muteSoundEffect(CORO_PARAM, uint32, uint32, uint32, uint32) {
g_vm->setMusicVolume(GLOBALS._curSoundEffect, 0);
}
-DECLARE_CUSTOM_FUNCTION(DemuteSoundEffect)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void demuteSoundEffect(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._bFadeOutStop = true;
g_vm->setMusicVolume(GLOBALS._curSoundEffect, 64);
}
-DECLARE_CUSTOM_FUNCTION(MuteJingle)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void muteJingle(CORO_PARAM, uint32, uint32, uint32, uint32) {
g_vm->setMusicVolume(2, 0);
}
-DECLARE_CUSTOM_FUNCTION(DemuteJingle)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void demuteJingle(CORO_PARAM, uint32, uint32, uint32, uint32) {
g_vm->setMusicVolume(2, 64);
}
-void CustPlayMusic(uint32 nChannel, const char *mFN, uint32 nFX, bool bLoop, int nSync = 0) {
+void custPlayMusic(uint32 nChannel, const char *mFN, uint32 nFX, bool bLoop, int nSync = 0) {
if (nSync == 0)
nSync = 2000;
debugC(DEBUG_INTERMEDIATE, kTonyDebugMusic, "Start CustPlayMusic");
@@ -2167,21 +2124,21 @@ void CustPlayMusic(uint32 nChannel, const char *mFN, uint32 nFX, bool bLoop, int
debugC(DEBUG_INTERMEDIATE, kTonyDebugMusic, "End CustPlayMusic");
}
-DECLARE_CUSTOM_FUNCTION(PlaySoundEffect)(CORO_PARAM, uint32 nMusic, uint32 nFX, uint32 bNoLoop, uint32) {
+void playSoundEffect(CORO_PARAM, uint32 nMusic, uint32 nFX, uint32 bNoLoop, uint32) {
if (nFX == 0 || nFX == 1 || nFX == 2) {
debugC(DEBUG_INTERMEDIATE, kTonyDebugSound, "PlaySoundEffect stop fadeout");
GLOBALS._bFadeOutStop = true;
}
GLOBALS._lastMusic = nMusic;
- CustPlayMusic(GLOBALS._curSoundEffect, musicFiles[nMusic].name, nFX, bNoLoop ? false : true, musicFiles[nMusic].sync);
+ custPlayMusic(GLOBALS._curSoundEffect, kMusicFiles[nMusic]._name, nFX, bNoLoop ? false : true, kMusicFiles[nMusic]._sync);
}
-DECLARE_CUSTOM_FUNCTION(PlayJingle)(CORO_PARAM, uint32 nMusic, uint32 nFX, uint32 bLoop, uint32) {
- CustPlayMusic(2, jingleFileNames[nMusic], nFX, bLoop);
+void playJingle(CORO_PARAM, uint32 nMusic, uint32 nFX, uint32 bLoop, uint32) {
+ custPlayMusic(2, kJingleFileNames[nMusic], nFX, bLoop);
}
-DECLARE_CUSTOM_FUNCTION(PlayItemSfx)(CORO_PARAM, uint32 nItem, uint32 nSFX, uint32, uint32) {
+void playItemSfx(CORO_PARAM, uint32 nItem, uint32 nSFX, uint32, uint32) {
if (nItem == 0) {
GLOBALS._tony->playSfx(nSFX);
} else {
@@ -2191,76 +2148,71 @@ DECLARE_CUSTOM_FUNCTION(PlayItemSfx)(CORO_PARAM, uint32 nItem, uint32 nSFX, uint
}
}
-
-void RestoreMusic(CORO_PARAM) {
+void restoreMusic(CORO_PARAM) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
- CORO_INVOKE_4(PlaySoundEffect, GLOBALS._lastMusic, 0, 0, 0);
+ CORO_INVOKE_4(playSoundEffect, GLOBALS._lastMusic, 0, 0, 0);
if (GLOBALS._lastTappeto != 0)
- CustPlayMusic(4, ambianceFile[GLOBALS._lastTappeto], 0, true);
+ custPlayMusic(4, kAmbianceFile[GLOBALS._lastTappeto], 0, true);
CORO_END_CODE;
}
-void SaveMusic(Common::OutSaveFile *f) {
+void saveMusic(Common::OutSaveFile *f) {
f->writeByte(GLOBALS._lastMusic);
f->writeByte(GLOBALS._lastTappeto);
}
-void LoadMusic(Common::InSaveFile *f) {
+void loadMusic(Common::InSaveFile *f) {
GLOBALS._lastMusic = f->readByte();
GLOBALS._lastTappeto = f->readByte();
}
-
-DECLARE_CUSTOM_FUNCTION(JingleFadeStart)(CORO_PARAM, uint32 nJingle, uint32 bLoop, uint32, uint32) {
+void jingleFadeStart(CORO_PARAM, uint32 nJingle, uint32 bLoop, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
- CORO_INVOKE_4(FadeOutSoundEffect, 0, 0, 0, 0);
- CORO_INVOKE_4(MuteJingle, 0, 0, 0, 0);
- CORO_INVOKE_4(PlayJingle, nJingle, 0, bLoop, 0);
- CORO_INVOKE_4(FadeInJingle, 0, 0, 0, 0);
+ CORO_INVOKE_4(fadeOutSoundEffect, 0, 0, 0, 0);
+ CORO_INVOKE_4(muteJingle, 0, 0, 0, 0);
+ CORO_INVOKE_4(playJingle, nJingle, 0, bLoop, 0);
+ CORO_INVOKE_4(fadeInJingle, 0, 0, 0, 0);
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(JingleFadeEnd)(CORO_PARAM, uint32 nJingle, uint32 bLoop, uint32, uint32) {
+void jingleFadeEnd(CORO_PARAM, uint32 nJingle, uint32 bLoop, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
- CORO_INVOKE_4(FadeOutJingle, 0, 0, 0, 0);
- CORO_INVOKE_4(FadeInSoundEffect, 0, 0, 0, 0);
+ CORO_INVOKE_4(fadeOutJingle, 0, 0, 0, 0);
+ CORO_INVOKE_4(fadeInSoundEffect, 0, 0, 0, 0);
CORO_END_CODE;
}
-
-
-
-DECLARE_CUSTOM_FUNCTION(MustSkipIdleStart)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void mustSkipIdleStart(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._bSkipIdle = true;
CoroScheduler.setEvent(GLOBALS._hSkipIdle);
}
-DECLARE_CUSTOM_FUNCTION(MustSkipIdleEnd)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void mustSkipIdleEnd(CORO_PARAM, uint32, uint32, uint32, uint32) {
GLOBALS._bSkipIdle = false;
CoroScheduler.resetEvent(GLOBALS._hSkipIdle);
}
-DECLARE_CUSTOM_FUNCTION(PatIrqFreeze)(CORO_PARAM, uint32 bStatus, uint32, uint32, uint32) {
+void patIrqFreeze(CORO_PARAM, uint32 bStatus, uint32, uint32, uint32) {
// Unused in ScummVM.
}
-DECLARE_CUSTOM_FUNCTION(OpenInitLoadMenu)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void openInitLoadMenu(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -2271,7 +2223,7 @@ DECLARE_CUSTOM_FUNCTION(OpenInitLoadMenu)(CORO_PARAM, uint32, uint32, uint32, ui
CORO_END_CODE;
}
-DECLARE_CUSTOM_FUNCTION(OpenInitOptions)(CORO_PARAM, uint32, uint32, uint32, uint32) {
+void openInitOptions(CORO_PARAM, uint32, uint32, uint32, uint32) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -2282,8 +2234,7 @@ DECLARE_CUSTOM_FUNCTION(OpenInitOptions)(CORO_PARAM, uint32, uint32, uint32, uin
CORO_END_CODE;
}
-
-DECLARE_CUSTOM_FUNCTION(DoCredits)(CORO_PARAM, uint32 nMsg, uint32 dwTime, uint32, uint32) {
+void doCredits(CORO_PARAM, uint32 nMsg, uint32 dwTime, uint32, uint32) {
CORO_BEGIN_CONTEXT;
RMMessage *msg;
RMTextDialog *text;
@@ -2355,159 +2306,157 @@ DECLARE_CUSTOM_FUNCTION(DoCredits)(CORO_PARAM, uint32 nMsg, uint32 dwTime, uint3
CORO_END_CODE;
}
-
-
BEGIN_CUSTOM_FUNCTION_MAP()
-ASSIGN(1, CustLoadLocation)
-ASSIGN(2, MySleep)
-ASSIGN(3, SetPointer)
-ASSIGN(5, MoveTony)
-ASSIGN(6, FaceToMe)
-ASSIGN(7, BackToMe)
-ASSIGN(8, LeftToMe)
-ASSIGN(9, RightToMe)
-ASSIGN(10, SendTonyMessage)
-ASSIGN(11, ChangeBoxStatus)
-ASSIGN(12, ChangeLocation)
-ASSIGN(13, DisableTony)
-ASSIGN(14, EnableTony)
-ASSIGN(15, WaitForPatternEnd)
-ASSIGN(16, SetLocStartPosition)
-ASSIGN(17, ScrollLocation)
-ASSIGN(18, MoveTonyAndWait)
-ASSIGN(19, ChangeHotspot)
-ASSIGN(20, AddInventory)
-ASSIGN(21, RemoveInventory)
-ASSIGN(22, ChangeInventoryStatus)
-ASSIGN(23, SetTonyPosition)
-ASSIGN(24, SendFullscreenMessage)
-ASSIGN(25, SaveTonyPosition)
-ASSIGN(26, RestoreTonyPosition)
-ASSIGN(27, DisableInput)
-ASSIGN(28, EnableInput)
-ASSIGN(29, StopTony)
-
-ASSIGN(30, TonyTakeUp1)
-ASSIGN(31, TonyTakeMid1)
-ASSIGN(32, TonyTakeDown1)
-ASSIGN(33, TonyTakeUp2)
-ASSIGN(34, TonyTakeMid2)
-ASSIGN(35, TonyTakeDown2)
-
-ASSIGN(72, TonyPutUp1)
-ASSIGN(73, TonyPutMid1)
-ASSIGN(74, TonyPutDown1)
-ASSIGN(75, TonyPutUp2)
-ASSIGN(76, TonyPutMid2)
-ASSIGN(77, TonyPutDown2)
-
-ASSIGN(36, TonyOnTheFloor)
-ASSIGN(37, TonyGetUp)
-ASSIGN(38, TonyShepherdess)
-ASSIGN(39, TonyWhistle)
-
-ASSIGN(40, TonyLaugh)
-ASSIGN(41, TonyHips)
-ASSIGN(42, TonySing)
-ASSIGN(43, TonyIndicate)
-ASSIGN(44, TonyScaredWithHands)
-ASSIGN(49, TonyScaredWithoutHands)
-ASSIGN(45, TonyWithGlasses)
-ASSIGN(46, TonyWithWorm)
-ASSIGN(47, TonyWithHammer)
-ASSIGN(48, TonyWithRope)
-ASSIGN(90, TonyWithRabbitANIM)
-ASSIGN(91, TonyWithRecipeANIM)
-ASSIGN(92, TonyWithCardsANIM)
-ASSIGN(93, TonyWithSnowmanANIM)
-ASSIGN(94, TonyWithSnowmanStart)
-ASSIGN(95, TonyWithSnowmanEnd)
-ASSIGN(96, TonyWithRabbitStart)
-ASSIGN(97, TonyWithRabbitEnd)
-ASSIGN(98, TonyWithRecipeStart)
-ASSIGN(99, TonyWithRecipeEnd)
-ASSIGN(100, TonyWithCardsStart)
-ASSIGN(101, TonyWithCardsEnd)
-ASSIGN(102, TonyWithNotebookStart)
-ASSIGN(103, TonyWithNotebookEnd)
-ASSIGN(104, TonyWithMegaphoneStart)
-ASSIGN(105, TonyWithMegaphoneEnd)
-ASSIGN(106, TonyWithBeardStart)
-ASSIGN(107, TonyWithBeardEnd)
-ASSIGN(108, TonyGiggle)
-ASSIGN(109, TonyDisgusted)
-ASSIGN(110, TonySarcastic)
-ASSIGN(111, TonyMacbeth)
-ASSIGN(112, TonySniffLeft)
-ASSIGN(113, TonySniffRight)
-ASSIGN(114, TonyScaredStart)
-ASSIGN(115, TonyScaredEnd)
-ASSIGN(116, TonyWithSecretary)
-
-ASSIGN(50, CharSetCode)
-ASSIGN(51, CharSetColor)
-ASSIGN(52, CharSetTalkPattern)
-ASSIGN(53, CharSendMessage)
-ASSIGN(54, CharSetStartEndTalkPattern)
-
-ASSIGN(60, MCharSetCode)
-ASSIGN(61, MCharSetColor)
-ASSIGN(62, MCharSetCurrentGroup)
-ASSIGN(63, MCharSetNumTalksInGroup)
-ASSIGN(64, MCharSetNumTexts)
-ASSIGN(65, MCharSendMessage)
-ASSIGN(66, MCharSetPosition)
-ASSIGN(67, MCharSetAlwaysBack)
-ASSIGN(68, MCharResetCode)
-
-ASSIGN(70, StartDialog)
-ASSIGN(71, SendDialogMessage)
-
-ASSIGN(80, TakeOwnership)
-ASSIGN(81, ReleaseOwnership)
-
-ASSIGN(86, PlaySoundEffect)
-ASSIGN(87, PlayJingle)
-ASSIGN(88, FadeInSoundEffect)
-ASSIGN(89, FadeOutSoundEffect)
-ASSIGN(123, FadeInJingle)
-ASSIGN(124, FadeOutJingle)
-ASSIGN(125, MuteSoundEffect)
-ASSIGN(126, DemuteSoundEffect)
-ASSIGN(127, MuteJingle)
-ASSIGN(128, DemuteJingle)
-ASSIGN(84, StopSoundEffect)
-ASSIGN(85, StopJingle)
-ASSIGN(83, PlayItemSfx)
-ASSIGN(129, JingleFadeStart)
-ASSIGN(130, JingleFadeEnd)
-
-ASSIGN(120, ShakeScreen)
-ASSIGN(121, AutoSave)
-ASSIGN(122, AbortGame)
-ASSIGN(131, NoBullsEye)
-ASSIGN(132, SendFullscreenMsgStart)
-ASSIGN(133, SendFullscreenMsgEnd)
-ASSIGN(134, CustEnableGUI)
-ASSIGN(135, CustDisableGUI)
-ASSIGN(136, ClearScreen)
-ASSIGN(137, PatIrqFreeze)
-ASSIGN(138, TonySetPerorate)
-ASSIGN(139, OpenInitLoadMenu)
-ASSIGN(140, OpenInitOptions)
-ASSIGN(141, SyncScrollLocation)
-ASSIGN(142, CloseLocation)
-ASSIGN(143, SetAlwaysDisplay)
-ASSIGN(144, DoCredits)
-
-ASSIGN(200, MustSkipIdleStart);
-ASSIGN(201, MustSkipIdleEnd);
+ASSIGN(1, custLoadLocation)
+ASSIGN(2, mySleep)
+ASSIGN(3, setPointer)
+ASSIGN(5, moveTony)
+ASSIGN(6, faceToMe)
+ASSIGN(7, backToMe)
+ASSIGN(8, leftToMe)
+ASSIGN(9, rightToMe)
+ASSIGN(10, sendTonyMessage)
+ASSIGN(11, changeBoxStatus)
+ASSIGN(12, changeLocation)
+ASSIGN(13, disableTony)
+ASSIGN(14, enableTony)
+ASSIGN(15, waitForPatternEnd)
+ASSIGN(16, setLocStartPosition)
+ASSIGN(17, scrollLocation)
+ASSIGN(18, moveTonyAndWait)
+ASSIGN(19, changeHotspot)
+ASSIGN(20, addInventory)
+ASSIGN(21, removeInventory)
+ASSIGN(22, changeInventoryStatus)
+ASSIGN(23, setTonyPosition)
+ASSIGN(24, sendFullscreenMessage)
+ASSIGN(25, saveTonyPosition)
+ASSIGN(26, restoreTonyPosition)
+ASSIGN(27, disableInput)
+ASSIGN(28, enableInput)
+ASSIGN(29, stopTony)
+
+ASSIGN(30, tonyTakeUp1)
+ASSIGN(31, tonyTakeMid1)
+ASSIGN(32, tonyTakeDown1)
+ASSIGN(33, tonyTakeUp2)
+ASSIGN(34, tonyTakeMid2)
+ASSIGN(35, tonyTakeDown2)
+
+ASSIGN(72, tonyPutUp1)
+ASSIGN(73, tonyPutMid1)
+ASSIGN(74, tonyPutDown1)
+ASSIGN(75, tonyPutUp2)
+ASSIGN(76, tonyPutMid2)
+ASSIGN(77, tonyPutDown2)
+
+ASSIGN(36, tonyOnTheFloor)
+ASSIGN(37, tonyGetUp)
+ASSIGN(38, tonyShepherdess)
+ASSIGN(39, tonyWhistle)
+
+ASSIGN(40, tonyLaugh)
+ASSIGN(41, tonyHips)
+ASSIGN(42, tonySing)
+ASSIGN(43, tonyIndicate)
+ASSIGN(44, tonyScaredWithHands)
+ASSIGN(49, tonyScaredWithoutHands)
+ASSIGN(45, tonyWithGlasses)
+ASSIGN(46, tonyWithWorm)
+ASSIGN(47, tonyWithHammer)
+ASSIGN(48, tonyWithRope)
+ASSIGN(90, tonyWithRabbitANIM)
+ASSIGN(91, tonyWithRecipeANIM)
+ASSIGN(92, tonyWithCardsANIM)
+ASSIGN(93, tonyWithSnowmanANIM)
+ASSIGN(94, tonyWithSnowmanStart)
+ASSIGN(95, tonyWithSnowmanEnd)
+ASSIGN(96, tonyWithRabbitStart)
+ASSIGN(97, tonyWithRabbitEnd)
+ASSIGN(98, tonyWithRecipeStart)
+ASSIGN(99, tonyWithRecipeEnd)
+ASSIGN(100, tonyWithCardsStart)
+ASSIGN(101, tonyWithCardsEnd)
+ASSIGN(102, tonyWithNotebookStart)
+ASSIGN(103, tonyWithNotebookEnd)
+ASSIGN(104, tonyWithMegaphoneStart)
+ASSIGN(105, tonyWithMegaphoneEnd)
+ASSIGN(106, tonyWithBeardStart)
+ASSIGN(107, tonyWithBeardEnd)
+ASSIGN(108, tonyGiggle)
+ASSIGN(109, tonyDisgusted)
+ASSIGN(110, tonySarcastic)
+ASSIGN(111, tonyMacbeth)
+ASSIGN(112, tonySniffLeft)
+ASSIGN(113, tonySniffRight)
+ASSIGN(114, tonyScaredStart)
+ASSIGN(115, tonyScaredEnd)
+ASSIGN(116, tonyWithSecretary)
+
+ASSIGN(50, charSetCode)
+ASSIGN(51, charSetColor)
+ASSIGN(52, charSetTalkPattern)
+ASSIGN(53, charSendMessage)
+ASSIGN(54, charSetStartEndTalkPattern)
+
+ASSIGN(60, mCharSetCode)
+ASSIGN(61, mCharSetColor)
+ASSIGN(62, mCharSetCurrentGroup)
+ASSIGN(63, mCharSetNumTalksInGroup)
+ASSIGN(64, mCharSetNumTexts)
+ASSIGN(65, mCharSendMessage)
+ASSIGN(66, mCharSetPosition)
+ASSIGN(67, mCharSetAlwaysBack)
+ASSIGN(68, mCharResetCode)
+
+ASSIGN(70, startDialog)
+ASSIGN(71, sendDialogMessage)
+
+ASSIGN(80, takeOwnership)
+ASSIGN(81, releaseOwnership)
+
+ASSIGN(86, playSoundEffect)
+ASSIGN(87, playJingle)
+ASSIGN(88, fadeInSoundEffect)
+ASSIGN(89, fadeOutSoundEffect)
+ASSIGN(123, fadeInJingle)
+ASSIGN(124, fadeOutJingle)
+ASSIGN(125, muteSoundEffect)
+ASSIGN(126, demuteSoundEffect)
+ASSIGN(127, muteJingle)
+ASSIGN(128, demuteJingle)
+ASSIGN(84, stopSoundEffect)
+ASSIGN(85, stopJingle)
+ASSIGN(83, playItemSfx)
+ASSIGN(129, jingleFadeStart)
+ASSIGN(130, jingleFadeEnd)
+
+ASSIGN(120, shakeScreen)
+ASSIGN(121, autoSave)
+ASSIGN(122, abortGame)
+ASSIGN(131, noBullsEye)
+ASSIGN(132, sendFullscreenMsgStart)
+ASSIGN(133, sendFullscreenMsgEnd)
+ASSIGN(134, custEnableGUI)
+ASSIGN(135, custDisableGUI)
+ASSIGN(136, clearScreen)
+ASSIGN(137, patIrqFreeze)
+ASSIGN(138, tonySetPerorate)
+ASSIGN(139, openInitLoadMenu)
+ASSIGN(140, openInitOptions)
+ASSIGN(141, syncScrollLocation)
+ASSIGN(142, closeLocation)
+ASSIGN(143, setAlwaysDisplay)
+ASSIGN(144, doCredits)
+
+ASSIGN(200, mustSkipIdleStart);
+ASSIGN(201, mustSkipIdleEnd);
END_CUSTOM_FUNCTION_MAP()
void processKilledCallback(Common::PROCESS *p) {
- for (uint i = 0; i < 10; i++)
+ for (uint i = 0; i < 10; i++) {
if (GLOBALS._mut[i]._ownerPid == p->pid) {
// Handle scripts which don't call ReleaseOwnership, such as
// the one in loc37's vEnter when Tony is chasing the mouse.
@@ -2517,6 +2466,7 @@ void processKilledCallback(Common::PROCESS *p) {
GLOBALS._mut[i]._lockCount = 0;
CoroScheduler.setEvent(GLOBALS._mut[i]._eventId);
}
+ }
}
void setupGlobalVars(RMTony *tony, RMPointer *ptr, RMGameBoxes *box, RMLocation *loc, RMInventory *inv, RMInput *input) {
@@ -2531,13 +2481,12 @@ void setupGlobalVars(RMTony *tony, RMPointer *ptr, RMGameBoxes *box, RMLocation
GLOBALS.EnableGUI = mainEnableGUI;
GLOBALS._bAlwaysDisplay = false;
- int i;
CoroScheduler.setResourceCallback(processKilledCallback);
- for (i = 0; i < 10; i++)
+ for (int i = 0; i < 10; i++)
GLOBALS._mut[i]._eventId = CoroScheduler.createEvent(false, true);
- for (i = 0; i < 200; i++)
+ for (int i = 0; i < 200; i++)
GLOBALS._ambiance[i] = 0;
GLOBALS._ambiance[6] = AMBIANCE_CRICKETS;
diff --git a/engines/tony/custom.h b/engines/tony/custom.h
index 524ab14aab..0f1061e8cd 100644
--- a/engines/tony/custom.h
+++ b/engines/tony/custom.h
@@ -36,9 +36,12 @@ namespace Tony {
using namespace MPAL;
-#define INIT_CUSTOM_FUNCTION MapCustomFunctions
+struct MusicFileEntry {
+ const char *_name;
+ int _sync;
+};
-#define DECLARE_CUSTOM_FUNCTION(x) void x
+#define INIT_CUSTOM_FUNCTION MapCustomFunctions
#define BEGIN_CUSTOM_FUNCTION_MAP() \
static void AssignError(int num) { \
@@ -63,6 +66,17 @@ class RMLocation;
class RMInventory;
class RMInput;
+void charsSaveAll(Common::OutSaveFile *f);
+void charsLoadAll(Common::InSaveFile *f);
+void mCharResetCodes();
+void saveChangedHotspot(Common::OutSaveFile *f);
+void loadChangedHotspot(Common::InSaveFile *f);
+void reapplyChangedHotspot();
+
+void restoreMusic(CORO_PARAM);
+void saveMusic(Common::OutSaveFile *f);
+void loadMusic(Common::InSaveFile *f);
+
void INIT_CUSTOM_FUNCTION(LPCUSTOMFUNCTION *lpMap, Common::String *lpStrMap);
void setupGlobalVars(RMTony *tony, RMPointer *ptr, RMGameBoxes *box, RMLocation *loc, RMInventory *inv, RMInput *input);
diff --git a/engines/tony/detection_tables.h b/engines/tony/detection_tables.h
index f9881c29f2..ce3ab01a9f 100644
--- a/engines/tony/detection_tables.h
+++ b/engines/tony/detection_tables.h
@@ -124,6 +124,22 @@ static const TonyGameDescription gameDescriptions[] = {
},
},
{
+ // Tony Tough Italian provided by Giovanni Bajo
+ {
+ "tony",
+ 0,
+ {
+ {"roasted.mpr", 0, "06203dbbc85fdd1e6dc8fc211c1a6207", 135911071},
+ {"roasted.mpc", 0, "6202816f991b15af82aab84e3e4be011", 380183},
+ AD_LISTEND
+ },
+ Common::IT_ITA,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NONE)
+ },
+ },
+ {
// Tony Tough Polish provided by Fabio Barzagli
{
"tony",
@@ -139,6 +155,39 @@ static const TonyGameDescription gameDescriptions[] = {
GUIO1(GUIO_NONE)
},
},
+ {
+ // Tony Tough German "Gamestar" provided in bug #3566035
+ {
+ "tony",
+ 0,
+ {
+ {"roasted.mpr", 0, "06203dbbc85fdd1e6dc8fc211c1a6207", 135911071},
+ {"roasted.mpc", 0, "187de6f88f4083808cb66342ab55a7fd", 389904},
+ AD_LISTEND
+ },
+ Common::DE_DEU,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NONE)
+ },
+ },
+ {
+ // Tony Tough Czech provided in bug #3565765
+ {
+ "tony",
+ 0,
+ {
+ // {"data1.cab", 0, "c6d5dd8f0c1241a6e3f7861b7f27bf7b", 4350},
+ {"roasted.mpr", 0, "06203dbbc85fdd1e6dc8fc211c1a6207", 135911071},
+ {"roasted.mpc", 0, "a8283a101878f3ca105f1f83f07e2c40", 386491},
+ AD_LISTEND
+ },
+ Common::CZ_CZE,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NONE)
+ },
+ },
{ AD_TABLE_END_MARKER }
};
diff --git a/engines/tony/font.cpp b/engines/tony/font.cpp
index 927adf9006..fa018b4464 100644
--- a/engines/tony/font.cpp
+++ b/engines/tony/font.cpp
@@ -84,10 +84,9 @@ void RMFont::unload() {
RMGfxPrimitive *RMFont::makeLetterPrimitive(byte bChar, int &nLength) {
RMFontPrimitive *prim;
- int nLett;
// Convert from character to glyph index
- nLett = convertToLetter(bChar);
+ int nLett = convertToLetter(bChar);
assert(nLett < _nLetters);
// Create primitive font
@@ -120,12 +119,11 @@ void RMFont::close() {
}
int RMFont::stringLen(const Common::String &text) {
- uint len, i;
-
if (text.empty())
return letterLength('\0');
- len = 0;
+ uint len = 0;
+ uint i;
for (i = 0; i < text.size() - 1; i++)
len += letterLength(text[i], text[i + 1]);
len += letterLength(text[i]);
@@ -157,7 +155,6 @@ void RMFontColor::setBaseColor(byte r1, byte g1, byte b1) {
int gstep = g / 14;
int bstep = b / 14;
- int i;
byte pal[768 * 3];
// Check if we are already on the right color
@@ -169,7 +166,7 @@ void RMFontColor::setBaseColor(byte r1, byte g1, byte b1) {
_fontB = b1;
// Constructs a new palette for the font
- for (i = 1; i < 16; i++) {
+ for (int i = 1; i < 16; i++) {
pal[i * 3 + 0] = r >> 16;
pal[i * 3 + 1] = g >> 16;
pal[i * 3 + 2] = b >> 16;
@@ -184,7 +181,7 @@ void RMFontColor::setBaseColor(byte r1, byte g1, byte b1) {
pal[15 * 3 + 2] += 8;
// Puts in all the letters
- for (i = 0; i < _nLetters; i++)
+ for (int i = 0; i < _nLetters; i++)
_letter[i].loadPaletteWA(pal);
}
@@ -204,8 +201,6 @@ int RMFontWithTables::letterLength(int nChar, int nNext) {
\****************************************************************************/
void RMFontDialog::init() {
- int i;
-
// bernie: Number of characters in the font
int nchars =
112 // base
@@ -222,7 +217,7 @@ void RMFontDialog::init() {
_hDefault = 18;
Common::fill(&_l2Table[0][0], &_l2Table[0][0] + (256 * 256), '\0');
- for (i = 0; i < 256; i++) {
+ for (int i = 0; i < 256; i++) {
_cTable[i] = g_vm->_cTableDialog[i];
_lTable[i] = g_vm->_lTableDialog[i];
}
@@ -234,8 +229,6 @@ void RMFontDialog::init() {
\****************************************************************************/
void RMFontMacc::init() {
- int i;
-
// bernie: Number of characters in the font
int nchars =
102 // base
@@ -245,7 +238,6 @@ void RMFontMacc::init() {
+ 8 // francais
+ 5; // deutsch
-
load(RES_F_MACC, nchars, 11, 16);
// Default
@@ -253,7 +245,7 @@ void RMFontMacc::init() {
_hDefault = 17;
Common::fill(&_l2Table[0][0], &_l2Table[0][0] + (256 * 256), '\0');
- for (i = 0; i < 256; i++) {
+ for (int i = 0; i < 256; i++) {
_cTable[i] = g_vm->_cTableMacc[i];
_lTable[i] = g_vm->_lTableMacc[i];
}
@@ -264,8 +256,6 @@ void RMFontMacc::init() {
\****************************************************************************/
void RMFontCredits::init() {
- int i;
-
// bernie: Number of characters in the font
int nchars =
112 // base
@@ -275,7 +265,6 @@ void RMFontCredits::init() {
+ 8 // french
+ 2; // deutsch
-
load(RES_F_CREDITS, nchars, 27, 28, RES_F_CPAL);
// Default
@@ -283,7 +272,7 @@ void RMFontCredits::init() {
_hDefault = 28;
Common::fill(&_l2Table[0][0], &_l2Table[0][0] + (256 * 256), '\0');
- for (i = 0; i < 256; i++) {
+ for (int i = 0; i < 256; i++) {
_cTable[i] = g_vm->_cTableCred[i];
_lTable[i] = g_vm->_lTableCred[i];
}
@@ -305,10 +294,7 @@ void RMFontObj::setBothCase(int nChar, int nNext, signed char spiazz) {
_l2Table[TOLOWER(nChar)][TOLOWER(nNext)] = spiazz;
}
-
void RMFontObj::init() {
- int i;
-
//bernie: Number of characters in the font (solo maiuscolo)
int nchars =
85 // base
@@ -318,7 +304,6 @@ void RMFontObj::init() {
+ 0 // francais (no uppercase chars)
+ 1; // deutsch
-
load(RES_F_OBJ, nchars, 25, 30);
// Initialize the font table
@@ -326,7 +311,7 @@ void RMFontObj::init() {
_hDefault = 30;
Common::fill(&_l2Table[0][0], &_l2Table[0][0] + (256 * 256), '\0');
- for (i = 0; i < 256; i++) {
+ for (int i = 0; i < 256; i++) {
_cTable[i] = g_vm->_cTableObj[i];
_lTable[i] = g_vm->_lTableObj[i];
}
@@ -345,7 +330,6 @@ void RMFontObj::init() {
setBothCase('R', 'U', 3);
}
-
/****************************************************************************\
* RMText Methods
\****************************************************************************/
@@ -409,11 +393,6 @@ void RMText::writeText(const Common::String &text, int nFont, int *time) {
void RMText::writeText(Common::String text, RMFontColor *font, int *time) {
RMGfxPrimitive *prim;
- uint p, old_p;
- int j, x, y;
- int len;
- int numchar;
- int width, height;
// Set the base color
font->setBaseColor(_textR, _textG, _textB);
@@ -428,8 +407,9 @@ void RMText::writeText(Common::String text, RMFontColor *font, int *time) {
// Divide the words into lines. In this cycle, X contains the maximum length reached by a line,
// and the number of lines
Common::Array<Common::String> lines;
- p = 0;
- j = x = 0;
+ uint p = 0;
+ int j = 0;
+ int x = 0;
while (p < text.size()) {
j += font->stringLen(text[p]);
if (j > (((_aHorType == HLEFTPAR) && (lines.size() > 0)) ? _maxLineLength - 25 : _maxLineLength)) {
@@ -443,7 +423,7 @@ void RMText::writeText(Common::String text, RMFontColor *font, int *time) {
// width of a line caused discontinuation of the whole sentence.
// This workaround has the partial word broken up so it will still display
//
- old_p = p;
+ uint old_p = p;
while (text[p] != ' ' && text[p] != '-' && p > 0)
p--;
@@ -475,8 +455,8 @@ void RMText::writeText(Common::String text, RMFontColor *font, int *time) {
x += 8;
// Starting position for the surface: X1, Y
- width = x;
- height = (lines.size() - 1) * font->letterHeight() + font->_fontDimy;
+ int width = x;
+ int height = (lines.size() - 1) * font->letterHeight() + font->_fontDimy;
// Create the surface
create(width, height);
@@ -484,8 +464,8 @@ void RMText::writeText(Common::String text, RMFontColor *font, int *time) {
p = 0;
- y = 0;
- numchar = 0;
+ int y = 0;
+ int numchar = 0;
for (uint i = 0; i < lines.size(); ++i) {
const Common::String &line = lines[i];
@@ -522,6 +502,7 @@ void RMText::writeText(Common::String text, RMFontColor *font, int *time) {
continue;
}
+ int len;
prim = font->makeLetterPrimitive(line[p], len);
prim->getDst()._x1 = x;
prim->getDst()._y1 = y;
@@ -737,8 +718,8 @@ void RMTextDialog::removeThis(CORO_PARAM, bool &result) {
CORO_END_CODE;
}
-void RMTextDialog::Unregister() {
- RMGfxTask::Unregister();
+void RMTextDialog::unregister() {
+ RMGfxTask::unregister();
assert(_nInList == 0);
CoroScheduler.setEvent(_hEndDisplay);
}
@@ -908,7 +889,7 @@ RMPoint RMTextItemName::getHotspot() {
if (_item == NULL)
return _mpos + _curscroll;
else
- return _item->hotspot();
+ return _item->getHotspot();
}
RMItem *RMTextItemName::getSelectedItem() {
@@ -944,7 +925,7 @@ RMDialogChoice::RMDialogChoice() {
_hUnreg = CoroScheduler.createEvent(false, false);
_bRemoveFromOT = false;
-
+
_curAdded = 0;
_bShow = false;
}
@@ -953,8 +934,8 @@ RMDialogChoice::~RMDialogChoice() {
CoroScheduler.closeEvent(_hUnreg);
}
-void RMDialogChoice::Unregister() {
- RMGfxWoodyBuffer::Unregister();
+void RMDialogChoice::unregister() {
+ RMGfxWoodyBuffer::unregister();
assert(!_nInList);
CoroScheduler.pulseEvent(_hUnreg);
@@ -987,8 +968,6 @@ void RMDialogChoice::close() {
}
void RMDialogChoice::setNumChoices(int num) {
- int i;
-
_numChoices = num;
_curAdded = 0;
@@ -997,7 +976,7 @@ void RMDialogChoice::setNumChoices(int num) {
_ptDrawStrings = new RMPoint[num];
// Initialization
- for (i = 0; i < _numChoices; i++) {
+ for (int i = 0; i < _numChoices; i++) {
_drawedStrings[i].setColor(0, 255, 0);
_drawedStrings[i].setAlignType(RMText::HLEFTPAR, RMText::VTOP);
_drawedStrings[i].setMaxLineLength(600);
diff --git a/engines/tony/font.h b/engines/tony/font.h
index 99b20571b1..13c1ddf268 100644
--- a/engines/tony/font.h
+++ b/engines/tony/font.h
@@ -252,7 +252,7 @@ public:
virtual void removeThis(CORO_PARAM, bool &result);
// Overloaded de-registration
- virtual void Unregister();
+ virtual void unregister();
// Overloading of the Draw to center the text, if necessary
virtual void draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim);
@@ -344,7 +344,7 @@ protected:
public:
virtual void removeThis(CORO_PARAM, bool &result);
virtual void draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim);
- void Unregister();
+ void unregister();
public:
// Initialization
diff --git a/engines/tony/game.cpp b/engines/tony/game.cpp
index 2bcfdc7fc2..42ace987b4 100644
--- a/engines/tony/game.cpp
+++ b/engines/tony/game.cpp
@@ -34,7 +34,6 @@
#include "tony/mpal/memory.h"
#include "tony/mpal/mpal.h"
#include "tony/mpal/mpalutils.h"
-#include "tony/custom.h"
#include "tony/game.h"
#include "tony/gfxengine.h"
#include "tony/tony.h"
@@ -288,9 +287,7 @@ RMOptionScreen::RMOptionScreen() {
_buttonSave_ArrowRight = NULL;
_bEditSaveName = false;
- int i;
-
- for (i = 0; i < 6; i++) {
+ for (int i = 0; i < 6; i++) {
_curThumb[i] = NULL;
_buttonSave_States[i] = NULL;
}
@@ -501,9 +498,7 @@ void RMOptionScreen::refreshAll(CORO_PARAM) {
}
void RMOptionScreen::refreshThumbnails() {
- int i;
-
- for (i = 0; i < 6; i++) {
+ for (int i = 0; i < 6; i++) {
if (_curThumb[i])
delete _curThumb[i];
@@ -691,9 +686,7 @@ void RMOptionScreen::closeState() {
_buttonExit = NULL;
if (_nState == MENULOAD || _nState == MENUSAVE) {
- int i;
-
- for (i = 0; i < 6; i++) {
+ for (int i = 0; i < 6; i++) {
if (_curThumb[i] != NULL) {
delete _curThumb[i];
_curThumb[i] = NULL;
@@ -981,7 +974,7 @@ void RMOptionScreen::doFrame(CORO_PARAM, RMInput *input) {
CORO_BEGIN_CODE(_ctx);
- // If it is fully open, do nothing
+ // If it is not fully open, do nothing
if (_fadeStep != 6)
return;
@@ -1343,9 +1336,7 @@ void RMOptionScreen::removeThis(CORO_PARAM, bool &result) {
bool RMOptionScreen::loadThumbnailFromSaveState(int nState, byte *lpDestBuf, Common::String &name, byte &diff) {
- Common::String buf;
char namebuf[256];
- int i;
Common::InSaveFile *f;
char id[4];
@@ -1355,7 +1346,7 @@ bool RMOptionScreen::loadThumbnailFromSaveState(int nState, byte *lpDestBuf, Com
diff = 10;
// Get the savegame filename for the given slot
- buf = g_vm->getSaveStateFileName(nState);
+ Common::String buf = g_vm->getSaveStateFileName(nState);
// Try and open the savegame
f = g_system->getSavefileManager()->openForLoading(buf);
@@ -1410,9 +1401,9 @@ bool RMOptionScreen::loadThumbnailFromSaveState(int nState, byte *lpDestBuf, Com
return true;
}
- i = f->readByte();
- f->read(namebuf, i);
- namebuf[i] = '\0';
+ int bufSize = f->readByte();
+ f->read(namebuf, bufSize);
+ namebuf[bufSize] = '\0';
name = namebuf;
delete f;
@@ -1436,9 +1427,7 @@ RMPointer::~RMPointer() {
}
void RMPointer::init() {
- int i;
-
- for (i = 0; i < 5; i++) {
+ for (int i = 0; i < 5; i++) {
RMResRaw res(RES_P_GO + i);
_pointer[i] = new RMGfxSourceBuffer8RLEByteAA;
@@ -1446,7 +1435,7 @@ void RMPointer::init() {
_pointer[i]->loadPaletteWA(RES_P_PAL);
}
- for (i = 0; i < 5; i++) {
+ for (int i = 0; i < 5; i++) {
RMRes res(RES_P_PAP1 + i);
Common::SeekableReadStream *ds = res.getReadStream();
_specialPointer[i] = new RMItem;
@@ -1467,9 +1456,7 @@ void RMPointer::init() {
}
void RMPointer::close() {
- int i;
-
- for (i = 0; i < 5; i++) {
+ for (int i = 0; i < 5; i++) {
if (_pointer[i] != NULL) {
delete _pointer[i];
_pointer[i] = NULL;
diff --git a/engines/tony/gfxcore.cpp b/engines/tony/gfxcore.cpp
index 71bf31396c..04ce01b0ed 100644
--- a/engines/tony/gfxcore.cpp
+++ b/engines/tony/gfxcore.cpp
@@ -56,7 +56,7 @@ void RMGfxTask::Register() {
_nInList++;
}
-void RMGfxTask::Unregister() {
+void RMGfxTask::unregister() {
_nInList--;
assert(_nInList >= 0);
}
@@ -269,7 +269,7 @@ void RMGfxTargetBuffer::clearOT() {
cur = _otlist;
while (cur != NULL) {
- cur->_prim->_task->Unregister();
+ cur->_prim->_task->unregister();
delete cur->_prim;
n = cur->_next;
delete cur;
@@ -303,7 +303,7 @@ void RMGfxTargetBuffer::drawOT(CORO_PARAM) {
CORO_INVOKE_1(_ctx->cur->_prim->_task->removeThis, _ctx->result);
if (_ctx->result) {
// De-register the task
- _ctx->cur->_prim->_task->Unregister();
+ _ctx->cur->_prim->_task->unregister();
// Delete task, freeing the memory
delete _ctx->cur->_prim;
@@ -361,7 +361,7 @@ void RMGfxTargetBuffer::addPrim(RMGfxPrimitive *prim) {
void RMGfxTargetBuffer::addDirtyRect(const Common::Rect &r) {
assert(r.isValidRect());
if (_trackDirtyRects && r.width() > 0 && r.height() > 0)
- _currentDirtyRects.push_back(r);
+ _currentDirtyRects.push_back(r);
}
Common::List<Common::Rect> &RMGfxTargetBuffer::getDirtyRects() {
@@ -507,9 +507,7 @@ int RMGfxSourceBufferPal::loadPaletteWA(const byte *buf, bool bSwapped) {
}
int RMGfxSourceBufferPal::loadPalette(const byte *buf) {
- int i;
-
- for (i = 0; i < 256; i++)
+ for (int i = 0; i < 256; i++)
memcpy(_pal + i * 3, buf + i * 4, 3);
preparePalette();
@@ -518,9 +516,7 @@ int RMGfxSourceBufferPal::loadPalette(const byte *buf) {
}
void RMGfxSourceBufferPal::preparePalette() {
- int i;
-
- for (i = 0; i < 256; i++) {
+ for (int i = 0; i < 256; i++) {
_palFinal[i] = (((int)_pal[i * 3 + 0] >> 3) << 10) |
(((int)_pal[i * 3 + 1] >> 3) << 5) |
(((int)_pal[i * 3 + 2] >> 3) << 0);
@@ -528,10 +524,8 @@ void RMGfxSourceBufferPal::preparePalette() {
}
int RMGfxSourceBufferPal::init(const byte *buf, int dimx, int dimy, bool bLoadPalette) {
- int read;
-
// Load the RAW image
- read = RMGfxSourceBuffer::init(buf, dimx, dimy);
+ int read = RMGfxSourceBuffer::init(buf, dimx, dimy);
// Load the palette if necessary
if (bLoadPalette)
@@ -596,7 +590,7 @@ RMGfxSourceBuffer8::~RMGfxSourceBuffer8() {
}
void RMGfxSourceBuffer8::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
- int x, y, width, height, u, v;
+ int width, height, u, v;
int bufx = bigBuf.getDimx();
uint16 *buf = bigBuf;
byte *raw = _buf;
@@ -623,10 +617,10 @@ void RMGfxSourceBuffer8::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimit
// Normal step
if (_bTrasp0) {
- for (y = 0; y < height; y++) {
+ for (int y = 0; y < height; y++) {
raw = _buf + (y + v) * _dimx + u;
- for (x = 0; x < width; x++) {
+ for (int x = 0; x < width; x++) {
if (*raw)
*buf = _palFinal[*raw];
buf++;
@@ -636,10 +630,10 @@ void RMGfxSourceBuffer8::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimit
buf += bufx - width;
}
} else {
- for (y = 0; y < height; y++) {
+ for (int y = 0; y < height; y++) {
raw = _buf + (y + v) * _dimx + u;
- for (x = 0; x < width; x += 2) {
+ for (int x = 0; x < width; x += 2) {
buf[0] = _palFinal[raw[0]];
buf[1] = _palFinal[raw[1]];
@@ -693,11 +687,9 @@ RMGfxSourceBuffer8AB::~RMGfxSourceBuffer8AB() {
}
int RMGfxSourceBuffer8AB::calcTrasp(int fore, int back) {
- int r, g, b;
-
- r = (GETRED(fore) >> 2) + (GETRED(back) >> 1);
- g = (GETGREEN(fore) >> 2) + (GETGREEN(back) >> 1);
- b = (GETBLUE(fore) >> 2) + (GETBLUE(back) >> 1);
+ int r = (GETRED(fore) >> 2) + (GETRED(back) >> 1);
+ int g = (GETGREEN(fore) >> 2) + (GETGREEN(back) >> 1);
+ int b = (GETBLUE(fore) >> 2) + (GETBLUE(back) >> 1);
if (r > 0x1F)
r = 0x1F;
@@ -713,7 +705,7 @@ int RMGfxSourceBuffer8AB::calcTrasp(int fore, int back) {
void RMGfxSourceBuffer8AB::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
- int x, y, width, height, u, v;
+ int width, height, u, v;
int bufx = bigBuf.getDimx();
uint16 *buf = bigBuf;
byte *raw = _buf;
@@ -740,10 +732,10 @@ void RMGfxSourceBuffer8AB::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrim
// Passaggio normale
if (_bTrasp0) {
- for (y = 0; y < height; y++) {
+ for (int y = 0; y < height; y++) {
raw = _buf + (y + v) * _dimx + u;
- for (x = 0; x < width; x++) {
+ for (int x = 0; x < width; x++) {
if (*raw)
*buf = calcTrasp(_palFinal[*raw], *buf);
@@ -754,10 +746,10 @@ void RMGfxSourceBuffer8AB::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrim
buf += bufx - width;
}
} else {
- for (y = 0; y < height; y++) {
+ for (int y = 0; y < height; y++) {
raw = _buf + (y + v) * _dimx + u;
- for (x = 0; x < width; x += 2) {
+ for (int x = 0; x < width; x += 2) {
buf[0] = calcTrasp(_palFinal[raw[0]], buf[0]);
buf[1] = calcTrasp(_palFinal[raw[1]], buf[1]);
@@ -809,9 +801,7 @@ void RMGfxSourceBuffer8RLE::init(Common::ReadStream &ds, int dimx, int dimy, boo
if (_bNeedRLECompress) {
RMGfxSourceBufferPal::init(ds, dimx, dimy, bLoadPalette);
} else {
- int size;
-
- size = ds.readSint32LE();
+ int size = ds.readSint32LE();
_buf = new byte[size];
ds.read(_buf, size);
@@ -845,7 +835,6 @@ void RMGfxSourceBuffer8RLE::setAlreadyCompressed() {
}
void RMGfxSourceBuffer8RLE::compressRLE() {
- int x, y;
byte *startline;
byte *cur;
byte curdata;
@@ -856,7 +845,7 @@ void RMGfxSourceBuffer8RLE::compressRLE() {
// Perform RLE compression for lines
cur = _megaRLEBuf;
src = _buf;
- for (y = 0; y < _dimy; y++) {
+ for (int y = 0; y < _dimy; y++) {
// Save the beginning of the line
startline = cur;
@@ -867,7 +856,7 @@ void RMGfxSourceBuffer8RLE::compressRLE() {
curdata = 0;
rep = 0;
startsrc = src;
- for (x = 0; x < _dimx;) {
+ for (int x = 0; x < _dimx;) {
if ((curdata == 0 && *src == 0) || (curdata == 1 && *src == _alphaBlendColor)
|| (curdata == 2 && (*src != _alphaBlendColor && *src != 0))) {
src++;
@@ -875,13 +864,13 @@ void RMGfxSourceBuffer8RLE::compressRLE() {
x++;
} else {
if (curdata == 0) {
- RLEWriteTrasp(cur, rep);
+ rleWriteTrasp(cur, rep);
curdata++;
} else if (curdata == 1) {
- RLEWriteAlphaBlend(cur, rep);
+ rleWriteAlphaBlend(cur, rep);
curdata++;
} else {
- RLEWriteData(cur, rep, startsrc);
+ rleWriteData(cur, rep, startsrc);
curdata = 0;
}
@@ -892,16 +881,16 @@ void RMGfxSourceBuffer8RLE::compressRLE() {
// Pending data?
if (curdata == 1) {
- RLEWriteAlphaBlend(cur, rep);
- RLEWriteData(cur, 0, NULL);
+ rleWriteAlphaBlend(cur, rep);
+ rleWriteData(cur, 0, NULL);
}
if (curdata == 2) {
- RLEWriteData(cur, rep, startsrc);
+ rleWriteData(cur, rep, startsrc);
}
// End of line
- RLEWriteEOL(cur);
+ rleWriteEOL(cur);
// Write the length of the line
WRITE_LE_UINT16(startline, (uint16)(cur - startline));
@@ -911,26 +900,25 @@ void RMGfxSourceBuffer8RLE::compressRLE() {
delete[] _buf;
// Copy the compressed image
- x = cur - _megaRLEBuf;
- _buf = new byte[x];
- Common::copy(_megaRLEBuf, _megaRLEBuf + x, _buf);
+ int bufSize = cur - _megaRLEBuf;
+ _buf = new byte[bufSize];
+ Common::copy(_megaRLEBuf, _megaRLEBuf + bufSize, _buf);
}
void RMGfxSourceBuffer8RLE::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
- int y;
byte *src;
uint16 *buf = bigBuf;
- int x1, y1, u, v, width, height;
+ int u, v, width, height;
// Clipping
- x1 = prim->getDst()._x1;
- y1 = prim->getDst()._y1;
+ int x1 = prim->getDst()._x1;
+ int y1 = prim->getDst()._y1;
if (!clip2D(x1, y1, u, v, width, height, false, &bigBuf))
return;
// Go forward through the RLE lines
src = _buf;
- for (y = 0; y < v; y++)
+ for (int y = 0; y < v; y++)
src += READ_LE_UINT16(src);
// Calculate the position in the destination buffer
@@ -952,9 +940,9 @@ void RMGfxSourceBuffer8RLE::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPri
// Specify the drawn area
bigBuf.addDirtyRect(Common::Rect(x1 - width, y1, x1 + 1, y1 + height));
- for (y = 0; y < height; y++) {
+ for (int y = 0; y < height; y++) {
// Decompression
- RLEDecompressLineFlipped(buf + x1, src + 2, u, width);
+ rleDecompressLineFlipped(buf + x1, src + 2, u, width);
// Next line
src += READ_LE_UINT16(src);
@@ -966,9 +954,9 @@ void RMGfxSourceBuffer8RLE::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPri
// Specify the drawn area
bigBuf.addDirtyRect(Common::Rect(x1, y1, x1 + width, y1 + height));
- for (y = 0; y < height; y++) {
+ for (int y = 0; y < height; y++) {
// Decompression
- RLEDecompressLine(buf + x1, src + 2, u, width);
+ rleDecompressLine(buf + x1, src + 2, u, width);
// Next line
src += READ_LE_UINT16(src);
@@ -985,20 +973,19 @@ void RMGfxSourceBuffer8RLE::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPri
\****************************************************************************/
RMGfxSourceBuffer8RLEByte::~RMGfxSourceBuffer8RLEByte() {
-
}
-void RMGfxSourceBuffer8RLEByte::RLEWriteTrasp(byte *&cur, int rep) {
+void RMGfxSourceBuffer8RLEByte::rleWriteTrasp(byte *&cur, int rep) {
assert(rep < 255);
*cur ++ = rep;
}
-void RMGfxSourceBuffer8RLEByte::RLEWriteAlphaBlend(byte *&cur, int rep) {
+void RMGfxSourceBuffer8RLEByte::rleWriteAlphaBlend(byte *&cur, int rep) {
assert(rep < 255);
*cur ++ = rep;
}
-void RMGfxSourceBuffer8RLEByte::RLEWriteData(byte *&cur, int rep, byte *src) {
+void RMGfxSourceBuffer8RLEByte::rleWriteData(byte *&cur, int rep, byte *src) {
assert(rep < 256);
*cur ++ = rep;
@@ -1011,13 +998,12 @@ void RMGfxSourceBuffer8RLEByte::RLEWriteData(byte *&cur, int rep, byte *src) {
return;
}
-void RMGfxSourceBuffer8RLEByte::RLEWriteEOL(byte *&cur) {
+void RMGfxSourceBuffer8RLEByte::rleWriteEOL(byte *&cur) {
*cur ++ = 0xFF;
}
-void RMGfxSourceBuffer8RLEByte::RLEDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength) {
- int i, n;
- int r, g, b;
+void RMGfxSourceBuffer8RLEByte::rleDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength) {
+ int n;
if (nStartSkip == 0)
goto RLEByteDoTrasp;
@@ -1086,10 +1072,10 @@ RLEByteDoAlpha:
RLEByteDoAlpha2:
if (n > nLength)
n = nLength;
- for (i = 0; i < n; i++) {
- r = (*dst >> 10) & 0x1F;
- g = (*dst >> 5) & 0x1F;
- b = *dst & 0x1F;
+ for (int i = 0; i < n; i++) {
+ int r = (*dst >> 10) & 0x1F;
+ int g = (*dst >> 5) & 0x1F;
+ int b = *dst & 0x1F;
r = (r >> 2) + (_alphaR >> 1);
g = (g >> 2) + (_alphaG >> 1);
@@ -1111,7 +1097,7 @@ RLEByteDoCopy2:
if (n > nLength)
n = nLength;
- for (i = 0; i < n; i++)
+ for (int i = 0; i < n; i++)
*dst ++ = _palFinal[*src++];
nLength -= n;
@@ -1121,9 +1107,8 @@ RLEByteDoCopy2:
}
}
-void RMGfxSourceBuffer8RLEByte::RLEDecompressLineFlipped(uint16 *dst, byte *src, int nStartSkip, int nLength) {
- int i, n;
- int r, g, b;
+void RMGfxSourceBuffer8RLEByte::rleDecompressLineFlipped(uint16 *dst, byte *src, int nStartSkip, int nLength) {
+ int n;
if (nStartSkip == 0)
goto RLEByteFlippedDoTrasp;
@@ -1192,10 +1177,10 @@ RLEByteFlippedDoAlpha:
RLEByteFlippedDoAlpha2:
if (n > nLength)
n = nLength;
- for (i = 0; i < n; i++) {
- r = (*dst >> 10) & 0x1F;
- g = (*dst >> 5) & 0x1F;
- b = *dst & 0x1F;
+ for (int i = 0; i < n; i++) {
+ int r = (*dst >> 10) & 0x1F;
+ int g = (*dst >> 5) & 0x1F;
+ int b = *dst & 0x1F;
r = (r >> 2) + (_alphaR >> 1);
g = (g >> 2) + (_alphaG >> 1);
@@ -1217,7 +1202,7 @@ RLEByteFlippedDoCopy2:
if (n > nLength)
n = nLength;
- for (i = 0; i < n; i++)
+ for (int i = 0; i < n; i++)
*dst-- = _palFinal[*src++];
nLength -= n;
@@ -1236,17 +1221,17 @@ RMGfxSourceBuffer8RLEWord::~RMGfxSourceBuffer8RLEWord() {
}
-void RMGfxSourceBuffer8RLEWord::RLEWriteTrasp(byte *&cur, int rep) {
+void RMGfxSourceBuffer8RLEWord::rleWriteTrasp(byte *&cur, int rep) {
WRITE_LE_UINT16(cur, rep);
cur += 2;
}
-void RMGfxSourceBuffer8RLEWord::RLEWriteAlphaBlend(byte *&cur, int rep) {
+void RMGfxSourceBuffer8RLEWord::rleWriteAlphaBlend(byte *&cur, int rep) {
WRITE_LE_UINT16(cur, rep);
cur += 2;
}
-void RMGfxSourceBuffer8RLEWord::RLEWriteData(byte *&cur, int rep, byte *src) {
+void RMGfxSourceBuffer8RLEWord::rleWriteData(byte *&cur, int rep, byte *src) {
WRITE_LE_UINT16(cur, rep);
cur += 2;
@@ -1257,14 +1242,13 @@ void RMGfxSourceBuffer8RLEWord::RLEWriteData(byte *&cur, int rep, byte *src) {
}
}
-void RMGfxSourceBuffer8RLEWord::RLEWriteEOL(byte *&cur) {
+void RMGfxSourceBuffer8RLEWord::rleWriteEOL(byte *&cur) {
*cur ++ = 0xFF;
*cur ++ = 0xFF;
}
-void RMGfxSourceBuffer8RLEWord::RLEDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength) {
- int i, n;
- int r, g, b;
+void RMGfxSourceBuffer8RLEWord::rleDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength) {
+ int n;
if (nStartSkip == 0)
goto RLEWordDoTrasp;
@@ -1341,10 +1325,10 @@ RLEWordDoAlpha2:
if (n > nLength)
n = nLength;
- for (i = 0; i < n; i++) {
- r = (*dst >> 10) & 0x1F;
- g = (*dst >> 5) & 0x1F;
- b = *dst & 0x1F;
+ for (int i = 0; i < n; i++) {
+ int r = (*dst >> 10) & 0x1F;
+ int g = (*dst >> 5) & 0x1F;
+ int b = *dst & 0x1F;
r = (r >> 2) + (_alphaR >> 1);
g = (g >> 2) + (_alphaG >> 1);
@@ -1368,7 +1352,7 @@ RLEWordDoCopy2:
if (n > nLength)
n = nLength;
- for (i = 0; i < n; i++)
+ for (int i = 0; i < n; i++)
*dst++ = _palFinal[*src++];
nLength -= n;
@@ -1380,9 +1364,8 @@ RLEWordDoCopy2:
}
}
-void RMGfxSourceBuffer8RLEWord::RLEDecompressLineFlipped(uint16 *dst, byte *src, int nStartSkip, int nLength) {
- int i, n;
- int r, g, b;
+void RMGfxSourceBuffer8RLEWord::rleDecompressLineFlipped(uint16 *dst, byte *src, int nStartSkip, int nLength) {
+ int n;
if (nStartSkip == 0)
goto RLEWordFlippedDoTrasp;
@@ -1459,10 +1442,10 @@ RLEWordFlippedDoAlpha2:
if (n > nLength)
n = nLength;
- for (i = 0; i < n; i++) {
- r = (*dst >> 10) & 0x1F;
- g = (*dst >> 5) & 0x1F;
- b = *dst & 0x1F;
+ for (int i = 0; i < n; i++) {
+ int r = (*dst >> 10) & 0x1F;
+ int g = (*dst >> 5) & 0x1F;
+ int b = *dst & 0x1F;
r = (r >> 2) + (_alphaR >> 1);
g = (g >> 2) + (_alphaG >> 1);
@@ -1486,7 +1469,7 @@ RLEWordFlippedDoCopy2:
if (n > nLength)
n = nLength;
- for (i = 0; i < n; i++)
+ for (int i = 0; i < n; i++)
*dst-- = _palFinal[*src++];
nLength -= n;
@@ -1505,12 +1488,11 @@ RMGfxSourceBuffer8RLEWordAB::~RMGfxSourceBuffer8RLEWordAB() {
}
-void RMGfxSourceBuffer8RLEWordAB::RLEDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength) {
- int i, n;
- int r, g, b, r2, g2, b2;
+void RMGfxSourceBuffer8RLEWordAB::rleDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength) {
+ int n;
if (!GLOBALS._bCfgTransparence) {
- RMGfxSourceBuffer8RLEWord::RLEDecompressLine(dst, src, nStartSkip, nLength);
+ RMGfxSourceBuffer8RLEWord::rleDecompressLine(dst, src, nStartSkip, nLength);
return;
}
@@ -1590,10 +1572,10 @@ RLEWordDoAlpha2:
n = nLength;
// @@@ SHOULD NOT BE THERE !!!!!
- for (i = 0; i < n; i++) {
- r = (*dst >> 10) & 0x1F;
- g = (*dst >> 5) & 0x1F;
- b = *dst & 0x1F;
+ for (int i = 0; i < n; i++) {
+ int r = (*dst >> 10) & 0x1F;
+ int g = (*dst >> 5) & 0x1F;
+ int b = *dst & 0x1F;
r = (r >> 2) + (_alphaR >> 1);
g = (g >> 2) + (_alphaG >> 1);
@@ -1617,14 +1599,14 @@ RLEWordDoCopy2:
if (n > nLength)
n = nLength;
- for (i = 0; i < n; i++) {
- r = (*dst >> 10) & 0x1F;
- g = (*dst >> 5) & 0x1F;
- b = *dst & 0x1F;
+ for (int i = 0; i < n; i++) {
+ int r = (*dst >> 10) & 0x1F;
+ int g = (*dst >> 5) & 0x1F;
+ int b = *dst & 0x1F;
- r2 = (_palFinal[*src] >> 10) & 0x1F;
- g2 = (_palFinal[*src] >> 5) & 0x1F;
- b2 = _palFinal[*src] & 0x1F;
+ int r2 = (_palFinal[*src] >> 10) & 0x1F;
+ int g2 = (_palFinal[*src] >> 5) & 0x1F;
+ int b2 = _palFinal[*src] & 0x1F;
r = (r >> 1) + (r2 >> 1);
g = (g >> 1) + (g2 >> 1);
@@ -1658,7 +1640,6 @@ void RMGfxSourceBuffer8AA::prepareImage() {
}
void RMGfxSourceBuffer8AA::calculateAA() {
- int x, y;
byte *src, *srcaa;
// First pass: fill the edges
@@ -1666,8 +1647,8 @@ void RMGfxSourceBuffer8AA::calculateAA() {
src = _buf;
srcaa = _megaAABuf;
- for (y = 0; y < _dimy; y++) {
- for (x = 0; x < _dimx; x++) {
+ for (int y = 0; y < _dimy; y++) {
+ for (int x = 0; x < _dimx; x++) {
if (*src == 0) {
if ((y > 0 && src[-_dimx] != 0) ||
(y < _dimy - 1 && src[_dimx] != 0) ||
@@ -1683,8 +1664,8 @@ void RMGfxSourceBuffer8AA::calculateAA() {
src = _buf;
srcaa = _megaAABuf;
- for (y = 0; y < _dimy; y++) {
- for (x = 0; x < _dimx; x++) {
+ for (int y = 0; y < _dimy; y++) {
+ for (int x = 0; x < _dimx; x++) {
if (*src != 0) {
if ((y > 0 && srcaa[-_dimx] == 1) ||
(y < _dimy - 1 && srcaa[_dimx] == 1) ||
@@ -1715,23 +1696,20 @@ RMGfxSourceBuffer8AA::~RMGfxSourceBuffer8AA() {
}
void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
- int x, y;
byte *src;
uint16 *mybuf;
uint16 *buf;
- int x1, y1, u, v, width, height;
- int r, g, b;
- int step;
+ int u, v, width, height;
// Clip the sprite
- x1 = prim->getDst()._x1;
- y1 = prim->getDst()._y1;
+ int x1 = prim->getDst()._x1;
+ int y1 = prim->getDst()._y1;
if (!clip2D(x1, y1, u, v, width, height, false, &bigBuf))
return;
// Go forward through the RLE lines
src = _buf;
- for (y = 0; y < v; y++)
+ for (int y = 0; y < v; y++)
src += READ_LE_UINT16(src);
// Eliminate horizontal clipping
@@ -1758,6 +1736,7 @@ void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri
buf = bigBuf;
buf += y1 * bigBuf.getDimx();
+ int step;
if (prim->isFlipped())
step = -1;
else
@@ -1765,17 +1744,17 @@ void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri
// Loop
buf += bigBuf.getDimx(); // Skip the first line
- for (y = 1; y < height - 1; y++) {
+ for (int y = 1; y < height - 1; y++) {
// if (prim->IsFlipped())
// mybuf=&buf[x1+m_dimx-1];
// else
mybuf = &buf[x1];
- for (x = 0; x < width; x++, mybuf += step) {
+ for (int x = 0; x < width; x++, mybuf += step) {
if (_aabuf[(y + v) * _dimx + x + u] == 2 && x != 0 && x != width - 1) {
- r = GETRED(mybuf[1]) + GETRED(mybuf[-1]) + GETRED(mybuf[-bigBuf.getDimx()]) + GETRED(mybuf[bigBuf.getDimx()]);
- g = GETGREEN(mybuf[1]) + GETGREEN(mybuf[-1]) + GETGREEN(mybuf[-bigBuf.getDimx()]) + GETGREEN(mybuf[bigBuf.getDimx()]);
- b = GETBLUE(mybuf[1]) + GETBLUE(mybuf[-1]) + GETBLUE(mybuf[-bigBuf.getDimx()]) + GETBLUE(mybuf[bigBuf.getDimx()]);
+ int r = GETRED(mybuf[1]) + GETRED(mybuf[-1]) + GETRED(mybuf[-bigBuf.getDimx()]) + GETRED(mybuf[bigBuf.getDimx()]);
+ int g = GETGREEN(mybuf[1]) + GETGREEN(mybuf[-1]) + GETGREEN(mybuf[-bigBuf.getDimx()]) + GETGREEN(mybuf[bigBuf.getDimx()]);
+ int b = GETBLUE(mybuf[1]) + GETBLUE(mybuf[-1]) + GETBLUE(mybuf[-bigBuf.getDimx()]) + GETBLUE(mybuf[bigBuf.getDimx()]);
r += GETRED(mybuf[0]);
g += GETGREEN(mybuf[0]);
@@ -1785,9 +1764,12 @@ void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri
g /= 5;
b /= 5;
- if (r > 31) r = 31;
- if (g > 31) g = 31;
- if (b > 31) b = 31;
+ if (r > 31)
+ r = 31;
+ if (g > 31)
+ g = 31;
+ if (b > 31)
+ b = 31;
mybuf[0] = (r << 10) | (g << 5) | b;
}
@@ -1803,17 +1785,17 @@ void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri
// Looppone
buf += bigBuf.getDimx();
- for (y = 1; y < height - 1; y++) {
+ for (int y = 1; y < height - 1; y++) {
// if (prim->IsFlipped())
// mybuf=&buf[x1+m_dimx-1];
// else
mybuf = &buf[x1];
- for (x = 0; x < width; x++, mybuf += step) {
+ for (int x = 0; x < width; x++, mybuf += step) {
if (_aabuf[(y + v) * _dimx + x + u] == 1 && x != 0 && x != width - 1) {
- r = GETRED(mybuf[1]) + GETRED(mybuf[-1]) + GETRED(mybuf[-bigBuf.getDimx()]) + GETRED(mybuf[bigBuf.getDimx()]);
- g = GETGREEN(mybuf[1]) + GETGREEN(mybuf[-1]) + GETGREEN(mybuf[-bigBuf.getDimx()]) + GETGREEN(mybuf[bigBuf.getDimx()]);
- b = GETBLUE(mybuf[1]) + GETBLUE(mybuf[-1]) + GETBLUE(mybuf[-bigBuf.getDimx()]) + GETBLUE(mybuf[bigBuf.getDimx()]);
+ int r = GETRED(mybuf[1]) + GETRED(mybuf[-1]) + GETRED(mybuf[-bigBuf.getDimx()]) + GETRED(mybuf[bigBuf.getDimx()]);
+ int g = GETGREEN(mybuf[1]) + GETGREEN(mybuf[-1]) + GETGREEN(mybuf[-bigBuf.getDimx()]) + GETGREEN(mybuf[bigBuf.getDimx()]);
+ int b = GETBLUE(mybuf[1]) + GETBLUE(mybuf[-1]) + GETBLUE(mybuf[-bigBuf.getDimx()]) + GETBLUE(mybuf[bigBuf.getDimx()]);
r += GETRED(mybuf[0]) * 2;
g += GETGREEN(mybuf[0]) * 2;
@@ -1823,9 +1805,12 @@ void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri
g /= 6;
b /= 6;
- if (r > 31) r = 31;
- if (g > 31) g = 31;
- if (b > 31) b = 31;
+ if (r > 31)
+ r = 31;
+ if (g > 31)
+ g = 31;
+ if (b > 31)
+ b = 31;
mybuf[0] = (r << 10) | (g << 5) | b;
}
@@ -1941,16 +1926,13 @@ RMGfxSourceBuffer16::~RMGfxSourceBuffer16() {
void RMGfxSourceBuffer16::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
uint16 *buf = bigBuf;
uint16 *raw = (uint16 *)_buf;
- int dimx, dimy;
- int u, v;
- int x1, y1;
- dimx = _dimx;
- dimy = _dimy;
- u = 0;
- v = 0;
- x1 = 0;
- y1 = 0;
+ int dimx = _dimx;
+ int dimy = _dimy;
+ int u = 0;
+ int v = 0;
+ int x1 = 0;
+ int y1 = 0;
if (prim->haveSrc()) {
u = prim->getSrc()._x1;
@@ -1999,10 +1981,9 @@ void RMGfxSourceBuffer16::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimi
void RMGfxSourceBuffer16::prepareImage() {
// Color space conversion if necessary!
- int i;
uint16 *buf = (uint16 *)_buf;
- for (i = 0; i < _dimx * _dimy; i++)
+ for (int i = 0; i < _dimx * _dimy; i++)
WRITE_LE_UINT16(&buf[i], FROM_LE_16(buf[i]) & 0x7FFF);
}
@@ -2041,7 +2022,6 @@ void RMGfxBox::setColor(byte r, byte g, byte b) {
}
void RMGfxBox::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
- int i, j;
uint16 *buf = bigBuf;
RMRect rcDst;
@@ -2050,8 +2030,8 @@ void RMGfxBox::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim)
buf += rcDst._y1 * bigBuf.getDimx() + rcDst._x1;
// Loop through the pixels
- for (j = 0; j < rcDst.height(); j++) {
- for (i = 0; i < rcDst.width(); i++)
+ for (int j = 0; j < rcDst.height(); j++) {
+ for (int i = 0; i < rcDst.width(); i++)
*buf++ = _wFillColor;
buf += bigBuf.getDimx() - rcDst.width();
diff --git a/engines/tony/gfxcore.h b/engines/tony/gfxcore.h
index ac4eee05e4..f0deed83ee 100644
--- a/engines/tony/gfxcore.h
+++ b/engines/tony/gfxcore.h
@@ -146,7 +146,7 @@ public:
// Registration
virtual void Register();
- virtual void Unregister();
+ virtual void unregister();
};
@@ -303,12 +303,12 @@ protected:
protected:
static byte _megaRLEBuf[];
- virtual void RLEWriteTrasp(byte *&cur, int rep) = 0;
- virtual void RLEWriteData(byte *&cur, int rep, byte *src) = 0;
- virtual void RLEWriteEOL(byte *&cur) = 0;
- virtual void RLEWriteAlphaBlend(byte *&cur, int rep) = 0;
- virtual void RLEDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength) = 0;
- virtual void RLEDecompressLineFlipped(uint16 *dst, byte *src, int nStartSkip, int nLength) = 0;
+ virtual void rleWriteTrasp(byte *&cur, int rep) = 0;
+ virtual void rleWriteData(byte *&cur, int rep, byte *src) = 0;
+ virtual void rleWriteEOL(byte *&cur) = 0;
+ virtual void rleWriteAlphaBlend(byte *&cur, int rep) = 0;
+ virtual void rleDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength) = 0;
+ virtual void rleDecompressLineFlipped(uint16 *dst, byte *src, int nStartSkip, int nLength) = 0;
// Perform image compression in RLE
void compressRLE();
@@ -338,12 +338,12 @@ public:
class RMGfxSourceBuffer8RLEByte : public RMGfxSourceBuffer8RLE {
protected:
- void RLEWriteTrasp(byte * &cur, int rep);
- void RLEWriteAlphaBlend(byte * &cur, int rep);
- void RLEWriteData(byte * &cur, int rep, byte *src);
- void RLEWriteEOL(byte * &cur);
- void RLEDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength);
- void RLEDecompressLineFlipped(uint16 *dst, byte *src, int nStartSkip, int nLength);
+ void rleWriteTrasp(byte * &cur, int rep);
+ void rleWriteAlphaBlend(byte * &cur, int rep);
+ void rleWriteData(byte * &cur, int rep, byte *src);
+ void rleWriteEOL(byte * &cur);
+ void rleDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength);
+ void rleDecompressLineFlipped(uint16 *dst, byte *src, int nStartSkip, int nLength);
public:
virtual ~RMGfxSourceBuffer8RLEByte();
@@ -351,12 +351,12 @@ public:
class RMGfxSourceBuffer8RLEWord : public RMGfxSourceBuffer8RLE {
protected:
- void RLEWriteTrasp(byte * &cur, int rep);
- void RLEWriteAlphaBlend(byte * &cur, int rep);
- void RLEWriteData(byte * &cur, int rep, byte *src);
- void RLEWriteEOL(byte * &cur);
- virtual void RLEDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength);
- virtual void RLEDecompressLineFlipped(uint16 *dst, byte *src, int nStartSkip, int nLength);
+ void rleWriteTrasp(byte * &cur, int rep);
+ void rleWriteAlphaBlend(byte * &cur, int rep);
+ void rleWriteData(byte * &cur, int rep, byte *src);
+ void rleWriteEOL(byte * &cur);
+ virtual void rleDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength);
+ virtual void rleDecompressLineFlipped(uint16 *dst, byte *src, int nStartSkip, int nLength);
public:
virtual ~RMGfxSourceBuffer8RLEWord();
@@ -364,7 +364,7 @@ public:
class RMGfxSourceBuffer8RLEWordAB : public RMGfxSourceBuffer8RLEWord {
protected:
- virtual void RLEDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength);
+ virtual void rleDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength);
public:
virtual ~RMGfxSourceBuffer8RLEWordAB();
diff --git a/engines/tony/gfxengine.cpp b/engines/tony/gfxengine.cpp
index 5c038e154d..c81e553770 100644
--- a/engines/tony/gfxengine.cpp
+++ b/engines/tony/gfxengine.cpp
@@ -40,7 +40,7 @@ namespace Tony {
* RMGfxEngine Methods
\****************************************************************************/
-void ExitAllIdles(CORO_PARAM, const void *param) {
+void exitAllIdles(CORO_PARAM, const void *param) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
@@ -129,7 +129,7 @@ void RMGfxEngine::openOptionScreen(CORO_PARAM, int type) {
GLOBALS._bIdleExited = false;
- CoroScheduler.createProcess(ExitAllIdles, &_nCurLoc, sizeof(int));
+ CoroScheduler.createProcess(exitAllIdles, &_nCurLoc, sizeof(int));
}
}
@@ -394,13 +394,10 @@ void RMGfxEngine::initForNewLocation(int nLoc, RMPoint ptTonyStart, RMPoint star
}
uint32 RMGfxEngine::loadLocation(int nLoc, RMPoint ptTonyStart, RMPoint start) {
- bool bLoaded;
- int i;
-
_nCurLoc = nLoc;
- bLoaded = false;
- for (i = 0; i < 5; i++) {
+ bool bLoaded = false;
+ for (int i = 0; i < 5; i++) {
// Try the loading of the location
RMRes res(_nCurLoc);
if (!res.isValid())
@@ -532,36 +529,22 @@ void RMGfxEngine::disableMouse() {
_bAlwaysDrawMouse = false;
}
-void CharsSaveAll(Common::OutSaveFile *f);
-void CharsLoadAll(Common::InSaveFile *f);
-void MCharResetCodes();
-void SaveChangedHotspot(Common::OutSaveFile *f);
-void LoadChangedHotspot(Common::InSaveFile *f);
-void ReapplyChangedHotspot();
-
-void RestoreMusic(CORO_PARAM);
-void SaveMusic(Common::OutSaveFile *f);
-void LoadMusic(Common::InSaveFile *f);
-
#define TONY_SAVEGAME_VERSION 8
void RMGfxEngine::saveState(const Common::String &fn, byte *curThumb, const Common::String &name) {
Common::OutSaveFile *f;
byte *state;
- uint thumbsize;
- uint size;
- int i;
char buf[4];
RMPoint tp = _tony.position();
// Saving: MPAL variables, current location, and Tony inventory position
// For now, we only save the MPAL state
- size = mpalGetSaveStateSize();
+ uint size = mpalGetSaveStateSize();
state = new byte[size];
mpalSaveState(state);
- thumbsize = 160 * 120 * 2;
+ uint thumbsize = 160 * 120 * 2;
buf[0] = 'R';
buf[1] = 'M';
@@ -577,7 +560,7 @@ void RMGfxEngine::saveState(const Common::String &fn, byte *curThumb, const Comm
f->write(curThumb, thumbsize);
// Difficulty level
- i = mpalQueryGlobalVar("VERSIONEFACILE");
+ int i = mpalQueryGlobalVar("VERSIONEFACILE");
f->writeByte(i);
i = strlen(name.c_str());
@@ -608,16 +591,14 @@ void RMGfxEngine::saveState(const Common::String &fn, byte *curThumb, const Comm
delete[] state;
// New Ver5
- bool bStat;
-
// Saves the state of the shepherdess and show yourself
- bStat = _tony.getShepherdess();
+ bool bStat = _tony.getShepherdess();
f->writeByte(bStat);
bStat = _inter.getPerorate();
f->writeByte(bStat);
// Save the chars
- CharsSaveAll(f);
+ charsSaveAll(f);
// Save the options
f->writeByte(GLOBALS._bCfgInvLocked);
@@ -639,10 +620,10 @@ void RMGfxEngine::saveState(const Common::String &fn, byte *curThumb, const Comm
f->writeByte(GLOBALS._nCfgSFXVolume);
// Save the hotspots
- SaveChangedHotspot(f);
+ saveChangedHotspot(f);
// Save the music
- SaveMusic(f);
+ saveMusic(f);
f->finalize();
delete f;
@@ -653,7 +634,7 @@ void RMGfxEngine::loadState(CORO_PARAM, const Common::String &fn) {
CORO_BEGIN_CONTEXT;
Common::InSaveFile *f;
byte *state, *statecmp;
- uint size, sizecmp;
+ uint32 size, sizecmp;
char buf[4];
RMPoint tp;
int loc;
@@ -734,7 +715,7 @@ void RMGfxEngine::loadState(CORO_PARAM, const Common::String &fn) {
_inv.loadState(_ctx->state);
delete[] _ctx->state;
- if (_ctx->ver >= 0x2) { // Versione 2: box please
+ if (_ctx->ver >= 0x2) { // Version 2: box please
_ctx->size = _ctx->f->readUint32LE();
_ctx->state = new byte[_ctx->size];
_ctx->f->read(_ctx->state, _ctx->size);
@@ -743,7 +724,7 @@ void RMGfxEngine::loadState(CORO_PARAM, const Common::String &fn) {
}
if (_ctx->ver >= 5) {
- // Versione 5
+ // Version 5
bool bStat = false;
bStat = _ctx->f->readByte();
@@ -751,7 +732,7 @@ void RMGfxEngine::loadState(CORO_PARAM, const Common::String &fn) {
bStat = _ctx->f->readByte();
_inter.setPerorate(bStat);
- CharsLoadAll(_ctx->f);
+ charsLoadAll(_ctx->f);
}
if (_ctx->ver >= 6) {
@@ -775,11 +756,11 @@ void RMGfxEngine::loadState(CORO_PARAM, const Common::String &fn) {
GLOBALS._nCfgSFXVolume = _ctx->f->readByte();
// Load hotspots
- LoadChangedHotspot(_ctx->f);
+ loadChangedHotspot(_ctx->f);
}
if (_ctx->ver >= 7) {
- LoadMusic(_ctx->f);
+ loadMusic(_ctx->f);
}
delete _ctx->f;
@@ -793,13 +774,13 @@ void RMGfxEngine::loadState(CORO_PARAM, const Common::String &fn) {
mpalQueryDoAction(0, _ctx->loc, 0);
else {
// In the new ones, we just reset the mcode
- MCharResetCodes();
+ mCharResetCodes();
}
if (_ctx->ver >= 6)
- ReapplyChangedHotspot();
+ reapplyChangedHotspot();
- CORO_INVOKE_0(RestoreMusic);
+ CORO_INVOKE_0(restoreMusic);
_bGUIInterface = true;
_bGUIInventory = true;
diff --git a/engines/tony/inventory.cpp b/engines/tony/inventory.cpp
index 81d62a035c..12540e5b7f 100644
--- a/engines/tony/inventory.cpp
+++ b/engines/tony/inventory.cpp
@@ -73,9 +73,6 @@ bool RMInventory::checkPointInside(const RMPoint &pt) {
void RMInventory::init() {
- int i, j;
- int curres;
-
// Create the main buffer
create(RM_SX, 68);
setPriority(185);
@@ -89,10 +86,10 @@ void RMInventory::init() {
_nItems = 78; // @@@ Number of takeable items
_items = new RMInventoryItem[_nItems + 1];
- curres = 10500;
+ int curres = 10500;
// Loop through the items
- for (i = 0; i <= _nItems; i++) {
+ for (int i = 0; i <= _nItems; i++) {
// Load the items from the resource
RMRes res(curres);
assert(res.isValid());
@@ -115,7 +112,7 @@ void RMInventory::init() {
_items[i]._pointer = new RMGfxSourceBuffer8RLEByteAA[_items[i]._icon.numPattern()];
- for (j = 0; j < _items[i]._icon.numPattern(); j++) {
+ for (int j = 0; j < _items[i]._icon.numPattern(); j++) {
RMResRaw raw(curres);
assert(raw.isValid());
@@ -232,9 +229,7 @@ void RMInventory::removeThis(CORO_PARAM, bool &result) {
}
void RMInventory::removeItem(int code) {
- int i;
-
- for (i = 0; i < _nInv; i++)
+ for (int i = 0; i < _nInv; i++) {
if (_inv[i] == code - 10000) {
g_system->lockMutex(_csModifyInterface);
@@ -247,6 +242,7 @@ void RMInventory::removeItem(int code) {
g_system->unlockMutex(_csModifyInterface);
return;
}
+ }
}
void RMInventory::addItem(int code) {
@@ -286,9 +282,7 @@ void RMInventory::changeItemStatus(uint32 code, uint32 dwStatus) {
void RMInventory::prepare() {
- int i;
-
- for (i = 1; i < RM_SX / 64 - 1; i++) {
+ for (int i = 1; i < RM_SX / 64 - 1; i++) {
if (i - 1 + _curPos < _nInv)
addPrim(new RMGfxPrimitive(&_items[_inv[i - 1 + _curPos]]._icon, RMPoint(i * 64, 0)));
else
@@ -325,10 +319,8 @@ void RMInventory::endCombine() {
}
bool RMInventory::leftClick(const RMPoint &mpos, int &nCombineObj) {
- int n;
-
// The left click picks an item from your inventory to use it with the background
- n = mpos._x / 64;
+ int n = mpos._x / 64;
if (_state == OPENED) {
if (n > 0 && n < RM_SX / 64 - 1 && _inv[n - 1 + _curPos] != 0) {
@@ -679,18 +671,17 @@ RMItem *RMInventory::whichItemIsIn(const RMPoint &mpt) {
int RMInventory::getSaveStateSize() {
// m_inv pattern m_nInv
- return 256 * 4 + 256 * 4 + 4 ;
+ return 256 * 4 + 256 * 4 + 4;
}
void RMInventory::saveState(byte *state) {
- int i, x;
-
WRITE_LE_UINT32(state, _nInv);
state += 4;
Common::copy(_inv, _inv + 256, (uint32 *)state);
state += 256 * 4;
- for (i = 0; i < 256; i++) {
+ int x;
+ for (int i = 0; i < 256; i++) {
if (i < _nItems)
x = _items[i]._status;
else
@@ -702,14 +693,13 @@ void RMInventory::saveState(byte *state) {
}
int RMInventory::loadState(byte *state) {
- int i, x;
-
_nInv = READ_LE_UINT32(state);
state += 4;
Common::copy((uint32 *)state, (uint32 *)state + 256, _inv);
state += 256 * 4;
- for (i = 0; i < 256; i++) {
+ int x;
+ for (int i = 0; i < 256; i++) {
x = READ_LE_UINT32(state);
state += 4;
@@ -721,7 +711,7 @@ int RMInventory::loadState(byte *state) {
_curPos = 0;
_bCombining = false;
-
+
_items[29]._icon.setPattern(1);
if (_nInv > 8)
@@ -768,17 +758,15 @@ bool RMInterface::active() {
}
int RMInterface::onWhichBox(RMPoint pt) {
- int max, i;
-
pt -= _openStart;
// Check how many verbs you have to consider
- max = 4;
+ int max = 4;
if (_bPerorate)
max = 5;
// Find the verb
- for (i = 0; i < max; i++) {
+ for (int i = 0; i < max; i++) {
if (_hotbbox[i].ptInRect(pt))
return i;
}
@@ -895,7 +883,6 @@ bool RMInterface::getPerorate() {
}
void RMInterface::init() {
- int i;
RMResRaw inter(RES_I_INTERFACE);
RMRes pal(RES_I_INTERPPAL);
@@ -904,7 +891,7 @@ void RMInterface::init() {
RMGfxSourceBuffer::init(inter, inter.width(), inter.height());
loadPaletteWA(RES_I_INTERPAL);
- for (i = 0; i < 5; i++) {
+ for (int i = 0; i < 5; i++) {
RMResRaw part(RES_I_INTERP1 + i);
_hotzone[i].init(part, part.width(), part.height());
@@ -942,11 +929,9 @@ void RMInterface::init() {
}
void RMInterface::close() {
- int i;
-
destroy();
- for (i = 0; i < 5; i++)
+ for (int i = 0; i < 5; i++)
_hotzone[i].destroy();
}
diff --git a/engines/tony/loc.cpp b/engines/tony/loc.cpp
index 4fe19594f9..18470aa6fc 100644
--- a/engines/tony/loc.cpp
+++ b/engines/tony/loc.cpp
@@ -51,10 +51,8 @@ void RMPalette::readFromStream(Common::ReadStream &ds) {
\****************************************************************************/
void RMPattern::RMSlot::readFromStream(Common::ReadStream &ds, bool bLOX) {
- byte type;
-
// Type
- type = ds.readByte();
+ byte type = ds.readByte();
_type = (RMPattern::RMSlotType)type;
// Data
@@ -73,8 +71,6 @@ void RMPattern::RMSlot::readFromStream(Common::ReadStream &ds, bool bLOX) {
\****************************************************************************/
void RMPattern::readFromStream(Common::ReadStream &ds, bool bLOX) {
- int i;
-
// Pattern name
if (!bLOX)
_name = readString(ds);
@@ -94,7 +90,7 @@ void RMPattern::readFromStream(Common::ReadStream &ds, bool bLOX) {
// Create and read the slots
_slots = new RMSlot[_nSlots];
- for (i = 0; i < _nSlots && !ds.err(); i++) {
+ for (int i = 0; i < _nSlots && !ds.err(); i++) {
if (bLOX)
_slots[i].readFromStream(ds, true);
else
@@ -118,14 +114,12 @@ void RMPattern::stopSfx(RMSfx *sfx) {
}
int RMPattern::init(RMSfx *sfx, bool bPlayP0, byte *bFlag) {
- int i;
-
// Read the current time
_nStartTime = g_vm->getTime();
_nCurSlot = 0;
// Find the first frame of the pattern
- i = 0;
+ int i = 0;
while (_slots[i]._type != SPRITE) {
assert(i + 1 < _nSlots);
i++;
@@ -297,15 +291,13 @@ void RMSprite::getSizeFromStream(Common::SeekableReadStream &ds, int *dimx, int
}
void RMSprite::readFromStream(Common::SeekableReadStream &ds, bool bLOX) {
- int dimx, dimy;
-
// Sprite name
if (!bLOX)
_name = readString(ds);
// Dimensions
- dimx = ds.readSint32LE();
- dimy = ds.readSint32LE();
+ int dimx = ds.readSint32LE();
+ int dimy = ds.readSint32LE();
// Bounding box
_rcBox.readFromStream(ds);
@@ -343,12 +335,10 @@ RMSprite::~RMSprite() {
\****************************************************************************/
void RMSfx::readFromStream(Common::ReadStream &ds, bool bLOX) {
- int size;
-
// sfx name
_name = readString(ds);
- size = ds.readSint32LE();
+ int size = ds.readSint32LE();
// Read the entire buffer into a MemoryReadStream
byte *buffer = (byte *)malloc(size);
@@ -390,7 +380,7 @@ void RMSfx::setVolume(int vol) {
void RMSfx::pause(bool bPause) {
if (_fx) {
- _fx->pause(bPause);
+ _fx->setPause(bPause);
}
}
@@ -463,9 +453,6 @@ bool RMItem::isIn(const RMPoint &pt, int *size) {
}
void RMItem::readFromStream(Common::SeekableReadStream &ds, bool bLOX) {
- int i, dimx, dimy;
- byte cm;
-
// MPAL code
_mpalCode = ds.readSint32LE();
@@ -490,7 +477,7 @@ void RMItem::readFromStream(Common::SeekableReadStream &ds, bool bLOX) {
_nPatterns = ds.readSint32LE();
// Color mode
- cm = ds.readByte();
+ byte cm = ds.readByte();
_cm = (RMColorMode)cm;
// Flag for the presence of custom palette differences
@@ -519,9 +506,10 @@ void RMItem::readFromStream(Common::SeekableReadStream &ds, bool bLOX) {
_sfx = new RMSfx[_nSfx];
_patterns = new RMPattern[_nPatterns + 1];
+ int dimx, dimy;
// Read in class data
- if (!ds.err())
- for (i = 0; i < _nSprites && !ds.err(); i++) {
+ if (!ds.err()) {
+ for (int i = 0; i < _nSprites && !ds.err(); i++) {
// Download the sprites
if (bLOX) {
_sprites[i].LOXGetSizeFromStream(ds, &dimx, &dimy);
@@ -536,23 +524,26 @@ void RMItem::readFromStream(Common::SeekableReadStream &ds, bool bLOX) {
if (_cm == CM_256 && _bPal)
_sprites[i].setPalette(_pal._data);
}
+ }
- if (!ds.err())
- for (i = 0; i < _nSfx && !ds.err(); i++) {
+ if (!ds.err()) {
+ for (int i = 0; i < _nSfx && !ds.err(); i++) {
if (bLOX)
_sfx[i].readFromStream(ds, true);
else
_sfx[i].readFromStream(ds, false);
}
+ }
// Read the pattern from pattern 1
- if (!ds.err())
- for (i = 1; i <= _nPatterns && !ds.err(); i++) {
+ if (!ds.err()) {
+ for (int i = 1; i <= _nPatterns && !ds.err(); i++) {
if (bLOX)
_patterns[i].readFromStream(ds, true);
else
_patterns[i].readFromStream(ds, false);
}
+ }
// Initialize the current pattern
if (_bInitCurPattern)
@@ -662,7 +653,7 @@ void RMItem::setStatus(int nStatus) {
_bIsActive = (nStatus > 0);
}
-RMPoint RMItem::hotspot() {
+RMPoint RMItem::getHotspot() {
return _hot;
}
@@ -677,7 +668,7 @@ void RMItem::setPattern(int nPattern, bool bPlayP0) {
if (_nCurPattern > 0)
_patterns[_nCurPattern].stopSfx(_sfx);
}
-
+
// Remember the current pattern
_nCurPattern = nPattern;
@@ -789,14 +780,11 @@ void RMItem::playSfx(int nSfx) {
}
void RMItem::pauseSound(bool bPause) {
- int i;
-
- for (i = 0; i < _nSfx; i++)
+ for (int i = 0; i < _nSfx; i++)
_sfx[i].pause(bPause);
}
-
/****************************************************************************\
* RMWipe Methods
\****************************************************************************/
@@ -823,8 +811,8 @@ int RMWipe::priority() {
return 200;
}
-void RMWipe::Unregister() {
- RMGfxTask::Unregister();
+void RMWipe::unregister() {
+ RMGfxTask::unregister();
assert(_nInList == 0);
CoroScheduler.setEvent(_hUnregistered);
}
@@ -952,7 +940,7 @@ short RMCharacter::findPath(short source, short destination) {
error = 1; // Possible error
// 1st cycle: explore possible new nodes
- for (int i = 0; i < cur->_numbBox; i++)
+ for (int i = 0; i < cur->_numbBox; i++) {
if (valid[i] == 1) {
error = 0; // Failure de-bunked
int j = 0;
@@ -967,12 +955,13 @@ short RMCharacter::findPath(short source, short destination) {
minCost = nodeCost[i] + 1;
}
}
+ }
if (error)
finish = true; // All nodes saturated
// 2nd cycle: adding new nodes that were found, saturate old nodes
- for (int i = 0; i < cur->_numbBox; i++)
+ for (int i = 0; i < cur->_numbBox; i++) {
if ((valid[i] == 1) && ((nodeCost[i] + 1) == minCost)) {
box[i]._adj[nextNode[i]] = 2;
nodeCost[nextNode[i]] = minCost;
@@ -984,6 +973,7 @@ short RMCharacter::findPath(short source, short destination) {
if (nextNode[i] == destination)
finish = true;
}
+ }
}
// Remove the path from the adjacent modified matrixes
@@ -1079,91 +1069,91 @@ void RMCharacter::goTo(CORO_PARAM, RMPoint destcoord, bool bReversed) {
}
-RMPoint RMCharacter::searching(char UP, char DOWN, char RIGHT, char LEFT, RMPoint punto) {
- short passi, minimo;
- RMPoint nuovo, trovato;
- minimo = 32000;
+RMPoint RMCharacter::searching(char UP, char DOWN, char RIGHT, char LEFT, RMPoint point) {
+ short steps;
+ RMPoint newPt, foundPt;
+ short minStep = 32000;
if (UP) {
- nuovo = punto;
- passi = 0;
- while ((inWhichBox(nuovo) == -1) && (nuovo._y >= 0)) {
- nuovo._y--;
- passi++;
+ newPt = point;
+ steps = 0;
+ while ((inWhichBox(newPt) == -1) && (newPt._y >= 0)) {
+ newPt._y--;
+ steps++;
}
- if ((inWhichBox(nuovo) != -1) && (passi < minimo) &&
- findPath(inWhichBox(_pos), inWhichBox(nuovo))) {
- minimo = passi;
- nuovo._y--; // to avoid error?
- trovato = nuovo;
+ if ((inWhichBox(newPt) != -1) && (steps < minStep) &&
+ findPath(inWhichBox(_pos), inWhichBox(newPt))) {
+ minStep = steps;
+ newPt._y--; // to avoid error?
+ foundPt = newPt;
}
}
if (DOWN) {
- nuovo = punto;
- passi = 0;
- while ((inWhichBox(nuovo) == -1) && (nuovo._y < 480)) {
- nuovo._y++;
- passi++;
+ newPt = point;
+ steps = 0;
+ while ((inWhichBox(newPt) == -1) && (newPt._y < 480)) {
+ newPt._y++;
+ steps++;
}
- if ((inWhichBox(nuovo) != -1) && (passi < minimo) &&
- findPath(inWhichBox(_pos), inWhichBox(nuovo))) {
- minimo = passi;
- nuovo._y++; // to avoid error?
- trovato = nuovo;
+ if ((inWhichBox(newPt) != -1) && (steps < minStep) &&
+ findPath(inWhichBox(_pos), inWhichBox(newPt))) {
+ minStep = steps;
+ newPt._y++; // to avoid error?
+ foundPt = newPt;
}
}
if (RIGHT) {
- nuovo = punto;
- passi = 0;
- while ((inWhichBox(nuovo) == -1) && (nuovo._x < 640)) {
- nuovo._x++;
- passi++;
+ newPt = point;
+ steps = 0;
+ while ((inWhichBox(newPt) == -1) && (newPt._x < 640)) {
+ newPt._x++;
+ steps++;
}
- if ((inWhichBox(nuovo) != -1) && (passi < minimo) &&
- findPath(inWhichBox(_pos), inWhichBox(nuovo))) {
- minimo = passi;
- nuovo._x++; // to avoid error?
- trovato = nuovo;
+ if ((inWhichBox(newPt) != -1) && (steps < minStep) &&
+ findPath(inWhichBox(_pos), inWhichBox(newPt))) {
+ minStep = steps;
+ newPt._x++; // to avoid error?
+ foundPt = newPt;
}
}
if (LEFT) {
- nuovo = punto;
- passi = 0;
- while ((inWhichBox(nuovo) == -1) && (nuovo._x >= 0)) {
- nuovo._x--;
- passi++;
+ newPt = point;
+ steps = 0;
+ while ((inWhichBox(newPt) == -1) && (newPt._x >= 0)) {
+ newPt._x--;
+ steps++;
}
- if ((inWhichBox(nuovo) != -1) && (passi < minimo) &&
- findPath(inWhichBox(_pos), inWhichBox(nuovo))) {
- minimo = passi;
- nuovo._x--; // to avoid error?
- trovato = nuovo;
+ if ((inWhichBox(newPt) != -1) && (steps < minStep) &&
+ findPath(inWhichBox(_pos), inWhichBox(newPt))) {
+ minStep = steps;
+ newPt._x--; // to avoid error?
+ foundPt = newPt;
}
}
- if (minimo == 32000)
- trovato = punto;
+ if (minStep == 32000)
+ foundPt = point;
- return trovato;
+ return foundPt;
}
-RMPoint RMCharacter::nearestPoint(const RMPoint &punto) {
- return searching(1, 1, 1, 1, punto);
+RMPoint RMCharacter::nearestPoint(const RMPoint &point) {
+ return searching(1, 1, 1, 1, point);
}
-short RMCharacter::scanLine(const RMPoint &punto) {
+short RMCharacter::scanLine(const RMPoint &point) {
int Ldx, Ldy, Lcount;
float Lfx, Lfy, Lslope;
RMPoint Lstart, Lend, Lscan;
signed char Lspeed, Lstatus;
Lstart = _pos;
- Lend = punto;
+ Lend = point;
Ldx = Lstart._x - Lend._x;
Ldy = Lstart._y - Lend._y;
Lfx = Ldx;
@@ -1209,60 +1199,60 @@ short RMCharacter::scanLine(const RMPoint &punto) {
/**
* Calculates intersections between the straight line and the closest BBOX
*/
-RMPoint RMCharacter::invScanLine(const RMPoint &punto) {
- int Ldx, Ldy, Lcount;
- float Lfx, Lfy, Lslope;
- RMPoint Lstart, Lend, Lscan;
- signed char Lspeed, Lstatus, Lbox = -1;
-
- Lstart = punto; // Exchange!
- Lend = _pos; // :-)
- Ldx = Lstart._x - Lend._x;
- Ldy = Lstart._y - Lend._y;
- Lfx = Ldx;
- Lfy = Ldy;
- Ldx = ABS(Ldx);
- Ldy = ABS(Ldy);
- Lspeed = 1;
- Lcount = 0;
-
- if (Ldx > Ldy) {
- Lslope = Lfy / Lfx;
- if (Lend._x < Lstart._x)
- Lspeed = -Lspeed;
- Lstatus = 1;
+RMPoint RMCharacter::invScanLine(const RMPoint &point) {
+ RMPoint lStart = point; // Exchange!
+ RMPoint lEnd = _pos; // :-)
+ int lDx = lStart._x - lEnd._x;
+ int lDy = lStart._y - lEnd._y;
+ float lFx = lDx;
+ float lFy = lDy;
+ lDx = ABS(lDx);
+ lDy = ABS(lDy);
+ signed char lSpeed = 1;
+ int lCount = 0;
+
+ signed char lStatus;
+ float lSlope;
+
+ if (lDx > lDy) {
+ lSlope = lFy / lFx;
+ if (lEnd._x < lStart._x)
+ lSpeed = -lSpeed;
+ lStatus = 1;
} else {
- Lslope = Lfx / Lfy;
- if (Lend._y < Lstart._y)
- Lspeed = -Lspeed;
- Lstatus = 0;
+ lSlope = lFx / lFy;
+ if (lEnd._y < lStart._y)
+ lSpeed = -lSpeed;
+ lStatus = 0;
}
- Lscan = Lstart;
+
+ RMPoint lScan = lStart;
+ signed char lBox = -1;
for (;;) {
- if (inWhichBox(Lscan) != -1) {
- if (inWhichBox(Lscan) != Lbox) {
- if (inWhichBox(_pos) == inWhichBox(Lscan) || findPath(inWhichBox(_pos), inWhichBox(Lscan)))
- return Lscan;
+ if (inWhichBox(lScan) != -1) {
+ if (inWhichBox(lScan) != lBox) {
+ if (inWhichBox(_pos) == inWhichBox(lScan) || findPath(inWhichBox(_pos), inWhichBox(lScan)))
+ return lScan;
else
- Lbox = inWhichBox(Lscan);
+ lBox = inWhichBox(lScan);
}
}
- Lcount++;
- if (Lstatus) {
- Ldx = Lspeed * Lcount;
- Ldy = (int)(Lslope * Ldx);
+ lCount++;
+ if (lStatus) {
+ lDx = lSpeed * lCount;
+ lDy = (int)(lSlope * lDx);
} else {
- Ldy = Lspeed * Lcount;
- Ldx = (int)(Lslope * Ldy);
+ lDy = lSpeed * lCount;
+ lDx = (int)(lSlope * lDy);
}
- Lscan._x = Lstart._x + Ldx;
- Lscan._y = Lstart._y + Ldy;
+ lScan._x = lStart._x + lDx;
+ lScan._y = lStart._y + lDy;
// WORKAROUND: Handles cases where the points never fall inside a bounding box
- if (Lscan._x < -100 || Lscan._y < -100 || Lscan._x >= 1000 || Lscan._y >= 1000)
- return punto;
+ if (lScan._x < -100 || lScan._y < -100 || lScan._x >= 1000 || lScan._y >= 1000)
+ return point;
}
}
@@ -1272,25 +1262,24 @@ RMPoint RMCharacter::invScanLine(const RMPoint &punto) {
*/
RMPoint RMCharacter::nearestHotSpot(int sourcebox, int destbox) {
- RMPoint puntocaldo;
- short cc;
- int x, y, distanzaminima;
- distanzaminima = 10000000;
+ RMPoint hotspot;
+ int x, y;
+ int minDist = 10000000;
RMBoxLoc *cur = _theBoxes->getBoxes(_curLocation);
- for (cc = 0; cc < cur->_boxes[sourcebox]._numHotspot; cc++)
+ for (short cc = 0; cc < cur->_boxes[sourcebox]._numHotspot; cc++)
if ((cur->_boxes[sourcebox]._hotspot[cc]._destination) == destbox) {
x = ABS(cur->_boxes[sourcebox]._hotspot[cc]._hotx - _pos._x);
y = ABS(cur->_boxes[sourcebox]._hotspot[cc]._hoty - _pos._y);
- if ((x * x + y * y) < distanzaminima) {
- distanzaminima = x * x + y * y;
- puntocaldo._x = cur->_boxes[sourcebox]._hotspot[cc]._hotx;
- puntocaldo._y = cur->_boxes[sourcebox]._hotspot[cc]._hoty;
+ if ((x * x + y * y) < minDist) {
+ minDist = x * x + y * y;
+ hotspot._x = cur->_boxes[sourcebox]._hotspot[cc]._hotx;
+ hotspot._y = cur->_boxes[sourcebox]._hotspot[cc]._hoty;
}
}
- return puntocaldo;
+ return hotspot;
}
void RMCharacter::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
@@ -1310,13 +1299,12 @@ void RMCharacter::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pr
void RMCharacter::newBoxEntered(int nBox) {
RMBoxLoc *cur;
- bool bOldReverse;
// Recall on ExitBox
mpalQueryDoAction(3, _curLocation, _curBox);
cur = _theBoxes->getBoxes(_curLocation);
- bOldReverse = cur->_boxes[_curBox]._bReversed;
+ bool bOldReverse = cur->_boxes[_curBox]._bReversed;
_curBox = nBox;
// If Z is changed, we must remove it from the OT
@@ -1673,7 +1661,7 @@ RMCharacter::RMCharacter() {
_bMovingWithoutMinpath = false;
_bDrawNow = false;
_bNeedToStop = false;
-
+
memset(_path, 0, sizeof(_path));
_pos.set(0, 0);
@@ -1693,10 +1681,6 @@ void RMCharacter::linkToBoxes(RMGameBoxes *boxes) {
\****************************************************************************/
void RMBox::readFromStream(Common::ReadStream &ds) {
- uint16 w;
- int i;
- byte b;
-
// Bbox
_left = ds.readSint32LE();
_top = ds.readSint32LE();
@@ -1704,24 +1688,25 @@ void RMBox::readFromStream(Common::ReadStream &ds) {
_bottom = ds.readSint32LE();
// Adjacency
- for (i = 0; i < MAXBOXES; i++) {
+ for (int i = 0; i < MAXBOXES; i++) {
_adj[i] = ds.readSint32LE();
}
// Misc
_numHotspot = ds.readSint32LE();
_destZ = ds.readByte();
- b = ds.readByte();
+ byte b = ds.readByte();
_bActive = b;
b = ds.readByte();
_bReversed = b;
// Reversed expansion space
- for (i = 0; i < 30; i++)
+ for (int i = 0; i < 30; i++)
ds.readByte();
+ uint16 w;
// Hotspots
- for (i = 0; i < _numHotspot; i++) {
+ for (int i = 0; i < _numHotspot; i++) {
w = ds.readUint16LE();
_hotspot[i]._hotx = w;
w = ds.readUint16LE();
@@ -1745,14 +1730,12 @@ RMBoxLoc::~RMBoxLoc() {
}
void RMBoxLoc::readFromStream(Common::ReadStream &ds) {
- int i;
char buf[2];
- byte ver;
// ID and version
buf[0] = ds.readByte();
buf[1] = ds.readByte();
- ver = ds.readByte();
+ byte ver = ds.readByte();
assert(buf[0] == 'B' && buf[1] == 'X');
assert(ver == 3);
@@ -1763,19 +1746,18 @@ void RMBoxLoc::readFromStream(Common::ReadStream &ds) {
_boxes = new RMBox[_numbBox];
// Read in boxes
- for (i = 0; i < _numbBox; i++)
+ for (int i = 0; i < _numbBox; i++)
_boxes[i].readFromStream(ds);
}
void RMBoxLoc::recalcAllAdj() {
- int i, j;
-
- for (i = 0; i < _numbBox; i++) {
+ for (int i = 0; i < _numbBox; i++) {
Common::fill(_boxes[i]._adj, _boxes[i]._adj + MAXBOXES, 0);
- for (j = 0; j < _boxes[i]._numHotspot; j++)
+ for (int j = 0; j < _boxes[i]._numHotspot; j++) {
if (_boxes[_boxes[i]._hotspot[j]._destination]._bActive)
_boxes[i]._adj[_boxes[i]._hotspot[j]._destination] = 1;
+ }
}
}
@@ -1794,11 +1776,9 @@ RMGameBoxes::~RMGameBoxes() {
}
void RMGameBoxes::init() {
- int i;
-
// Load boxes from disk
_nLocBoxes = 130;
- for (i = 1; i <= _nLocBoxes; i++) {
+ for (int i = 1; i <= _nLocBoxes; i++) {
RMRes res(10000 + i);
Common::SeekableReadStream *ds = res.getReadStream();
@@ -1834,13 +1814,12 @@ bool RMGameBoxes::isInBox(int nLoc, int nBox, const RMPoint &pt) {
}
int RMGameBoxes::whichBox(int nLoc, const RMPoint &punto) {
- int i;
RMBoxLoc *cur = getBoxes(nLoc);
if (!cur)
return -1;
- for (i = 0; i < cur->_numbBox; i++) {
+ for (int i = 0; i < cur->_numbBox; i++) {
if (cur->_boxes[i]._bActive) {
if ((punto._x >= cur->_boxes[i]._left) && (punto._x <= cur->_boxes[i]._right) &&
(punto._y >= cur->_boxes[i]._top) && (punto._y <= cur->_boxes[i]._bottom))
@@ -1857,12 +1836,9 @@ void RMGameBoxes::changeBoxStatus(int nLoc, int nBox, int status) {
}
int RMGameBoxes::getSaveStateSize() {
- int size;
- int i;
+ int size = 4;
- size = 4;
-
- for (i = 1; i <= _nLocBoxes; i++) {
+ for (int i = 1; i <= _nLocBoxes; i++) {
size += 4;
size += _allBoxes[i]->_numbBox;
}
@@ -1871,38 +1847,34 @@ int RMGameBoxes::getSaveStateSize() {
}
void RMGameBoxes::saveState(byte *state) {
- int i, j;
-
// Save the number of locations with boxes
WRITE_LE_UINT32(state, _nLocBoxes);
state += 4;
// For each location, write out the number of boxes and their status
- for (i = 1; i <= _nLocBoxes; i++) {
+ for (int i = 1; i <= _nLocBoxes; i++) {
WRITE_LE_UINT32(state, _allBoxes[i]->_numbBox);
state += 4;
- for (j = 0; j < _allBoxes[i]->_numbBox; j++)
+ for (int j = 0; j < _allBoxes[i]->_numbBox; j++)
*state++ = _allBoxes[i]->_boxes[j]._bActive;
}
}
void RMGameBoxes::loadState(byte *state) {
- int i, j;
- int nloc, nbox;
-
// Load number of items
- nloc = READ_LE_UINT32(state);
+ int nloc = READ_LE_UINT32(state);
state += 4;
assert(nloc <= _nLocBoxes);
+ int nbox;
// For each location, read the number of boxes and their status
- for (i = 1; i <= nloc; i++) {
+ for (int i = 1; i <= nloc; i++) {
nbox = READ_LE_UINT32(state);
state += 4;
- for (j = 0; j < nbox ; j++) {
+ for (int j = 0; j < nbox ; j++) {
if (j < _allBoxes[i]->_numbBox)
_allBoxes[i]->_boxes[j]._bActive = *state;
@@ -1944,10 +1916,6 @@ int RMLocation::TEMPGetNumLoc() {
*/
bool RMLocation::load(Common::SeekableReadStream &ds) {
char id[3];
- int dimx, dimy;
- byte ver;
- byte cm;
- int i;
// Reset dirty rectangling
_prevScroll.set(-1, -1);
@@ -1965,7 +1933,7 @@ bool RMLocation::load(Common::SeekableReadStream &ds) {
return false;
// Version
- ver = ds.readByte();
+ byte ver = ds.readByte();
assert(ver == 6);
// Location name
@@ -1981,12 +1949,12 @@ bool RMLocation::load(Common::SeekableReadStream &ds) {
ds.skip(1);
// Location dimensions
- dimx = ds.readSint32LE();
- dimy = ds.readSint32LE();
+ int dimx = ds.readSint32LE();
+ int dimy = ds.readSint32LE();
_curScroll.set(0, 0);
// Read the color mode
- cm = ds.readByte();
+ byte cm = ds.readByte();
_cmode = (RMColorMode)cm;
// Initialize the source buffer and read the location
@@ -2019,7 +1987,7 @@ bool RMLocation::load(Common::SeekableReadStream &ds) {
g_vm->freezeTime();
- for (i = 0; i < _nItems && !ds.err(); i++)
+ for (int i = 0; i < _nItems && !ds.err(); i++)
_items[i].readFromStream(ds);
g_vm->unfreezeTime();
@@ -2028,12 +1996,8 @@ bool RMLocation::load(Common::SeekableReadStream &ds) {
bool RMLocation::loadLOX(Common::SeekableReadStream &ds) {
- int dimx, dimy;
- byte ver;
- int i;
-
// Version
- ver = ds.readByte();
+ byte ver = ds.readByte();
assert(ver == 1);
// Location name
@@ -2045,8 +2009,8 @@ bool RMLocation::loadLOX(Common::SeekableReadStream &ds) {
TEMPTonyStart._y = ds.readSint32LE();
// Dimensions
- dimx = ds.readSint32LE();
- dimy = ds.readSint32LE();
+ int dimx = ds.readSint32LE();
+ int dimy = ds.readSint32LE();
_curScroll.set(0, 0);
// It's always 65K (16-bit) mode
@@ -2063,7 +2027,7 @@ bool RMLocation::loadLOX(Common::SeekableReadStream &ds) {
if (_nItems > 0)
_items = new RMItem[_nItems];
- for (i = 0; i < _nItems && !ds.err(); i++)
+ for (int i = 0; i < _nItems && !ds.err(); i++)
_items[i].readFromStream(ds, true);
return ds.err();
@@ -2111,22 +2075,18 @@ void RMLocation::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri
* Prepare a frame, adding the location to the OT list, and all the items that have changed animation frame.
*/
void RMLocation::doFrame(RMGfxTargetBuffer *bigBuf) {
- int i;
-
// If the location is not in the OT list, add it in
if (!_nInList)
bigBuf->addPrim(new RMGfxPrimitive(this));
// Process all the location items
- for (i = 0; i < _nItems; i++)
+ for (int i = 0; i < _nItems; i++)
_items[i].doFrame(bigBuf);
}
RMItem *RMLocation::getItemFromCode(uint32 dwCode) {
- int i;
-
- for (i = 0; i < _nItems; i++) {
+ for (int i = 0; i < _nItems; i++) {
if (_items[i].mpalCode() == (int)dwCode)
return &_items[i];
}
@@ -2239,9 +2199,7 @@ void RMLocation::setScrollPosition(const RMPoint &scroll) {
void RMLocation::pauseSound(bool bPause) {
- int i;
-
- for (i = 0; i < _nItems; i++)
+ for (int i = 0; i < _nItems; i++)
_items[i].pauseSound(bPause);
}
diff --git a/engines/tony/loc.h b/engines/tony/loc.h
index 61eece2440..04ba772458 100644
--- a/engines/tony/loc.h
+++ b/engines/tony/loc.h
@@ -256,7 +256,7 @@ public:
void setStatus(int nStatus);
bool isIn(const RMPoint &pt, int *size = NULL);
- RMPoint hotspot();
+ RMPoint getHotspot();
bool getName(Common::String &name);
int mpalCode();
@@ -403,12 +403,12 @@ private:
int inWhichBox(const RMPoint &pt);
short findPath(short source, short destination);
- RMPoint searching(char UP, char DOWN, char RIGHT, char LEFT, RMPoint punto);
+ RMPoint searching(char UP, char DOWN, char RIGHT, char LEFT, RMPoint point);
RMPoint nearestPoint(const RMPoint &punto);
void goTo(CORO_PARAM, RMPoint destcoord, bool bReversed = false);
- short scanLine(const RMPoint &punto);
- RMPoint invScanLine(const RMPoint &punto);
+ short scanLine(const RMPoint &point);
+ RMPoint invScanLine(const RMPoint &point);
RMPoint nearestHotSpot(int sourcebox, int destbox);
void newBoxEntered(int nBox);
@@ -478,7 +478,7 @@ public:
void closeFade();
void waitForFadeEnd(CORO_PARAM);
- virtual void Unregister();
+ virtual void unregister();
virtual void removeThis(CORO_PARAM, bool &result);
virtual int priority();
};
diff --git a/engines/tony/mpal/expr.cpp b/engines/tony/mpal/expr.cpp
index 7923d263c0..824cd91651 100644
--- a/engines/tony/mpal/expr.cpp
+++ b/engines/tony/mpal/expr.cpp
@@ -35,68 +35,6 @@ namespace Tony {
namespace MPAL {
-/**
- * @defgroup Mathamatical operations
- */
-//@{
-
-#define OP_MUL ((1 << 4) | 0)
-#define OP_DIV ((1 << 4) | 1)
-#define OP_MODULE ((1 << 4) | 2)
-#define OP_ADD ((2 << 4) | 0)
-#define OP_SUB ((2 << 4) | 1)
-#define OP_SHL ((3 << 4) | 0)
-#define OP_SHR ((3 << 4) | 1)
-#define OP_MINOR ((4 << 4) | 0)
-#define OP_MAJOR ((4 << 4) | 1)
-#define OP_MINEQ ((4 << 4) | 2)
-#define OP_MAJEQ ((4 << 4) | 3)
-#define OP_EQUAL ((5 << 4) | 0)
-#define OP_NOEQUAL ((5 << 4) | 1)
-#define OP_BITAND ((6 << 4) | 0)
-#define OP_BITXOR ((7 << 4) | 0)
-#define OP_BITOR ((8 << 4) | 0)
-#define OP_AND ((9 << 4) | 0)
-#define OP_OR ((10 << 4) | 0)
-
-
-/**
- * Object types that can be contained in an EXPRESSION structure
- */
-enum ExprListTypes {
- ELT_NUMBER = 1,
- ELT_VAR = 2,
- ELT_PARENTH = 3,
- ELT_PARENTH2 = 4
-};
-
-//@}
-
-/**
- * @defgroup Structures
- */
-//@{
-
-/**
- * Mathamatical framework to manage operations
- */
-typedef struct {
- byte _type; // Tipo di oggetto (vedi enum ExprListTypes)
- byte _unary; // Unary operatore (NON SUPPORTATO)
-
- union {
- int _num; // Numero (se type==ELT_NUMBER)
- char *_name; // Nome variabile (se type==ELT_VAR)
- MpalHandle _son; // Handle a espressione (type==ELT_PARENTH)
- byte *_pson; // Handle lockato (type==ELT_PARENTH2)
- } _val;
-
- byte _symbol; // Simbolo matematico (vedi #define OP_*)
-
-} Expression;
-typedef Expression *LpExpression;
-
-//@}
/**
* Duplicate a mathematical expression.
@@ -106,15 +44,14 @@ typedef Expression *LpExpression;
*/
static byte *duplicateExpression(MpalHandle h) {
byte *orig, *clone;
- LpExpression one, two;
orig = (byte *)globalLock(h);
int num = *(byte *)orig;
- one = (LpExpression)(orig+1);
+ LpExpression one = (LpExpression)(orig+1);
clone = (byte *)globalAlloc(GMEM_FIXED, sizeof(Expression) * num + 1);
- two = (LpExpression)(clone + 1);
+ LpExpression two = (LpExpression)(clone + 1);
memcpy(clone, orig, sizeof(Expression) * num + 1);
@@ -180,7 +117,6 @@ static int Compute(int a, int b, byte symbol) {
static void solve(LpExpression one, int num) {
LpExpression two, three;
- int j;
while (num > 1) {
two = one + 1;
@@ -189,7 +125,7 @@ static void solve(LpExpression one, int num) {
memmove(one, two, (num - 1) * sizeof(Expression));
--num;
} else {
- j = 1;
+ int j = 1;
three = two + 1;
while ((three->_symbol != 0) && (two->_symbol & 0xF0) > (three->_symbol & 0xF0)) {
++two;
@@ -213,13 +149,11 @@ static void solve(LpExpression one, int num) {
* @returns Value
*/
static int evaluateAndFreeExpression(byte *expr) {
- LpExpression one, cur;
-
int num = *expr;
- one = (LpExpression)(expr + 1);
+ LpExpression one = (LpExpression)(expr + 1);
// 1) Substitutions of variables
- cur = one;
+ LpExpression cur = one;
for (int i = 0; i < num; i++, cur++) {
if (cur->_type == ELT_VAR) {
cur->_type = ELT_NUMBER;
@@ -254,7 +188,6 @@ static int evaluateAndFreeExpression(byte *expr) {
* @returns Pointer to the buffer immediately after the expression, or NULL if error.
*/
const byte *parseExpression(const byte *lpBuf, MpalHandle *h) {
- LpExpression cur;
byte *start;
uint32 num = *lpBuf;
@@ -270,12 +203,14 @@ const byte *parseExpression(const byte *lpBuf, MpalHandle *h) {
start = (byte *)globalLock(*h);
*start = (byte)num;
- cur = (LpExpression)(start + 1);
+ LpExpression cur = (LpExpression)(start + 1);
for (uint32 i = 0;i < num; i++) {
cur->_type = *(lpBuf);
- cur->_unary = *(lpBuf + 1);
+
+ // *(lpBuf + 1) contains the unary operator, unused => skipped
lpBuf += 2;
+
switch (cur->_type) {
case ELT_NUMBER:
cur->_val._num = (int32)READ_LE_UINT32(lpBuf);
@@ -322,10 +257,8 @@ const byte *parseExpression(const byte *lpBuf, MpalHandle *h) {
* @returns Numeric value
*/
int evaluateExpression(MpalHandle h) {
- int ret;
-
lockVar();
- ret = evaluateAndFreeExpression(duplicateExpression(h));
+ int ret = evaluateAndFreeExpression(duplicateExpression(h));
unlockVar();
return ret;
@@ -339,7 +272,6 @@ int evaluateExpression(MpalHandle h) {
*/
bool compareExpressions(MpalHandle h1, MpalHandle h2) {
byte *e1, *e2;
- LpExpression one, two;
e1 = (byte *)globalLock(h1);
e2 = (byte *)globalLock(h2);
@@ -353,8 +285,8 @@ bool compareExpressions(MpalHandle h1, MpalHandle h2) {
return false;
}
- one = (LpExpression)(e1 + 1);
- two = (LpExpression)(e2 + 1);
+ LpExpression one = (LpExpression)(e1 + 1);
+ LpExpression two = (LpExpression)(e2 + 1);
for (int i = 0; i < num1; i++) {
if (one->_type != two->_type || (i != num1 - 1 && one->_symbol != two->_symbol)) {
diff --git a/engines/tony/mpal/expr.h b/engines/tony/mpal/expr.h
index 9036099993..405624b4fe 100644
--- a/engines/tony/mpal/expr.h
+++ b/engines/tony/mpal/expr.h
@@ -35,6 +35,67 @@ namespace Tony {
namespace MPAL {
+/**
+ * @defgroup Mathamatical operations
+ */
+//@{
+
+#define OP_MUL ((1 << 4) | 0)
+#define OP_DIV ((1 << 4) | 1)
+#define OP_MODULE ((1 << 4) | 2)
+#define OP_ADD ((2 << 4) | 0)
+#define OP_SUB ((2 << 4) | 1)
+#define OP_SHL ((3 << 4) | 0)
+#define OP_SHR ((3 << 4) | 1)
+#define OP_MINOR ((4 << 4) | 0)
+#define OP_MAJOR ((4 << 4) | 1)
+#define OP_MINEQ ((4 << 4) | 2)
+#define OP_MAJEQ ((4 << 4) | 3)
+#define OP_EQUAL ((5 << 4) | 0)
+#define OP_NOEQUAL ((5 << 4) | 1)
+#define OP_BITAND ((6 << 4) | 0)
+#define OP_BITXOR ((7 << 4) | 0)
+#define OP_BITOR ((8 << 4) | 0)
+#define OP_AND ((9 << 4) | 0)
+#define OP_OR ((10 << 4) | 0)
+
+//@}
+
+/**
+ * @defgroup Structures
+ */
+
+//@{
+/**
+ * Mathamatical framework to manage operations
+ */
+typedef struct {
+ byte _type; // Object Type (see enum ExprListTypes)
+
+ union {
+ int _num; // Identifier (if type == ELT_NUMBER)
+ char *_name; // Variable name (if type == ELT_VAR)
+ MpalHandle _son; // Handle expressions (if type == ELT_PARENTH)
+ byte *_pson; // Handle lockato (if type == ELT_PARENTH2)
+ } _val;
+
+ byte _symbol; // Mathematic symbols (see #define OP_*)
+
+} Expression;
+typedef Expression *LpExpression;
+
+//@}
+
+/**
+ * Object types that can be contained in an EXPRESSION structure
+ */
+enum ExprListTypes {
+ ELT_NUMBER = 1,
+ ELT_VAR = 2,
+ ELT_PARENTH = 3,
+ ELT_PARENTH2 = 4
+};
+
/****************************************************************************\
* Function Prototypes
\****************************************************************************/
diff --git a/engines/tony/mpal/loadmpc.cpp b/engines/tony/mpal/loadmpc.cpp
index 953820be74..9c45cdf982 100644
--- a/engines/tony/mpal/loadmpc.cpp
+++ b/engines/tony/mpal/loadmpc.cpp
@@ -139,7 +139,6 @@ static void FreeScript(LpMpalScript lpmsScript) {
* @returns Pointer to the buffer after the item, or NULL on failure.
*/
static const byte *parseDialog(const byte *lpBuf, LpMpalDialog lpmdDialog) {
- uint32 num2, num3;
byte *lpLock;
lpmdDialog->_nObj = READ_LE_UINT32(lpBuf);
@@ -266,7 +265,7 @@ static const byte *parseDialog(const byte *lpBuf, LpMpalDialog lpmdDialog) {
lpmdDialog->_choice[i]._nChoice = READ_LE_UINT16(lpBuf);
lpBuf += 2;
- num2 = *lpBuf++;
+ uint32 num2 = *lpBuf++;
if (num2 >= MAX_SELECTS_PER_CHOICE)
error("Too much selects in choice #%d in dialog #%d", lpmdDialog->_choice[i]._nChoice, lpmdDialog->_nObj);
@@ -296,7 +295,7 @@ static const byte *parseDialog(const byte *lpBuf, LpMpalDialog lpmdDialog) {
lpBuf += 4;
// PlayGroup
- num3 = *lpBuf++;
+ uint32 num3 = *lpBuf++;
if (num3 >= MAX_PLAYGROUPS_PER_SELECT)
error("Too much playgroups in select #%d in choice #%d in dialog #%d", j, lpmdDialog->_choice[i]._nChoice, lpmdDialog->_nObj);
@@ -365,7 +364,6 @@ static const byte *parseItem(const byte *lpBuf, LpMpalItem lpmiItem) {
lpBuf++;
}
-
if (*lpBuf == 0) {
lpBuf++;
lpmiItem->_action[i]._when = NULL;
diff --git a/engines/tony/mpal/memory.cpp b/engines/tony/mpal/memory.cpp
index 428c07b3b7..dfbf16e789 100644
--- a/engines/tony/mpal/memory.cpp
+++ b/engines/tony/mpal/memory.cpp
@@ -33,8 +33,6 @@ namespace MPAL {
* MemoryManager methods
\****************************************************************************/
-const uint32 BLOCK_ID = 0x12345678;
-
/**
* Allocates a new memory block
* @return Returns a MemoryItem instance for the new block
@@ -64,7 +62,7 @@ void *MemoryManager::alloc(uint32 size, uint flags) {
return &item->_data[0];
}
-#define OFFSETOF(type, field) ((unsigned long) &(((type *) 0)->field))
+#define OFFSETOF(type, field) ((size_t) &(((type *) 0)->field))
/**
* Returns a reference to the MemoryItem for a gien byte pointer
diff --git a/engines/tony/mpal/memory.h b/engines/tony/mpal/memory.h
index ba7865938f..9c21cc20e6 100644
--- a/engines/tony/mpal/memory.h
+++ b/engines/tony/mpal/memory.h
@@ -69,6 +69,8 @@ public:
#define GMEM_MOVEABLE 2
#define GMEM_ZEROINIT 4
+const uint32 BLOCK_ID = 0x12345678;
+
} // end of namespace MPAL
} // end of namespace Tony
diff --git a/engines/tony/mpal/mpal.cpp b/engines/tony/mpal/mpal.cpp
index 10f5753540..8d83363c24 100644
--- a/engines/tony/mpal/mpal.cpp
+++ b/engines/tony/mpal/mpal.cpp
@@ -39,19 +39,6 @@ namespace Tony {
namespace MPAL {
-#define GETARG(type) va_arg(v, type)
-
-/****************************************************************************\
-* Copyright
-\****************************************************************************/
-
-const char *mpalCopyright =
- "\n\nMPAL - MultiPurpose Adventure Language for Windows 95\n"
- "Copyright 1997-98 Giovanni Bajo and Luca Giusti\n"
- "ALL RIGHTS RESERVED\n"
- "\n"
- "\n";
-
/****************************************************************************\
* Internal functions
\****************************************************************************/
@@ -363,24 +350,22 @@ static char *duplicateDialogPeriod(uint32 nPeriod) {
MpalHandle resLoad(uint32 dwId) {
MpalHandle h;
char head[4];
- uint32 nBytesRead;
- uint32 nSizeComp, nSizeDecomp;
byte *temp, *buf;
for (int i = 0; i < GLOBALS._nResources; i++)
if (GLOBALS._lpResources[i * 2] == dwId) {
GLOBALS._hMpr.seek(GLOBALS._lpResources[i * 2 + 1]);
- nBytesRead = GLOBALS._hMpr.read(head, 4);
+ uint32 nBytesRead = GLOBALS._hMpr.read(head, 4);
if (nBytesRead != 4)
return NULL;
if (head[0] != 'R' || head[1] != 'E' || head[2] != 'S' || head[3] != 'D')
return NULL;
- nSizeDecomp = GLOBALS._hMpr.readUint32LE();
+ uint32 nSizeDecomp = GLOBALS._hMpr.readUint32LE();
if (GLOBALS._hMpr.err())
return NULL;
- nSizeComp = GLOBALS._hMpr.readUint32LE();
+ uint32 nSizeComp = GLOBALS._hMpr.readUint32LE();
if (GLOBALS._hMpr.err())
return NULL;
@@ -463,18 +448,16 @@ static uint32 *GetItemList(uint32 nLoc) {
static LpItem getItemData(uint32 nOrdItem) {
LpMpalItem curitem = GLOBALS._lpmiItems + nOrdItem;
- LpItem ret;
- MpalHandle hDat;
char *dat;
char *patlength;
// Zeroing out the allocated memory is required!!!
- ret = (LpItem)globalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(Item));
+ LpItem ret = (LpItem)globalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(Item));
if (ret == NULL)
return NULL;
ret->_speed = 150;
- hDat = resLoad(curitem->_dwRes);
+ MpalHandle hDat = resLoad(curitem->_dwRes);
dat = (char *)globalLock(hDat);
if (dat[0] == 'D' && dat[1] == 'A' && dat[2] == 'T') {
@@ -659,6 +642,9 @@ void ScriptThread(CORO_PARAM, const void *param) {
CORO_KILL_SELF();
return;
}
+
+ // WORKAROUND: Wait for events to pulse.
+ CORO_SLEEP(1);
}
}
@@ -727,6 +713,9 @@ void ActionThread(CORO_PARAM, const void *param) {
GLOBALS._mpalError = 1;
break;
}
+
+ // WORKAROUND: Wait for events to pulse.
+ CORO_SLEEP(1);
}
globalDestroy(_ctx->item);
@@ -1138,6 +1127,9 @@ void GroupThread(CORO_PARAM, const void *param) {
CORO_KILL_SELF();
return;
}
+
+ // WORKAROUND: Wait for events to pulse.
+ CORO_SLEEP(1);
}
// The gruop is finished, so we can return to the calling function.
@@ -1403,11 +1395,7 @@ bool doSelection(uint32 i, uint32 dwData) {
*/
bool mpalInit(const char *lpszMpcFileName, const char *lpszMprFileName,
LPLPCUSTOMFUNCTION lplpcfArray, Common::String *lpcfStrings) {
- Common::File hMpc;
byte buf[5];
- uint32 nBytesRead;
- bool bCompress;
- uint32 dwSizeDecomp, dwSizeComp;
byte *cmpbuf;
// Save the array of custom functions
@@ -1415,21 +1403,22 @@ bool mpalInit(const char *lpszMpcFileName, const char *lpszMprFileName,
GLOBALS._lplpFunctionStrings = lpcfStrings;
// OPen the MPC file for reading
+ Common::File hMpc;
if (!hMpc.open(lpszMpcFileName))
return false;
// Read and check the header
- nBytesRead = hMpc.read(buf, 5);
+ uint32 nBytesRead = hMpc.read(buf, 5);
if (nBytesRead != 5)
return false;
if (buf[0] != 'M' || buf[1] != 'P' || buf[2] != 'C' || buf[3] != 0x20)
return false;
- bCompress = buf[4];
+ bool bCompress = buf[4];
// Reads the size of the uncompressed file, and allocate memory
- dwSizeDecomp = hMpc.readUint32LE();
+ uint32 dwSizeDecomp = hMpc.readUint32LE();
if (hMpc.err())
return false;
@@ -1439,7 +1428,7 @@ bool mpalInit(const char *lpszMpcFileName, const char *lpszMprFileName,
if (bCompress) {
// Get the compressed size and read the data in
- dwSizeComp = hMpc.readUint32LE();
+ uint32 dwSizeComp = hMpc.readUint32LE();
if (hMpc.err())
return false;
@@ -1480,7 +1469,7 @@ bool mpalInit(const char *lpszMpcFileName, const char *lpszMprFileName,
// Seek to the end of the file to read overall information
GLOBALS._hMpr.seek(-12, SEEK_END);
- dwSizeComp = GLOBALS._hMpr.readUint32LE();
+ uint32 dwSizeComp = GLOBALS._hMpr.readUint32LE();
if (GLOBALS._hMpr.err())
return false;
@@ -1958,11 +1947,9 @@ uint32 mpalGetError() {
* @returns TRUE if the script 'was launched, FALSE on failure
*/
bool mpalExecuteScript(int nScript) {
- LpMpalScript s;
-
LockScripts();
int n = scriptGetOrderFromNum(nScript);
- s = (LpMpalScript)globalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(MpalScript));
+ LpMpalScript s = (LpMpalScript)globalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(MpalScript));
if (s == NULL)
return false;
diff --git a/engines/tony/mpal/mpal.h b/engines/tony/mpal/mpal.h
index c5f505063f..5e1b02b3fc 100644
--- a/engines/tony/mpal/mpal.h
+++ b/engines/tony/mpal/mpal.h
@@ -102,6 +102,8 @@ namespace MPAL {
#define MAXPATTERN 40 // pattern of animation of an object
#define MAXPOLLINGLOCATIONS 64
+#define GETARG(type) va_arg(v, type)
+
/**
* Macro for use with queries that may refer to X and Y co-ordinates
*/
diff --git a/engines/tony/mpal/mpalutils.cpp b/engines/tony/mpal/mpalutils.cpp
index 92d4af37fc..0919aed5ac 100644
--- a/engines/tony/mpal/mpalutils.cpp
+++ b/engines/tony/mpal/mpalutils.cpp
@@ -81,7 +81,7 @@ Common::SeekableReadStream *RMRes::getReadStream() {
}
bool RMRes::isValid() {
- return _h != NULL;
+ return _h != NULL;
}
/****************************************************************************\
diff --git a/engines/tony/mpal/mpalutils.h b/engines/tony/mpal/mpalutils.h
index 629e157e29..d92bb6f9a2 100644
--- a/engines/tony/mpal/mpalutils.h
+++ b/engines/tony/mpal/mpalutils.h
@@ -59,7 +59,7 @@ class RMResRaw : public RMRes {
public:
RMResRaw(uint32 resID);
virtual ~RMResRaw();
-
+
const byte *dataPointer();
operator const byte*();
diff --git a/engines/tony/sound.cpp b/engines/tony/sound.cpp
index 2c2c280eb2..20386d6353 100644
--- a/engines/tony/sound.cpp
+++ b/engines/tony/sound.cpp
@@ -45,7 +45,7 @@ namespace Tony {
*
*/
FPSound::FPSound() {
- _bSoundSupported = false;
+ _soundSupported = false;
}
/**
@@ -54,8 +54,8 @@ FPSound::FPSound() {
* @returns True is everything is OK, False otherwise
*/
bool FPSound::init() {
- _bSoundSupported = g_system->getMixer()->isReady();
- return _bSoundSupported;
+ _soundSupported = g_system->getMixer()->isReady();
+ return _soundSupported;
}
/**
@@ -69,55 +69,55 @@ FPSound::~FPSound() {
/**
* Allocates an object of type FPStream, and return its pointer
*
- * @param lplpStream Will contain a pointer to the object you just created.
+ * @param streamPtr Will contain a pointer to the object you just created.
*
* @returns True is everything is OK, False otherwise
*/
-bool FPSound::createStream(FPStream **lplpStream) {
- (*lplpStream) = new FPStream(_bSoundSupported);
+bool FPSound::createStream(FPStream **streamPtr) {
+ (*streamPtr) = new FPStream(_soundSupported);
- return (*lplpStream != NULL);
+ return (*streamPtr != NULL);
}
/**
* Allocates an object of type FpSfx, and return its pointer
*
- * @param lplpSfx Will contain a pointer to the object you just created.
+ * @param soundPtr Will contain a pointer to the object you just created.
*
* @returns True is everything is OK, False otherwise
*/
-bool FPSound::createSfx(FPSfx **lplpSfx) {
- (*lplpSfx) = new FPSfx(_bSoundSupported);
+bool FPSound::createSfx(FPSfx **sfxPtr) {
+ (*sfxPtr) = new FPSfx(_soundSupported);
- return (*lplpSfx != NULL);
+ return (*sfxPtr != NULL);
}
/**
* Set the general volume
*
- * @param dwVolume Volume to set (0-63)
+ * @param volume Volume to set (0-63)
*/
-void FPSound::setMasterVolume(int dwVolume) {
- if (!_bSoundSupported)
+void FPSound::setMasterVolume(int volume) {
+ if (!_soundSupported)
return;
- g_system->getMixer()->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, CLIP<int>(dwVolume, 0, 63) * Audio::Mixer::kMaxChannelVolume / 63);
+ g_system->getMixer()->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, CLIP<int>(volume, 0, 63) * Audio::Mixer::kMaxChannelVolume / 63);
}
/**
* Get the general volume
*
- * @param lpdwVolume Variable that will contain the volume (0-63)
+ * @param volumePtr Variable that will contain the volume (0-63)
*/
-void FPSound::getMasterVolume(int *lpdwVolume) {
- if (!_bSoundSupported)
+void FPSound::getMasterVolume(int *volumePtr) {
+ if (!_soundSupported)
return;
- *lpdwVolume = g_system->getMixer()->getVolumeForSoundType(Audio::Mixer::kPlainSoundType) * 63 / Audio::Mixer::kMaxChannelVolume;
+ *volumePtr = g_system->getMixer()->getVolumeForSoundType(Audio::Mixer::kPlainSoundType) * 63 / Audio::Mixer::kMaxChannelVolume;
}
/**
@@ -128,15 +128,15 @@ void FPSound::getMasterVolume(int *lpdwVolume) {
*
*/
-FPSfx::FPSfx(bool bSoundOn) {
- _bSoundSupported = bSoundOn;
- _bFileLoaded = false;
+FPSfx::FPSfx(bool soundOn) {
+ _soundSupported = soundOn;
+ _fileLoaded = false;
_lastVolume = 63;
_hEndOfBuffer = CoroScheduler.createEvent(true, false);
- _bIsVoice = false;
+ _isVoice = false;
_loopStream = 0;
_rewindableStream = 0;
- _bPaused = false;
+ _paused = false;
g_vm->_activeSfx.push_back(this);
}
@@ -150,7 +150,7 @@ FPSfx::FPSfx(bool bSoundOn) {
*/
FPSfx::~FPSfx() {
- if (!_bSoundSupported)
+ if (!_soundSupported)
return;
g_system->getMixer()->stopHandle(_handle);
@@ -187,22 +187,22 @@ bool FPSfx::loadWave(Common::SeekableReadStream *stream) {
if (!_rewindableStream)
return false;
- _bFileLoaded = true;
+ _fileLoaded = true;
setVolume(_lastVolume);
return true;
}
bool FPSfx::loadVoiceFromVDB(Common::File &vdbFP) {
- if (!_bSoundSupported)
+ if (!_soundSupported)
return true;
uint32 size = vdbFP.readUint32LE();
uint32 rate = vdbFP.readUint32LE();
- _bIsVoice = true;
+ _isVoice = true;
_rewindableStream = Audio::makeADPCMStream(vdbFP.readStream(size), DisposeAfterUse::YES, 0, Audio::kADPCMDVI, rate, 1);
- _bFileLoaded = true;
+ _fileLoaded = true;
setVolume(62);
return true;
}
@@ -210,18 +210,18 @@ bool FPSfx::loadVoiceFromVDB(Common::File &vdbFP) {
/**
* Opens a file and loads a sound effect.
*
- * @param lpszFileName Sfx filename
- * @param dwCodec CODEC used to uncompress the samples
+ * @param fileName Sfx filename
+ * @param codec CODEC used to uncompress the samples
*
* @returns True is everything is OK, False otherwise
*/
-bool FPSfx::loadFile(const char *lpszFileName, uint32 dwCodec) {
- if (!_bSoundSupported)
+bool FPSfx::loadFile(const char *fileName, uint32 codec) {
+ if (!_soundSupported)
return true;
Common::File file;
- if (!file.open(lpszFileName)) {
+ if (!file.open(fileName)) {
warning("FPSfx::LoadFile(): Cannot open sfx file!");
return false;
}
@@ -236,7 +236,7 @@ bool FPSfx::loadFile(const char *lpszFileName, uint32 dwCodec) {
Common::SeekableReadStream *buffer = file.readStream(file.size() - file.pos());
- if (dwCodec == FPCODEC_ADPCM) {
+ if (codec == FPCODEC_ADPCM) {
_rewindableStream = Audio::makeADPCMStream(buffer, DisposeAfterUse::YES, 0, Audio::kADPCMDVI, rate, channels);
} else {
byte flags = Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN;
@@ -247,7 +247,7 @@ bool FPSfx::loadFile(const char *lpszFileName, uint32 dwCodec) {
_rewindableStream = Audio::makeRawStream(buffer, rate, flags, DisposeAfterUse::YES);
}
- _bFileLoaded = true;
+ _fileLoaded = true;
return true;
}
@@ -260,14 +260,14 @@ bool FPSfx::loadFile(const char *lpszFileName, uint32 dwCodec) {
bool FPSfx::play() {
stop(); // sanity check
- if (_bFileLoaded) {
+ if (_fileLoaded) {
CoroScheduler.resetEvent(_hEndOfBuffer);
_rewindableStream->rewind();
Audio::AudioStream *stream = _rewindableStream;
- if (_bLoop) {
+ if (_loop) {
if (!_loopStream)
_loopStream = Audio::makeLoopingAudioStream(_rewindableStream, 0);
@@ -279,7 +279,7 @@ bool FPSfx::play() {
setVolume(_lastVolume);
- if (_bPaused)
+ if (_paused)
g_system->getMixer()->pauseHandle(_handle, true);
}
@@ -293,9 +293,9 @@ bool FPSfx::play() {
*/
bool FPSfx::stop() {
- if (_bFileLoaded) {
+ if (_fileLoaded) {
g_system->getMixer()->stopHandle(_handle);
- _bPaused = false;
+ _paused = false;
}
return true;
@@ -304,15 +304,15 @@ bool FPSfx::stop() {
/**
* Enables or disables the Sfx loop.
*
- * @param _bLoop True to enable the loop, False to disable
+ * @param loop True to enable the loop, False to disable
*
* @remarks The loop must be activated BEFORE the sfx starts
* playing. Any changes made during the play will have
* no effect until the sfx is stopped then played again.
*/
-void FPSfx::setLoop(bool bLop) {
- _bLoop = bLop;
+void FPSfx::setLoop(bool loop) {
+ _loop = loop;
}
/**
@@ -320,65 +320,65 @@ void FPSfx::setLoop(bool bLop) {
*
*/
-void FPSfx::pause(bool bPause) {
- if (_bFileLoaded) {
- if (g_system->getMixer()->isSoundHandleActive(_handle) && (bPause ^ _bPaused))
- g_system->getMixer()->pauseHandle(_handle, bPause);
+void FPSfx::setPause(bool pause) {
+ if (_fileLoaded) {
+ if (g_system->getMixer()->isSoundHandleActive(_handle) && (pause ^ _paused))
+ g_system->getMixer()->pauseHandle(_handle, pause);
- _bPaused = bPause;
+ _paused = pause;
}
}
/**
* Change the volume of Sfx
*
- * @param dwVolume Volume to be set (0-63)
+ * @param volume Volume to be set (0-63)
*
*/
-void FPSfx::setVolume(int dwVolume) {
- if (dwVolume > 63)
- dwVolume = 63;
+void FPSfx::setVolume(int volume) {
+ if (volume > 63)
+ volume = 63;
- if (dwVolume < 0)
- dwVolume = 0;
+ if (volume < 0)
+ volume = 0;
- _lastVolume = dwVolume;
+ _lastVolume = volume;
- if (_bIsVoice) {
+ if (_isVoice) {
if (!GLOBALS._bCfgDubbing)
- dwVolume = 0;
+ volume = 0;
else {
- dwVolume -= (10 - GLOBALS._nCfgDubbingVolume) * 2;
- if (dwVolume < 0)
- dwVolume = 0;
+ volume -= (10 - GLOBALS._nCfgDubbingVolume) * 2;
+ if (volume < 0)
+ volume = 0;
}
} else {
if (!GLOBALS._bCfgSFX)
- dwVolume = 0;
+ volume = 0;
else {
- dwVolume -= (10 - GLOBALS._nCfgSFXVolume) * 2;
- if (dwVolume < 0)
- dwVolume = 0;
+ volume -= (10 - GLOBALS._nCfgSFXVolume) * 2;
+ if (volume < 0)
+ volume = 0;
}
}
if (g_system->getMixer()->isSoundHandleActive(_handle))
- g_system->getMixer()->setChannelVolume(_handle, dwVolume * Audio::Mixer::kMaxChannelVolume / 63);
+ g_system->getMixer()->setChannelVolume(_handle, volume * Audio::Mixer::kMaxChannelVolume / 63);
}
/**
* Gets the Sfx volume
*
- * @param lpdwVolume Will contain the current Sfx volume
+ * @param volumePtr Will contain the current Sfx volume
*
*/
-void FPSfx::getVolume(int *lpdwVolume) {
+void FPSfx::getVolume(int *volumePtr) {
if (g_system->getMixer()->isSoundHandleActive(_handle))
- *lpdwVolume = g_system->getMixer()->getChannelVolume(_handle) * 63 / Audio::Mixer::kMaxChannelVolume;
+ *volumePtr = g_system->getMixer()->getChannelVolume(_handle) * 63 / Audio::Mixer::kMaxChannelVolume;
else
- *lpdwVolume = 0;
+ *volumePtr = 0;
}
/**
@@ -421,14 +421,14 @@ void FPSfx::soundCheckProcess(CORO_PARAM, const void *param) {
* @remarks Do *NOT* declare an object directly, but rather
* create it using FPSound::CreateStream()
*/
-FPStream::FPStream(bool bSoundOn) {
- _bSoundSupported = bSoundOn;
- _bFileLoaded = false;
- _bPaused = false;
- _bLoop = false;
- _bDoFadeOut = false;
- _bSyncExit = false;
- _dwBufferSize = _dwSize = 0;
+FPStream::FPStream(bool soundOn) {
+ _soundSupported = soundOn;
+ _fileLoaded = false;
+ _paused = false;
+ _loop = false;
+ _doFadeOut = false;
+ _syncExit = false;
+ _bufferSize = _size = 0;
_lastVolume = 0;
_syncToPlay = NULL;
_loopStream = NULL;
@@ -442,13 +442,13 @@ FPStream::FPStream(bool bSoundOn) {
*/
FPStream::~FPStream() {
- if (!_bSoundSupported)
+ if (!_soundSupported)
return;
if (g_system->getMixer()->isSoundHandleActive(_handle))
stop();
- if (_bFileLoaded)
+ if (_fileLoaded)
unloadFile();
_syncToPlay = NULL;
@@ -470,31 +470,32 @@ void FPStream::release() {
* Opens a file stream
*
* @param fileName Filename to be opened
- * @param dwCodec CODEC to be used to uncompress samples
+ * @param codec CODEC to be used to uncompress samples
*
* @returns True is everything is OK, False otherwise
*/
-bool FPStream::loadFile(const Common::String &fileName, uint32 dwCodType, int nBufSize) {
- if (!_bSoundSupported)
+bool FPStream::loadFile(const Common::String &fileName, uint32 codec, int bufSize) {
+ if (!_soundSupported)
return true;
- if (_bFileLoaded)
+ if (_fileLoaded)
unloadFile();
// Save the codec type
- _dwCodec = dwCodType;
+ _codec = codec;
// Open the file stream for reading
if (!_file.open(fileName)) {
// Fallback: try with an extra '0' prefix
if (!_file.open("0" + fileName))
return false;
+ warning("FPStream::loadFile(): Fallback from %s to %s", fileName.c_str(), _file.getName());
}
// Save the size of the stream
- _dwSize = _file.size();
+ _size = _file.size();
- switch (_dwCodec) {
+ switch (_codec) {
case FPCODEC_RAW:
_rewindableStream = Audio::makeRawStream(&_file, 44100, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN | Audio::FLAG_STEREO, DisposeAfterUse::NO);
break;
@@ -509,8 +510,8 @@ bool FPStream::loadFile(const Common::String &fileName, uint32 dwCodType, int nB
}
// All done
- _bFileLoaded = true;
- _bPaused = false;
+ _fileLoaded = true;
+ _paused = false;
setVolume(63);
@@ -527,7 +528,7 @@ bool FPStream::loadFile(const Common::String &fileName, uint32 dwCodType, int nB
* memory used by the stream.
*/
bool FPStream::unloadFile() {
- if (!_bSoundSupported || !_bFileLoaded)
+ if (!_soundSupported || !_fileLoaded)
return true;
assert(!g_system->getMixer()->isSoundHandleActive(_handle));
@@ -540,7 +541,7 @@ bool FPStream::unloadFile() {
_file.close();
// Flag that the file is no longer in memory
- _bFileLoaded = false;
+ _fileLoaded = false;
return true;
}
@@ -552,7 +553,7 @@ bool FPStream::unloadFile() {
*/
bool FPStream::play() {
- if (!_bSoundSupported || !_bFileLoaded)
+ if (!_soundSupported || !_fileLoaded)
return false;
stop();
@@ -561,7 +562,7 @@ bool FPStream::play() {
Audio::AudioStream *stream = _rewindableStream;
- if (_bLoop) {
+ if (_loop) {
if (!_loopStream)
_loopStream = new Audio::LoopingAudioStream(_rewindableStream, 0, DisposeAfterUse::NO);
@@ -571,7 +572,7 @@ bool FPStream::play() {
// FIXME: Should this be kMusicSoundType or KPlainSoundType?
g_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType, &_handle, stream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
setVolume(_lastVolume);
- _bPaused = false;
+ _paused = false;
return true;
}
@@ -584,10 +585,10 @@ bool FPStream::play() {
*/
bool FPStream::stop() {
- if (!_bSoundSupported)
+ if (!_soundSupported)
return true;
- if (!_bFileLoaded)
+ if (!_fileLoaded)
return false;
if (!g_system->getMixer()->isSoundHandleActive(_handle))
@@ -595,49 +596,49 @@ bool FPStream::stop() {
g_system->getMixer()->stopHandle(_handle);
- _bPaused = false;
+ _paused = false;
return true;
}
-void FPStream::waitForSync(FPStream *toplay) {
+void FPStream::waitForSync(FPStream *toPlay) {
// FIXME: The idea here is that you wait for this stream to reach
// a buffer which is a multiple of nBufSize/nSync, and then the
// thread stops it and immediately starts the 'toplay' stream.
stop();
- toplay->play();
+ toPlay->play();
}
/**
* Unables or disables stream loop.
*
- * @param _bLoop True enable loop, False disables it
+ * @param loop True enable loop, False disables it
*
* @remarks The loop must be activated BEFORE the stream starts
* playing. Any changes made during the play will have no
* effect until the stream is stopped then played again.
*/
void FPStream::setLoop(bool loop) {
- _bLoop = loop;
+ _loop = loop;
}
/**
* Pause sound effect
*
- * @param bPause True enables pause, False disables it
+ * @param pause True enables pause, False disables it
*/
-void FPStream::pause(bool bPause) {
- if (!_bFileLoaded)
+void FPStream::setPause(bool pause) {
+ if (!_fileLoaded)
return;
- if (bPause == _bPaused)
+ if (pause == _paused)
return;
if (g_system->getMixer()->isSoundHandleActive(_handle))
- g_system->getMixer()->pauseHandle(_handle, bPause);
+ g_system->getMixer()->pauseHandle(_handle, pause);
- _bPaused = bPause;
+ _paused = pause;
// Trick to reset the volume after a possible new sound configuration
setVolume(_lastVolume);
@@ -646,43 +647,43 @@ void FPStream::pause(bool bPause) {
/**
* Change the volume of the stream
*
- * @param dwVolume Volume to be set (0-63)
+ * @param volume Volume to be set (0-63)
*
*/
-void FPStream::setVolume(int dwVolume) {
- if (dwVolume > 63)
- dwVolume = 63;
+void FPStream::setVolume(int volume) {
+ if (volume > 63)
+ volume = 63;
- if (dwVolume < 0)
- dwVolume = 0;
+ if (volume < 0)
+ volume = 0;
- _lastVolume = dwVolume;
+ _lastVolume = volume;
if (!GLOBALS._bCfgMusic)
- dwVolume = 0;
+ volume = 0;
else {
- dwVolume -= (10 - GLOBALS._nCfgMusicVolume) * 2;
- if (dwVolume < 0)
- dwVolume = 0;
+ volume -= (10 - GLOBALS._nCfgMusicVolume) * 2;
+ if (volume < 0)
+ volume = 0;
}
if (g_system->getMixer()->isSoundHandleActive(_handle))
- g_system->getMixer()->setChannelVolume(_handle, dwVolume * Audio::Mixer::kMaxChannelVolume / 63);
+ g_system->getMixer()->setChannelVolume(_handle, volume * Audio::Mixer::kMaxChannelVolume / 63);
}
/**
* Gets the volume of the stream
*
- * @param lpdwVolume Variable that will contain the current volume
+ * @param volumePtr Variable that will contain the current volume
*
*/
-void FPStream::getVolume(int *lpdwVolume) {
+void FPStream::getVolume(int *volumePtr) {
if (g_system->getMixer()->isSoundHandleActive(_handle))
- *lpdwVolume = g_system->getMixer()->getChannelVolume(_handle) * 63 / Audio::Mixer::kMaxChannelVolume;
+ *volumePtr = g_system->getMixer()->getChannelVolume(_handle) * 63 / Audio::Mixer::kMaxChannelVolume;
else
- *lpdwVolume = 0;
+ *volumePtr = 0;
}
} // End of namespace Tony
diff --git a/engines/tony/sound.h b/engines/tony/sound.h
index c859f781f4..7422de02b3 100644
--- a/engines/tony/sound.h
+++ b/engines/tony/sound.h
@@ -55,7 +55,7 @@ enum SoundCodecs {
class FPSound {
private:
- bool _bSoundSupported;
+ bool _soundSupported;
public:
/**
@@ -83,49 +83,49 @@ public:
/**
* Allocates an object of type FPStream, and return its pointer
*
- * @param lplpStream Will contain a pointer to the object you just created.
+ * @param streamPtr Will contain a pointer to the object you just created.
*
* @returns True is everything is OK, False otherwise
*/
- bool createStream(FPStream **lplpStream);
+ bool createStream(FPStream **streamPtr);
/**
* Allocates an object of type FpSfx, and return its pointer
*
- * @param lplpSfx Will contain a pointer to the object you just created.
+ * @param sfxPtr Will contain a pointer to the object you just created.
*
* @returns True is everything is OK, False otherwise
*/
- bool createSfx(FPSfx **lplpSfx);
+ bool createSfx(FPSfx **sfxPtr);
/**
* Set the general volume
*
- * @param dwVolume Volume to set (0-63)
+ * @param volume Volume to set (0-63)
*/
- void setMasterVolume(int dwVolume);
+ void setMasterVolume(int volume);
/**
* Get the general volume
*
- * @param lpdwVolume Variable that will contain the volume (0-63)
+ * @param volume Variable that will contain the volume (0-63)
*/
- void getMasterVolume(int *lpdwVolume);
+ void getMasterVolume(int *volume);
};
class FPSfx {
private:
- bool _bSoundSupported; // True if the sound is active
- bool _bFileLoaded; // True is a file is opened
- bool _bLoop; // True is sound effect should loop
+ bool _soundSupported; // True if the sound is active
+ bool _fileLoaded; // True is a file is opened
+ bool _loop; // True is sound effect should loop
int _lastVolume;
- bool _bIsVoice;
- bool _bPaused;
+ bool _isVoice;
+ bool _paused;
Audio::AudioStream *_loopStream;
Audio::RewindableAudioStream *_rewindableStream;
@@ -147,7 +147,7 @@ public:
*
*/
- FPSfx(bool bSoundOn);
+ FPSfx(bool soundOn);
/**
* Default Destructor.
@@ -173,13 +173,13 @@ public:
/**
* Opens a file and loads a sound effect.
*
- * @param lpszFileName Sfx filename
- * @param dwCodec CODEC used to uncompress the samples
+ * @param fileName Sfx filename
+ * @param codec CODEC used to uncompress the samples
*
* @returns True is everything is OK, False otherwise
*/
- bool loadFile(const char *lpszFileName, uint32 dwCodec = FPCODEC_RAW);
+ bool loadFile(const char *fileName, uint32 codec = FPCODEC_RAW);
bool loadWave(Common::SeekableReadStream *stream);
bool loadVoiceFromVDB(Common::File &vdbFP);
@@ -204,37 +204,37 @@ public:
*
*/
- void pause(bool bPause);
+ void setPause(bool pause);
/**
* Enables or disables the Sfx loop.
*
- * @param bLoop True to enable the loop, False to disable
+ * @param loop True to enable the loop, False to disable
*
* @remarks The loop must be activated BEFORE the sfx starts
* playing. Any changes made during the play will have
* no effect until the sfx is stopped then played again.
*/
- void setLoop(bool bLoop);
+ void setLoop(bool loop);
/**
* Change the volume of Sfx
*
- * @param dwVolume Volume to be set (0-63)
+ * @param volume Volume to be set (0-63)
*
*/
- void setVolume(int dwVolume);
+ void setVolume(int volume);
/**
* Gets the Sfx volume
*
- * @param lpdwVolume Will contain the current Sfx volume
+ * @param volumePtr Will contain the current Sfx volume
*
*/
- void getVolume(int *lpdwVolume);
+ void getVolume(int *volumePtr);
/**
* Returns true if the underlying sound has ended
@@ -244,18 +244,18 @@ public:
class FPStream {
private:
- uint32 _dwBufferSize; // Buffer size (bytes)
- uint32 _dwSize; // Stream size (bytes)
- uint32 _dwCodec; // CODEC used
-
- Common::File _file; // File handle used for the stream
-
- bool _bSoundSupported; // True if the sound is active
- bool _bFileLoaded; // True if the file is open
- bool _bLoop; // True if the stream should loop
- bool _bDoFadeOut; // True if fade out is required
- bool _bSyncExit;
- bool _bPaused;
+ uint32 _bufferSize; // Buffer size (bytes)
+ uint32 _size; // Stream size (bytes)
+ uint32 _codec; // CODEC used
+
+ Common::File _file; // File handle used for the stream
+
+ bool _soundSupported; // True if the sound is active
+ bool _fileLoaded; // True if the file is open
+ bool _loop; // True if the stream should loop
+ bool _doFadeOut; // True if fade out is required
+ bool _syncExit;
+ bool _paused;
int _lastVolume;
FPStream *_syncToPlay;
@@ -272,7 +272,7 @@ public:
* create it using FPSound::CreateStream()
*/
- FPStream(bool bSoundOn);
+ FPStream(bool soundOn);
/**
* Default destructor.
@@ -297,12 +297,12 @@ public:
* Opens a file stream
*
* @param fileName Filename to be opened
- * @param dwCodec CODEC to be used to uncompress samples
+ * @param codec CODEC to be used to uncompress samples
*
* @returns True is everything is OK, False otherwise
*/
- bool loadFile(const Common::String &fileName, uint32 dwCodec = FPCODEC_RAW, int nSync = 2000);
+ bool loadFile(const Common::String &fileName, uint32 codec = FPCODEC_RAW, int sync = 2000);
/**
* Closes a file stream (opened or not).
@@ -332,44 +332,44 @@ public:
*/
bool stop();
- void waitForSync(FPStream *toplay);
+ void waitForSync(FPStream *toPlay);
/**
* Pause sound effect
*
- * @param bPause True enables pause, False disables it
+ * @param pause True enables pause, False disables it
*/
- void pause(bool bPause);
+ void setPause(bool pause);
/**
* Unables or disables stream loop.
*
- * @param bLoop True enable loop, False disables it
+ * @param loop True enable loop, False disables it
*
* @remarks The loop must be activated BEFORE the stream starts
* playing. Any changes made during the play will have no
* effect until the stream is stopped then played again.
*/
- void setLoop(bool bLoop);
+ void setLoop(bool loop);
/**
* Change the volume of the stream
*
- * @param dwVolume Volume to be set (0-63)
+ * @param volume Volume to be set (0-63)
*/
- void setVolume(int dwVolume);
+ void setVolume(int volume);
/**
* Gets the volume of the stream
*
- * @param lpdwVolume Variable that will contain the current volume
+ * @param volumePtr Variable that will contain the current volume
*
*/
- void getVolume(int *lpdwVolume);
+ void getVolume(int *volumePtr);
};
} // End of namespace Tony
diff --git a/engines/tony/tony.cpp b/engines/tony/tony.cpp
index 4ffb84ced8..86740c6fe5 100644
--- a/engines/tony/tony.cpp
+++ b/engines/tony/tony.cpp
@@ -55,6 +55,7 @@ TonyEngine::TonyEngine(OSystem *syst, const TonyGameDescription *gameDesc) : Eng
SearchMan.addSubDirectoryMatching(gameDataDir, "Roasted");
SearchMan.addSubDirectoryMatching(gameDataDir, "Music");
SearchMan.addSubDirectoryMatching(gameDataDir, "Music/utilsfx");
+ SearchMan.addSubDirectoryMatching(gameDataDir, "Music/Layer");
// Set up load slot number
_initialLoadSlotNumber = -1;
@@ -244,16 +245,16 @@ bool TonyEngine::loadTonyDat() {
expectedLangVariant = 0;
break;
}
-
+
int numVariant = in.readUint16BE();
- if (expectedLangVariant > numVariant) {
+ if (expectedLangVariant > numVariant - 1) {
msg = Common::String::format("Font variant not present in 'tony.dat'. Get it from the ScummVM website");
GUIErrorMessage(msg);
warning("%s", msg.c_str());
-
+
return false;
}
-
+
in.seek(in.pos() + (2 * 256 * 8 * expectedLangVariant));
for (int i = 0; i < 256; i++) {
_cTableDialog[i] = in.readSint16BE();
@@ -323,7 +324,7 @@ void TonyEngine::playMusic(int nChannel, const Common::String &fname, int nFX, b
if (!getIsDemo()) {
if (!_stream[GLOBALS._nextChannel]->loadFile(fname, FPCODEC_ADPCM, nSync))
- g_vm->abortGame();
+ error("failed to open music file '%s'", fname.c_str());
} else {
_stream[GLOBALS._nextChannel]->loadFile(fname, FPCODEC_ADPCM, nSync);
}
@@ -335,7 +336,7 @@ void TonyEngine::playMusic(int nChannel, const Common::String &fname, int nFX, b
} else {
if (!getIsDemo()) {
if (!_stream[nChannel]->loadFile(fname, FPCODEC_ADPCM, nSync))
- g_vm->abortGame();
+ error("failed to open music file '%s'", fname.c_str());
} else {
_stream[nChannel]->loadFile(fname, FPCODEC_ADPCM, nSync);
}
@@ -356,7 +357,7 @@ void TonyEngine::doNextMusic(CORO_PARAM, const void *param) {
if (!g_vm->getIsDemo()) {
if (!streams[GLOBALS._nextChannel]->loadFile(GLOBALS._nextMusic, FPCODEC_ADPCM, GLOBALS._nextSync))
- g_vm->abortGame();
+ error("failed to open next music file '%s'", GLOBALS._nextMusic.c_str());
} else {
streams[GLOBALS._nextChannel]->loadFile(GLOBALS._nextMusic, FPCODEC_ADPCM, GLOBALS._nextSync);
}
@@ -513,13 +514,13 @@ void TonyEngine::pauseSound(bool bPause) {
for (uint i = 0; i < 6; i++)
if (_stream[i])
- _stream[i]->pause(bPause);
+ _stream[i]->setPause(bPause);
for (uint i = 0; i < MAX_SFX_CHANNELS; i++) {
if (_sfx[i])
- _sfx[i]->pause(bPause);
+ _sfx[i]->setPause(bPause);
if (_utilSfx[i])
- _utilSfx[i]->pause(bPause);
+ _utilSfx[i]->setPause(bPause);
}
}
@@ -631,10 +632,6 @@ void TonyEngine::openInitOptions(CORO_PARAM) {
_theEngine.openOptionScreen(coroParam, 2);
}
-void TonyEngine::abortGame() {
- _bQuitNow = true;
-}
-
/**
* Main process for playing the game.
*
@@ -772,9 +769,9 @@ void TonyEngine::syncSoundSettings() {
}
void TonyEngine::saveSoundSettings() {
- ConfMan.setBool("speech_mute", GLOBALS._bCfgDubbing);
- ConfMan.setBool("sfx_mute", GLOBALS._bCfgSFX);
- ConfMan.setBool("music_mute", GLOBALS._bCfgMusic);
+ ConfMan.setBool("speech_mute", !GLOBALS._bCfgDubbing);
+ ConfMan.setBool("sfx_mute", !GLOBALS._bCfgSFX);
+ ConfMan.setBool("music_mute", !GLOBALS._bCfgMusic);
ConfMan.setInt("speech_volume", GLOBALS._nCfgDubbingVolume * 256 / 10);
ConfMan.setInt("sfx_volume", GLOBALS._nCfgSFXVolume * 256 / 10);
diff --git a/engines/tony/tony.h b/engines/tony/tony.h
index 22090dfe51..332b122923 100644
--- a/engines/tony/tony.h
+++ b/engines/tony/tony.h
@@ -71,7 +71,7 @@ struct TonyGameDescription;
#define MAX_SFX_CHANNELS 32
#define TONY_DAT_VER_MAJ 0
-#define TONY_DAT_VER_MIN 1
+#define TONY_DAT_VER_MIN 3
struct VoiceHeader {
int _offset;
@@ -169,7 +169,6 @@ public:
void play();
void close();
- void abortGame();
void getDataDirectory(DataDir dir, char *path);
diff --git a/engines/tony/utils.cpp b/engines/tony/utils.cpp
index 3cc09a1454..81060146b7 100644
--- a/engines/tony/utils.cpp
+++ b/engines/tony/utils.cpp
@@ -383,7 +383,7 @@ void RMResUpdate::init(const Common::String &fileName) {
// It doesn't exist, so exit immediately
return;
- uint8 version = _hFile.readByte();
+ _hFile.readByte(); // Version, unused
_numUpd = _hFile.readUint32LE();
diff --git a/engines/tony/window.cpp b/engines/tony/window.cpp
index 013be84b4b..c9c450424f 100644
--- a/engines/tony/window.cpp
+++ b/engines/tony/window.cpp
@@ -256,7 +256,7 @@ void RMWindow::plotLines(const byte *lpBuf, const Common::Point &center, int x,
}
void RMWindow::showDirtyRects(bool v) {
- _showDirtyRects = v;
+ _showDirtyRects = v;
}
/****************************************************************************\
diff --git a/engines/toon/detection.cpp b/engines/toon/detection.cpp
index 3877fa2a6c..38b1f4f6e1 100644
--- a/engines/toon/detection.cpp
+++ b/engines/toon/detection.cpp
@@ -84,7 +84,7 @@ static const ADGameDescription gameDescriptions[] = {
{"study.svl", 0, "d4aff126ee27be3c3d25e2996369d7cb", 2324368},
},
Common::RU_RUS, Common::kPlatformPC, ADGF_NO_FLAGS, GUIO0()
- },
+ },
{
"toon", "",
{
diff --git a/engines/toon/movie.h b/engines/toon/movie.h
index e795182cba..4dd6583bf6 100644
--- a/engines/toon/movie.h
+++ b/engines/toon/movie.h
@@ -40,7 +40,7 @@ protected:
SmackerVideoTrack *createVideoTrack(uint32 width, uint32 height, uint32 frameCount, const Common::Rational &frameRate, uint32 flags, uint32 signature) const;
private:
- bool _lowRes;
+ bool _lowRes;
};
class Movie {
diff --git a/engines/toon/picture.cpp b/engines/toon/picture.cpp
index 204b0fe576..f59cdca064 100644
--- a/engines/toon/picture.cpp
+++ b/engines/toon/picture.cpp
@@ -71,7 +71,7 @@ bool Picture::loadPicture(const Common::String &file) {
_data = new uint8[decSize + 100];
_paletteEntries = READ_LE_UINT16(fileData + 14) / 3;
_useFullPalette = (_paletteEntries == 256);
-
+
if (_paletteEntries) {
_palette = new uint8[_paletteEntries * 3];
memcpy(_palette, fileData + 16, _paletteEntries * 3);
diff --git a/engines/touche/staticres.cpp b/engines/touche/staticres.cpp
index c18a947358..23b76558e4 100644
--- a/engines/touche/staticres.cpp
+++ b/engines/touche/staticres.cpp
@@ -471,7 +471,10 @@ const uint16 Graphics::_freGerFontOffs[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x1920
+ 0x0000, 0x0000, 0x0000, 0x1920, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000
};
const int Graphics::_freGerFontSize = ARRAYSIZE(Graphics::_freGerFontOffs);
diff --git a/engines/tsage/blue_force/blueforce_scenes3.cpp b/engines/tsage/blue_force/blueforce_scenes3.cpp
index 22c831f531..81e4af6e97 100644
--- a/engines/tsage/blue_force/blueforce_scenes3.cpp
+++ b/engines/tsage/blue_force/blueforce_scenes3.cpp
@@ -346,6 +346,14 @@ void Scene300::postInit(SceneObjectList *OwnerList) {
break;
}
+ if (BF_GLOBALS.getFlag(onBike) && !BF_GLOBALS.getFlag(onDuty)) {
+ BF_GLOBALS._sound1.play(30);
+ } else if ((BF_GLOBALS._dayNumber == 2) && (BF_GLOBALS._bookmark < bEndDayOne)) {
+ BF_GLOBALS._sound1.changeSound(49);
+ } else if (BF_GLOBALS._sceneManager._previousScene != 190) {
+ BF_GLOBALS._sound1.changeSound(33);
+ }
+
_item10.setDetails(4, 300, 7, 13, 16, 1);
_item11.setDetails(2, 300, 9, 13, 18, 1);
_item12.setDetails(5, 300, 10, 13, 19, 1);
diff --git a/engines/tsage/blue_force/blueforce_scenes7.cpp b/engines/tsage/blue_force/blueforce_scenes7.cpp
index bb29ad1f34..4cdd2f3f15 100644
--- a/engines/tsage/blue_force/blueforce_scenes7.cpp
+++ b/engines/tsage/blue_force/blueforce_scenes7.cpp
@@ -159,7 +159,7 @@ void Scene710::postInit(SceneObjectList *OwnerList) {
_stripManager.addSpeaker(&_skipSpeaker);
_stripManager.addSpeaker(&_lauraSpeaker);
_stripManager.addSpeaker(&_gameTextSpeaker);
-
+
_kid.postInit();
_kid._moveDiff = Common::Point(4, 2);
_laura.postInit();
diff --git a/engines/tsage/blue_force/blueforce_speakers.cpp b/engines/tsage/blue_force/blueforce_speakers.cpp
index 8af18b43b8..2a57616640 100644
--- a/engines/tsage/blue_force/blueforce_speakers.cpp
+++ b/engines/tsage/blue_force/blueforce_speakers.cpp
@@ -809,7 +809,7 @@ void SpeakerGiggles::setText(const Common::String &msg) {
SpeakerFBI::SpeakerFBI(): VisualSpeaker() {
_color1 = 27;
_color2 = 89;
-
+
_speakerName = "FBI";
}
@@ -832,7 +832,7 @@ void SpeakerFBI::setText(const Common::String &msg) {
SpeakerNico::SpeakerNico(): VisualSpeaker() {
_color1 = 105;
_color2 = 102;
-
+
_speakerName = "NICO";
}
@@ -845,7 +845,7 @@ void SpeakerNico::setText(const Common::String &msg) {
_object1.fixPriority(254);
_object1.setPosition(Common::Point(BF_GLOBALS._sceneManager._scene->_sceneBounds.left + 262,
BF_GLOBALS._sceneManager._scene->_sceneBounds.top + 166));
-
+
_object2.postInit();
_object2.setVisage(905);
_object2.setStrip2(1);
@@ -862,7 +862,7 @@ void SpeakerNico::setText(const Common::String &msg) {
SpeakerDA::SpeakerDA(): VisualSpeaker() {
_color1 = 82;
_color2 = 80;
-
+
_speakerName = "DA";
}
@@ -875,7 +875,7 @@ void SpeakerDA::setText(const Common::String &msg) {
_object1.fixPriority(254);
_object1.setPosition(Common::Point(BF_GLOBALS._sceneManager._scene->_sceneBounds.left + 84,
BF_GLOBALS._sceneManager._scene->_sceneBounds.top + 166));
-
+
_object2.postInit();
_object2.setVisage(915);
_object2.setStrip2(1);
@@ -892,7 +892,7 @@ void SpeakerDA::setText(const Common::String &msg) {
SpeakerGrandma::SpeakerGrandma(): VisualSpeaker() {
_color1 = 20;
_color2 = 23;
-
+
_speakerName = "GRANDMA";
}
@@ -905,7 +905,7 @@ void SpeakerGrandma::setText(const Common::String &msg) {
_object1.fixPriority(254);
_object1.setPosition(Common::Point(BF_GLOBALS._sceneManager._scene->_sceneBounds.left + 43,
BF_GLOBALS._sceneManager._scene->_sceneBounds.top + 166));
-
+
_object2.postInit();
_object2.setVisage(274);
_object2.setStrip2(3);
@@ -922,7 +922,7 @@ void SpeakerGrandma::setText(const Common::String &msg) {
SpeakerLyle::SpeakerLyle(): VisualSpeaker() {
_color1 = 29;
_color2 = 89;
-
+
_speakerName = "LYLE";
}
@@ -935,7 +935,7 @@ void SpeakerLyle::setText(const Common::String &msg) {
_object1.fixPriority(254);
_object1.setPosition(Common::Point(BF_GLOBALS._sceneManager._scene->_sceneBounds.left + 75,
BF_GLOBALS._sceneManager._scene->_sceneBounds.top + 166));
-
+
_object2.postInit();
_object2.setVisage(278);
_object2.setStrip2(1);
@@ -952,7 +952,7 @@ void SpeakerLyle::setText(const Common::String &msg) {
SpeakerGranText::SpeakerGranText(): VisualSpeaker() {
_color1 = 20;
_color2 = 23;
-
+
_speakerName = "GRANTEXT";
}
@@ -961,7 +961,7 @@ SpeakerGranText::SpeakerGranText(): VisualSpeaker() {
SpeakerLyleText::SpeakerLyleText(): VisualSpeaker() {
_color1 = 29;
_color2 = 89;
-
+
_speakerName = "LYLETEXT";
}
@@ -969,7 +969,7 @@ SpeakerLyleText::SpeakerLyleText(): VisualSpeaker() {
SpeakerKate::SpeakerKate(): VisualSpeaker() {
_color1 = 108;
-
+
_speakerName = "KATE";
}
@@ -982,7 +982,7 @@ void SpeakerKate::setText(const Common::String &msg) {
_object1.fixPriority(254);
_object1.setPosition(Common::Point(BF_GLOBALS._sceneManager._scene->_sceneBounds.left + 270,
BF_GLOBALS._sceneManager._scene->_sceneBounds.top + 166));
-
+
_object2.postInit();
_object2.setVisage(122);
_object2.setStrip2(1);
@@ -1000,7 +1000,7 @@ void SpeakerKate::setText(const Common::String &msg) {
SpeakerTony::SpeakerTony(): VisualSpeaker() {
_color1 = 108;
_color2 = 8;
-
+
_speakerName = "TONY";
}
diff --git a/engines/tsage/blue_force/blueforce_speakers.h b/engines/tsage/blue_force/blueforce_speakers.h
index 508279a929..e406a50fbe 100644
--- a/engines/tsage/blue_force/blueforce_speakers.h
+++ b/engines/tsage/blue_force/blueforce_speakers.h
@@ -290,7 +290,7 @@ public:
virtual Common::String getClassName() { return "FBI"; }
virtual void setText(const Common::String &msg);
};
-
+
class SpeakerNico: public VisualSpeaker {
public:
SpeakerNico();
@@ -340,7 +340,7 @@ public:
class SpeakerKate: public VisualSpeaker {
public:
SpeakerKate();
-
+
virtual Common::String getClassName() { return "SpeakerKate"; }
virtual void setText(const Common::String &msg);
};
@@ -348,7 +348,7 @@ public:
class SpeakerTony: public VisualSpeaker {
public:
SpeakerTony();
-
+
virtual Common::String getClassName() { return "SpeakerTony"; }
virtual void setText(const Common::String &msg);
};
diff --git a/engines/tsage/detection.cpp b/engines/tsage/detection.cpp
index bcadfdc201..a35d663b93 100644
--- a/engines/tsage/detection.cpp
+++ b/engines/tsage/detection.cpp
@@ -156,7 +156,7 @@ public:
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const {
Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(
generateGameStateFileName(target, slot));
-
+
if (f) {
TsAGE::tSageSavegameHeader header;
TsAGE::Saver::readSavegameHeader(f, header);
diff --git a/engines/tsage/globals.cpp b/engines/tsage/globals.cpp
index de9463268b..4589a926c9 100644
--- a/engines/tsage/globals.cpp
+++ b/engines/tsage/globals.cpp
@@ -205,7 +205,7 @@ void Globals::dispatchSounds() {
void TsAGE2Globals::reset() {
Globals::reset();
-
+
// Reset the inventory
T2_GLOBALS._uiElements.updateInventory();
T2_GLOBALS._uiElements._scoreValue = 0;
@@ -277,7 +277,7 @@ void BlueForceGlobals::synchronize(Serializer &s) {
void BlueForceGlobals::reset() {
TsAGE2Globals::reset();
_scenePalette.clearListeners();
-
+
_scrollFollower = &_player;
_bookmark = bNone;
@@ -368,7 +368,7 @@ namespace Ringworld2 {
void Ringworld2Globals::reset() {
Globals::reset();
-
+
// Reset the inventory
R2_INVENTORY.reset();
T2_GLOBALS._uiElements.updateInventory();
@@ -526,7 +526,7 @@ void Ringworld2Globals::synchronize(Serializer &s) {
for (i = 0; i < MAX_CHARACTERS; ++i)
s.syncAsByte(_v565F1[i]);
-
+
s.syncAsByte(_v565AE);
s.syncAsByte(_v566A4);
s.syncAsByte(_v566A5);
diff --git a/engines/tsage/ringworld/ringworld_logic.cpp b/engines/tsage/ringworld/ringworld_logic.cpp
index 7d571b40d7..0584570ac2 100644
--- a/engines/tsage/ringworld/ringworld_logic.cpp
+++ b/engines/tsage/ringworld/ringworld_logic.cpp
@@ -610,7 +610,7 @@ void NamedHotspot::doAction(int action) {
case CURSOR_USE:
if (_useLineNum == -1)
break;
-
+
SceneItem::display(_resNum, _useLineNum, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOR, 7, LIST_END);
return;
case CURSOR_TALK:
diff --git a/engines/tsage/ringworld2/ringworld2_logic.cpp b/engines/tsage/ringworld2/ringworld2_logic.cpp
index a06899fe5a..97042cb621 100644
--- a/engines/tsage/ringworld2/ringworld2_logic.cpp
+++ b/engines/tsage/ringworld2/ringworld2_logic.cpp
@@ -1695,7 +1695,7 @@ bool AnimationPlayer::load(int animId, Action *endAction) {
_playbackTickPrior = -1;
_playbackTick = 0;
- // The final multiplication is used to deliberately slow down playback, since the original
+ // 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;
_gameFrame = R2_GLOBALS._events.getFrameNumber();
@@ -1706,7 +1706,7 @@ bool AnimationPlayer::load(int animId, Action *endAction) {
int v = (_subData._sliceSize + 2) * _subData._ySlices * _subData._framesPerSlices;
_dataNeeded = (_subData._field16 / _subData._framesPerSlices) + v + 96;
}
-
+
debugC(1, ktSageDebugGraphics, "Data needed %d", _dataNeeded);
// Set up animation data objects
@@ -1760,7 +1760,7 @@ bool AnimationPlayer::load(int animId, Action *endAction) {
byte r = _subData._palData[idx * 3];
byte g = _subData._palData[idx * 3 + 1];
byte b = _subData._palData[idx * 3 + 2];
-
+
int palIndex = R2_GLOBALS._scenePalette.indexOf(r, g, b);
_palIndexes[idx] = palIndex;
}
diff --git a/engines/tsage/scenes.h b/engines/tsage/scenes.h
index 2daa71ba98..d5ac88c692 100644
--- a/engines/tsage/scenes.h
+++ b/engines/tsage/scenes.h
@@ -67,7 +67,7 @@ public:
void setZoomPercents(int yStart, int minPercent, int yEnd, int maxPercent);
void loadBackground(int xAmount, int yAmount);
-
+
void loadSceneData(int sceneNum);
};
diff --git a/engines/tsage/tsage.cpp b/engines/tsage/tsage.cpp
index 40f4dfcfd2..87697f950b 100644
--- a/engines/tsage/tsage.cpp
+++ b/engines/tsage/tsage.cpp
@@ -45,7 +45,7 @@ TSageEngine::TSageEngine(OSystem *system, const tSageGameDescription *gameDesc)
else if (g_vm->getGameID() == GType_BlueForce)
_debugger = new BlueForceDebugger();
else if (g_vm->getGameID() == GType_Ringworld2)
- _debugger = new Ringworld2Debugger();
+ _debugger = new Ringworld2Debugger();
}
Common::Error TSageEngine::init() {
@@ -92,7 +92,7 @@ void TSageEngine::initialize() {
g_resourceManager->addLib("TSAGE.RLB");
}
g_globals = new BlueForce::BlueForceGlobals();
-
+
// Setup the user interface
T2_GLOBALS._uiElements.setup(Common::Point(0, UI_INTERFACE_Y - 2));
@@ -107,7 +107,7 @@ void TSageEngine::initialize() {
// Reset all global variables
R2_GLOBALS.reset();
- }
+ }
g_globals->gfxManager().setDefaults();
diff --git a/engines/tucker/resource.cpp b/engines/tucker/resource.cpp
index bee09f7391..1b04f3fae9 100644
--- a/engines/tucker/resource.cpp
+++ b/engines/tucker/resource.cpp
@@ -29,6 +29,9 @@
#include "audio/decoders/vorbis.h"
#include "audio/decoders/wave.h"
+#include "graphics/surface.h"
+#include "graphics/decoders/pcx.h"
+
#include "tucker/tucker.h"
#include "tucker/graphics.h"
@@ -298,23 +301,21 @@ void TuckerEngine::loadImage(const char *fname, uint8 *dst, int type) {
return;
}
}
- f.seek(128, SEEK_SET);
- int size = 0;
- while (size < 64000) {
- int code = f.readByte();
- if (code >= 0xC0) {
- const int sz = code - 0xC0;
- code = f.readByte();
- memset(dst + size, code, sz);
- size += sz;
- } else {
- dst[size++] = code;
- }
- }
+
+ ::Graphics::PCXDecoder pcx;
+ if (!pcx.loadStream(f))
+ error("Error while reading PCX image");
+
+ const ::Graphics::Surface *pcxSurface = pcx.getSurface();
+ if (pcxSurface->format.bytesPerPixel != 1)
+ error("Invalid bytes per pixel in PCX surface (%d)", pcxSurface->format.bytesPerPixel);
+ if (pcxSurface->w != 320 || pcxSurface->h != 200)
+ error("Invalid PCX surface size (%d x %d)", pcxSurface->w, pcxSurface->h);
+ for (uint16 y = 0; y < pcxSurface->h; y++)
+ memcpy(dst + y * 320, pcxSurface->getBasePtr(0, y), pcxSurface->w);
+
if (type != 0) {
- if (f.readByte() != 12)
- return;
- f.read(_currentPalette, 768);
+ memcpy(_currentPalette, pcx.getPalette(), 3 * 256);
setBlackPalette();
}
}
diff --git a/engines/wintermute/ad/ad_actor.cpp b/engines/wintermute/ad/ad_actor.cpp
index 9087d66844..d175855d1e 100644
--- a/engines/wintermute/ad/ad_actor.cpp
+++ b/engines/wintermute/ad/ad_actor.cpp
@@ -602,13 +602,13 @@ bool AdActor::update() {
}
// finished playing animation?
- if (_state == STATE_PLAYING_ANIM && _animSprite != NULL && _animSprite->_finished) {
+ if (_state == STATE_PLAYING_ANIM && _animSprite != NULL && _animSprite->isFinished()) {
_state = _nextState;
_nextState = STATE_READY;
_currentSprite = _animSprite;
}
- if (_state == STATE_PLAYING_ANIM_SET && _animSprite2 != NULL && _animSprite2->_finished) {
+ if (_state == STATE_PLAYING_ANIM_SET && _animSprite2 != NULL && _animSprite2->isFinished()) {
_state = _nextState;
_nextState = STATE_READY;
_currentSprite = _animSprite2;
@@ -649,7 +649,7 @@ bool AdActor::update() {
//////////////////////////////////////////////////////////////////////////
case STATE_TURNING_LEFT:
- if (_tempSprite2 == NULL || _tempSprite2->_finished) {
+ if (_tempSprite2 == NULL || _tempSprite2->isFinished()) {
if (_dir > 0) {
_dir = (TDirection)(_dir - 1);
} else {
@@ -686,7 +686,7 @@ bool AdActor::update() {
//////////////////////////////////////////////////////////////////////////
case STATE_TURNING_RIGHT:
- if (_tempSprite2 == NULL || _tempSprite2->_finished) {
+ if (_tempSprite2 == NULL || _tempSprite2->isFinished()) {
_dir = (TDirection)(_dir + 1);
if ((int)_dir >= (int)NUM_DIRECTIONS) {
@@ -753,7 +753,7 @@ bool AdActor::update() {
}
bool timeIsUp = (_sentence->_sound && _sentence->_soundStarted && (!_sentence->_sound->isPlaying() && !_sentence->_sound->isPaused())) || (!_sentence->_sound && _sentence->_duration <= _gameRef->_timer - _sentence->_startTime);
- if (_tempSprite2 == NULL || _tempSprite2->_finished || (/*_tempSprite2->_looping &&*/ timeIsUp)) {
+ if (_tempSprite2 == NULL || _tempSprite2->isFinished() || (/*_tempSprite2->_looping &&*/ timeIsUp)) {
if (timeIsUp) {
_sentence->finish();
_tempSprite2 = NULL;
@@ -798,7 +798,7 @@ bool AdActor::update() {
if (_currentSprite && !already_moved) {
_currentSprite->getCurrentFrame(_zoomable ? ((AdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) : 100, _zoomable ? ((AdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) : 100);
- if (_currentSprite->_changed) {
+ if (_currentSprite->isChanged()) {
_posX += _currentSprite->_moveX;
_posY += _currentSprite->_moveY;
afterMove();
@@ -830,7 +830,7 @@ void AdActor::followPath() {
// are there points to follow?
if (_path->getCurrent() != NULL) {
- _state = STATE_FOLLOWING_PATH;;
+ _state = STATE_FOLLOWING_PATH;
initLine(BasePoint(_posX, _posY), *_path->getCurrent());
} else {
if (_afterWalkDir != DI_NONE) {
@@ -858,7 +858,7 @@ void AdActor::getNextStep() {
}
_currentSprite->getCurrentFrame(_zoomable ? ((AdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) : 100, _zoomable ? ((AdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) : 100);
- if (!_currentSprite->_changed) {
+ if (!_currentSprite->isChanged()) {
return;
}
@@ -1075,27 +1075,27 @@ bool AdActor::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack,
//////////////////////////////////////////////////////////////////////////
-ScValue *AdActor::scGetProperty(const char *name) {
+ScValue *AdActor::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Direction
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Direction") == 0) {
+ if (name == "Direction") {
_scValue->setInt(_dir);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Type") == 0) {
+ else if (name == "Type") {
_scValue->setString("actor");
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// TalkAnimName
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "TalkAnimName") == 0) {
+ else if (name == "TalkAnimName") {
_scValue->setString(_talkAnimName);
return _scValue;
}
@@ -1103,7 +1103,7 @@ ScValue *AdActor::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// WalkAnimName
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "WalkAnimName") == 0) {
+ else if (name == "WalkAnimName") {
_scValue->setString(_walkAnimName);
return _scValue;
}
@@ -1111,7 +1111,7 @@ ScValue *AdActor::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// IdleAnimName
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "IdleAnimName") == 0) {
+ else if (name == "IdleAnimName") {
_scValue->setString(_idleAnimName);
return _scValue;
}
@@ -1119,7 +1119,7 @@ ScValue *AdActor::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// TurnLeftAnimName
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "TurnLeftAnimName") == 0) {
+ else if (name == "TurnLeftAnimName") {
_scValue->setString(_turnLeftAnimName);
return _scValue;
}
@@ -1127,7 +1127,7 @@ ScValue *AdActor::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// TurnRightAnimName
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "TurnRightAnimName") == 0) {
+ else if (name == "TurnRightAnimName") {
_scValue->setString(_turnRightAnimName);
return _scValue;
} else {
@@ -1351,7 +1351,7 @@ bool AdActor::persist(BasePersistenceManager *persistMgr) {
//////////////////////////////////////////////////////////////////////////
TDirection AdActor::angleToDirection(int angle) {
- TDirection ret = DI_DOWN;;
+ TDirection ret = DI_DOWN;
if (angle > -112 && angle <= -67) {
ret = DI_UP;
diff --git a/engines/wintermute/ad/ad_actor.h b/engines/wintermute/ad/ad_actor.h
index 271e57cb85..543c9d063a 100644
--- a/engines/wintermute/ad/ad_actor.h
+++ b/engines/wintermute/ad/ad_actor.h
@@ -83,7 +83,7 @@ private:
AdSpriteSet *getAnimByName(const Common::String &animName);
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
diff --git a/engines/wintermute/ad/ad_entity.cpp b/engines/wintermute/ad/ad_entity.cpp
index 234af1fffa..9af7e034ca 100644
--- a/engines/wintermute/ad/ad_entity.cpp
+++ b/engines/wintermute/ad/ad_entity.cpp
@@ -28,28 +28,29 @@
#include "engines/wintermute/ad/ad_entity.h"
-#include "engines/wintermute/base/base_parser.h"
-#include "engines/wintermute/base/base_dynamic_buffer.h"
-#include "engines/wintermute/base/base_active_rect.h"
-#include "engines/wintermute/base/base_surface_storage.h"
-#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/ad/ad_game.h"
#include "engines/wintermute/ad/ad_scene.h"
-#include "engines/wintermute/base/sound/base_sound.h"
#include "engines/wintermute/ad/ad_waypoint_group.h"
-#include "engines/wintermute/base/font/base_font_storage.h"
-#include "engines/wintermute/base/font/base_font.h"
#include "engines/wintermute/ad/ad_sentence.h"
+#include "engines/wintermute/base/base_active_rect.h"
+#include "engines/wintermute/base/base_dynamic_buffer.h"
+#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_parser.h"
#include "engines/wintermute/base/base_region.h"
#include "engines/wintermute/base/base_sprite.h"
-#include "engines/wintermute/base/base_file_manager.h"
-#include "engines/wintermute/platform_osystem.h"
-#include "engines/wintermute/utils/utils.h"
+#include "engines/wintermute/base/base_surface_storage.h"
+#include "engines/wintermute/base/font/base_font_storage.h"
+#include "engines/wintermute/base/font/base_font.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
+#include "engines/wintermute/base/particles/part_emitter.h"
#include "engines/wintermute/base/scriptables/script_value.h"
#include "engines/wintermute/base/scriptables/script.h"
#include "engines/wintermute/base/scriptables/script_stack.h"
+#include "engines/wintermute/base/sound/base_sound.h"
#include "engines/wintermute/video/video_theora_player.h"
-#include "engines/wintermute/base/particles/part_emitter.h"
+#include "engines/wintermute/utils/utils.h"
+#include "engines/wintermute/platform_osystem.h"
#include "common/str.h"
namespace Wintermute {
@@ -577,7 +578,7 @@ bool AdEntity::update() {
}
// finished playing animation?
- if (_state == STATE_PLAYING_ANIM && _animSprite != NULL && _animSprite->_finished) {
+ if (_state == STATE_PLAYING_ANIM && _animSprite != NULL && _animSprite->isFinished()) {
_state = STATE_READY;
_currentSprite = _animSprite;
}
@@ -612,7 +613,7 @@ bool AdEntity::update() {
}
bool timeIsUp = (_sentence->_sound && _sentence->_soundStarted && (!_sentence->_sound->isPlaying() && !_sentence->_sound->isPaused())) || (!_sentence->_sound && _sentence->_duration <= _gameRef->_timer - _sentence->_startTime);
- if (_tempSprite2 == NULL || _tempSprite2->_finished || (/*_tempSprite2->_looping &&*/ timeIsUp)) {
+ if (_tempSprite2 == NULL || _tempSprite2->isFinished() || (/*_tempSprite2->_looping &&*/ timeIsUp)) {
if (timeIsUp) {
_sentence->finish();
_tempSprite2 = NULL;
@@ -638,7 +639,7 @@ bool AdEntity::update() {
if (_currentSprite) {
_currentSprite->getCurrentFrame(_zoomable ? ((AdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) : 100);
- if (_currentSprite->_changed) {
+ if (_currentSprite->isChanged()) {
_posX += _currentSprite->_moveX;
_posY += _currentSprite->_moveY;
}
@@ -828,13 +829,13 @@ bool AdEntity::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack
//////////////////////////////////////////////////////////////////////////
-ScValue *AdEntity::scGetProperty(const char *name) {
+ScValue *AdEntity::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type (RO)
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("entity");
return _scValue;
}
@@ -842,7 +843,7 @@ ScValue *AdEntity::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Item
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Item") == 0) {
+ else if (name == "Item") {
if (_item) {
_scValue->setString(_item);
} else {
@@ -855,7 +856,7 @@ ScValue *AdEntity::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Subtype (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Subtype") == 0) {
+ else if (name == "Subtype") {
if (_subtype == ENTITY_SOUND) {
_scValue->setString("sound");
} else {
@@ -868,7 +869,7 @@ ScValue *AdEntity::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// WalkToX
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "WalkToX") == 0) {
+ else if (name == "WalkToX") {
_scValue->setInt(_walkToX);
return _scValue;
}
@@ -876,7 +877,7 @@ ScValue *AdEntity::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// WalkToY
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "WalkToY") == 0) {
+ else if (name == "WalkToY") {
_scValue->setInt(_walkToY);
return _scValue;
}
@@ -884,7 +885,7 @@ ScValue *AdEntity::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// WalkToDirection
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "WalkToDirection") == 0) {
+ else if (name == "WalkToDirection") {
_scValue->setInt((int)_walkToDir);
return _scValue;
}
@@ -892,7 +893,7 @@ ScValue *AdEntity::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Region (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Region") == 0) {
+ else if (name == "Region") {
if (_region) {
_scValue->setNative(_region, true);
} else {
diff --git a/engines/wintermute/ad/ad_entity.h b/engines/wintermute/ad/ad_entity.h
index 39dc133eef..415987e50a 100644
--- a/engines/wintermute/ad/ad_entity.h
+++ b/engines/wintermute/ad/ad_entity.h
@@ -56,7 +56,7 @@ public:
TEntityType _subtype;
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
diff --git a/engines/wintermute/ad/ad_game.cpp b/engines/wintermute/ad/ad_game.cpp
index fe8a5991e2..4481b774c1 100644
--- a/engines/wintermute/ad/ad_game.cpp
+++ b/engines/wintermute/ad/ad_game.cpp
@@ -50,6 +50,7 @@
#include "engines/wintermute/base/base_viewport.h"
#include "engines/wintermute/base/particles/part_emitter.h"
#include "engines/wintermute/base/saveload.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
#include "engines/wintermute/base/scriptables/script_engine.h"
#include "engines/wintermute/base/scriptables/script.h"
#include "engines/wintermute/base/scriptables/script_stack.h"
@@ -875,20 +876,20 @@ bool AdGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack,
//////////////////////////////////////////////////////////////////////////
-ScValue *AdGame::scGetProperty(const char *name) {
+ScValue *AdGame::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("game");
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// Scene
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Scene") == 0) {
+ else if (name == "Scene") {
if (_scene) {
_scValue->setNative(_scene, true);
} else {
@@ -900,7 +901,7 @@ ScValue *AdGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// SelectedItem
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SelectedItem") == 0) {
+ else if (name == "SelectedItem") {
//if (_selectedItem) _scValue->setString(_selectedItem->_name);
if (_selectedItem) {
_scValue->setNative(_selectedItem, true);
@@ -913,14 +914,14 @@ ScValue *AdGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// NumItems
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "NumItems") == 0) {
+ else if (name == "NumItems") {
return _invObject->scGetProperty(name);
}
//////////////////////////////////////////////////////////////////////////
// SmartItemCursor
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SmartItemCursor") == 0) {
+ else if (name == "SmartItemCursor") {
_scValue->setBool(_smartItemCursor);
return _scValue;
}
@@ -928,7 +929,7 @@ ScValue *AdGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// InventoryVisible
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "InventoryVisible") == 0) {
+ else if (name == "InventoryVisible") {
_scValue->setBool(_inventoryBox && _inventoryBox->_visible);
return _scValue;
}
@@ -936,7 +937,7 @@ ScValue *AdGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// InventoryScrollOffset
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "InventoryScrollOffset") == 0) {
+ else if (name == "InventoryScrollOffset") {
if (_inventoryBox) {
_scValue->setInt(_inventoryBox->_scrollOffset);
} else {
@@ -949,7 +950,7 @@ ScValue *AdGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// ResponsesVisible (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ResponsesVisible") == 0) {
+ else if (name == "ResponsesVisible") {
_scValue->setBool(_stateEx == GAME_WAITING_RESPONSE);
return _scValue;
}
@@ -957,7 +958,7 @@ ScValue *AdGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// PrevScene / PreviousScene (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "PrevScene") == 0 || strcmp(name, "PreviousScene") == 0) {
+ else if (name == "PrevScene" || name == "PreviousScene") {
if (!_prevSceneName) {
_scValue->setString("");
} else {
@@ -969,7 +970,7 @@ ScValue *AdGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// PrevSceneFilename / PreviousSceneFilename (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "PrevSceneFilename") == 0 || strcmp(name, "PreviousSceneFilename") == 0) {
+ else if (name == "PrevSceneFilename" || name == "PreviousSceneFilename") {
if (!_prevSceneFilename) {
_scValue->setString("");
} else {
@@ -981,7 +982,7 @@ ScValue *AdGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// LastResponse (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "LastResponse") == 0) {
+ else if (name == "LastResponse") {
if (!_responseBox || !_responseBox->_lastResponseText) {
_scValue->setString("");
} else {
@@ -993,7 +994,7 @@ ScValue *AdGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// LastResponseOrig (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "LastResponseOrig") == 0) {
+ else if (name == "LastResponseOrig") {
if (!_responseBox || !_responseBox->_lastResponseTextOrig) {
_scValue->setString("");
} else {
@@ -1005,7 +1006,7 @@ ScValue *AdGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// InventoryObject
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "InventoryObject") == 0) {
+ else if (name == "InventoryObject") {
if (_inventoryOwner == _invObject) {
_scValue->setNative(this, true);
} else {
@@ -1018,7 +1019,7 @@ ScValue *AdGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// TotalNumItems
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "TotalNumItems") == 0) {
+ else if (name == "TotalNumItems") {
_scValue->setInt(_items.size());
return _scValue;
}
@@ -1026,7 +1027,7 @@ ScValue *AdGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// TalkSkipButton
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "TalkSkipButton") == 0) {
+ else if (name == "TalkSkipButton") {
_scValue->setInt(_talkSkipButton);
return _scValue;
}
@@ -1034,7 +1035,7 @@ ScValue *AdGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// ChangingScene
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ChangingScene") == 0) {
+ else if (name == "ChangingScene") {
_scValue->setBool(_scheduledScene != NULL);
return _scValue;
}
@@ -1042,7 +1043,7 @@ ScValue *AdGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// StartupScene
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "StartupScene") == 0) {
+ else if (name == "StartupScene") {
if (!_startupScene) {
_scValue->setNULL();
} else {
diff --git a/engines/wintermute/ad/ad_game.h b/engines/wintermute/ad/ad_game.h
index 46427331bf..81c79a3da8 100644
--- a/engines/wintermute/ad/ad_game.h
+++ b/engines/wintermute/ad/ad_game.h
@@ -126,7 +126,7 @@ public:
bool loadItemsBuffer(byte *buffer, bool merge = false);
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
bool validMouse();
diff --git a/engines/wintermute/ad/ad_inventory_box.cpp b/engines/wintermute/ad/ad_inventory_box.cpp
index 16b8e01ff3..7ae8ff8d69 100644
--- a/engines/wintermute/ad/ad_inventory_box.cpp
+++ b/engines/wintermute/ad/ad_inventory_box.cpp
@@ -35,6 +35,7 @@
#include "engines/wintermute/base/base_file_manager.h"
#include "engines/wintermute/base/base_viewport.h"
#include "engines/wintermute/base/base_dynamic_buffer.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
#include "engines/wintermute/ui/ui_button.h"
#include "engines/wintermute/ui/ui_window.h"
#include "engines/wintermute/platform_osystem.h"
diff --git a/engines/wintermute/ad/ad_item.cpp b/engines/wintermute/ad/ad_item.cpp
index afd813933b..427b1c7db4 100644
--- a/engines/wintermute/ad/ad_item.cpp
+++ b/engines/wintermute/ad/ad_item.cpp
@@ -36,11 +36,11 @@
#include "engines/wintermute/base/base_parser.h"
#include "engines/wintermute/base/sound/base_sound.h"
#include "engines/wintermute/base/base_sprite.h"
-#include "engines/wintermute/utils/utils.h"
-#include "engines/wintermute/platform_osystem.h"
#include "engines/wintermute/base/scriptables/script.h"
#include "engines/wintermute/base/scriptables/script_stack.h"
#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/utils/utils.h"
+#include "engines/wintermute/platform_osystem.h"
#include "common/str.h"
namespace Wintermute {
@@ -340,7 +340,7 @@ bool AdItem::update() {
}
// finished playing animation?
- if (_state == STATE_PLAYING_ANIM && _animSprite != NULL && _animSprite->_finished) {
+ if (_state == STATE_PLAYING_ANIM && _animSprite != NULL && _animSprite->isFinished()) {
_state = STATE_READY;
_currentSprite = _animSprite;
}
@@ -379,7 +379,7 @@ bool AdItem::update() {
}
bool timeIsUp = (_sentence->_sound && _sentence->_soundStarted && (!_sentence->_sound->isPlaying() && !_sentence->_sound->isPaused())) || (!_sentence->_sound && _sentence->_duration <= _gameRef->_timer - _sentence->_startTime);
- if (_tempSprite2 == NULL || _tempSprite2->_finished || (/*_tempSprite2->_looping &&*/ timeIsUp)) {
+ if (_tempSprite2 == NULL || _tempSprite2->isFinished() || (/*_tempSprite2->_looping &&*/ timeIsUp)) {
if (timeIsUp) {
_sentence->finish();
_tempSprite2 = NULL;
@@ -614,13 +614,13 @@ bool AdItem::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack,
//////////////////////////////////////////////////////////////////////////
-ScValue *AdItem::scGetProperty(const char *name) {
+ScValue *AdItem::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("item");
return _scValue;
}
@@ -628,7 +628,7 @@ ScValue *AdItem::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Name
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Name") == 0) {
+ else if (name == "Name") {
_scValue->setString(getName());
return _scValue;
}
@@ -636,7 +636,7 @@ ScValue *AdItem::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// DisplayAmount
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "DisplayAmount") == 0) {
+ else if (name == "DisplayAmount") {
_scValue->setBool(_displayAmount);
return _scValue;
}
@@ -644,7 +644,7 @@ ScValue *AdItem::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Amount
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Amount") == 0) {
+ else if (name == "Amount") {
_scValue->setInt(_amount);
return _scValue;
}
@@ -652,7 +652,7 @@ ScValue *AdItem::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// AmountOffsetX
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AmountOffsetX") == 0) {
+ else if (name == "AmountOffsetX") {
_scValue->setInt(_amountOffsetX);
return _scValue;
}
@@ -660,7 +660,7 @@ ScValue *AdItem::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// AmountOffsetY
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AmountOffsetY") == 0) {
+ else if (name == "AmountOffsetY") {
_scValue->setInt(_amountOffsetY);
return _scValue;
}
@@ -668,7 +668,7 @@ ScValue *AdItem::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// AmountAlign
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AmountAlign") == 0) {
+ else if (name == "AmountAlign") {
_scValue->setInt(_amountAlign);
return _scValue;
}
@@ -676,7 +676,7 @@ ScValue *AdItem::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// AmountString
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AmountString") == 0) {
+ else if (name == "AmountString") {
if (!_amountString) {
_scValue->setNULL();
} else {
@@ -688,7 +688,7 @@ ScValue *AdItem::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// CursorCombined
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "CursorCombined") == 0) {
+ else if (name == "CursorCombined") {
_scValue->setBool(_cursorCombined);
return _scValue;
} else {
diff --git a/engines/wintermute/ad/ad_item.h b/engines/wintermute/ad/ad_item.h
index 6047c542c1..79978f9f72 100644
--- a/engines/wintermute/ad/ad_item.h
+++ b/engines/wintermute/ad/ad_item.h
@@ -51,7 +51,7 @@ public:
bool loadBuffer(byte *buffer, bool complete = true);
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
diff --git a/engines/wintermute/ad/ad_layer.cpp b/engines/wintermute/ad/ad_layer.cpp
index 46b75b8b21..209c12b7a2 100644
--- a/engines/wintermute/ad/ad_layer.cpp
+++ b/engines/wintermute/ad/ad_layer.cpp
@@ -29,12 +29,12 @@
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/ad/ad_layer.h"
#include "engines/wintermute/ad/ad_scene_node.h"
-#include "engines/wintermute/base/base_parser.h"
#include "engines/wintermute/base/base_dynamic_buffer.h"
+#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/base/base_parser.h"
#include "engines/wintermute/base/scriptables/script_value.h"
#include "engines/wintermute/base/scriptables/script.h"
#include "engines/wintermute/base/scriptables/script_stack.h"
-#include "engines/wintermute/base/base_file_manager.h"
#include "engines/wintermute/platform_osystem.h"
#include "common/str.h"
@@ -376,13 +376,13 @@ bool AdLayer::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack,
//////////////////////////////////////////////////////////////////////////
-ScValue *AdLayer::scGetProperty(const char *name) {
+ScValue *AdLayer::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("layer");
return _scValue;
}
@@ -390,7 +390,7 @@ ScValue *AdLayer::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// NumNodes (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "NumNodes") == 0) {
+ else if (name == "NumNodes") {
_scValue->setInt(_nodes.size());
return _scValue;
}
@@ -398,7 +398,7 @@ ScValue *AdLayer::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Width
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Width") == 0) {
+ else if (name == "Width") {
_scValue->setInt(_width);
return _scValue;
}
@@ -406,7 +406,7 @@ ScValue *AdLayer::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Height
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Height") == 0) {
+ else if (name == "Height") {
_scValue->setInt(_height);
return _scValue;
}
@@ -414,7 +414,7 @@ ScValue *AdLayer::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Main (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Main") == 0) {
+ else if (name == "Main") {
_scValue->setBool(_main);
return _scValue;
}
@@ -422,7 +422,7 @@ ScValue *AdLayer::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// CloseUp
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "CloseUp") == 0) {
+ else if (name == "CloseUp") {
_scValue->setBool(_closeUp);
return _scValue;
}
@@ -430,7 +430,7 @@ ScValue *AdLayer::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Active
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Active") == 0) {
+ else if (name == "Active") {
_scValue->setBool(_active);
return _scValue;
} else {
diff --git a/engines/wintermute/ad/ad_layer.h b/engines/wintermute/ad/ad_layer.h
index bb5f73b13a..de65e2822f 100644
--- a/engines/wintermute/ad/ad_layer.h
+++ b/engines/wintermute/ad/ad_layer.h
@@ -47,7 +47,7 @@ public:
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent);
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
diff --git a/engines/wintermute/ad/ad_object.cpp b/engines/wintermute/ad/ad_object.cpp
index 6c77917979..7b91daab2e 100644
--- a/engines/wintermute/ad/ad_object.cpp
+++ b/engines/wintermute/ad/ad_object.cpp
@@ -37,18 +37,19 @@
#include "engines/wintermute/ad/ad_waypoint_group.h"
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/base/base_frame.h"
-#include "engines/wintermute/base/sound/base_sound.h"
-#include "engines/wintermute/base/base_surface_storage.h"
+#include "engines/wintermute/base/base_sprite.h"
+#include "engines/wintermute/base/base_string_table.h"
#include "engines/wintermute/base/base_sub_frame.h"
+#include "engines/wintermute/base/base_surface_storage.h"
#include "engines/wintermute/base/font/base_font.h"
#include "engines/wintermute/base/font/base_font_storage.h"
-#include "engines/wintermute/base/base_sprite.h"
-#include "engines/wintermute/base/base_string_table.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
+#include "engines/wintermute/base/particles/part_emitter.h"
#include "engines/wintermute/base/scriptables/script_engine.h"
#include "engines/wintermute/base/scriptables/script.h"
#include "engines/wintermute/base/scriptables/script_stack.h"
#include "engines/wintermute/base/scriptables/script_value.h"
-#include "engines/wintermute/base/particles/part_emitter.h"
+#include "engines/wintermute/base/sound/base_sound.h"
#include "common/str.h"
#include "common/util.h"
@@ -658,13 +659,13 @@ bool AdObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack
//////////////////////////////////////////////////////////////////////////
-ScValue *AdObject::scGetProperty(const char *name) {
+ScValue *AdObject::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("object");
return _scValue;
}
@@ -672,7 +673,7 @@ ScValue *AdObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Active
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Active") == 0) {
+ else if (name == "Active") {
_scValue->setBool(_active);
return _scValue;
}
@@ -680,7 +681,7 @@ ScValue *AdObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// IgnoreItems
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "IgnoreItems") == 0) {
+ else if (name == "IgnoreItems") {
_scValue->setBool(_ignoreItems);
return _scValue;
}
@@ -688,7 +689,7 @@ ScValue *AdObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// SceneIndependent
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SceneIndependent") == 0) {
+ else if (name == "SceneIndependent") {
_scValue->setBool(_sceneIndependent);
return _scValue;
}
@@ -696,7 +697,7 @@ ScValue *AdObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// SubtitlesWidth
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SubtitlesWidth") == 0) {
+ else if (name == "SubtitlesWidth") {
_scValue->setInt(_subtitlesWidth);
return _scValue;
}
@@ -704,7 +705,7 @@ ScValue *AdObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// SubtitlesPosRelative
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SubtitlesPosRelative") == 0) {
+ else if (name == "SubtitlesPosRelative") {
_scValue->setBool(_subtitlesModRelative);
return _scValue;
}
@@ -712,7 +713,7 @@ ScValue *AdObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// SubtitlesPosX
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SubtitlesPosX") == 0) {
+ else if (name == "SubtitlesPosX") {
_scValue->setInt(_subtitlesModX);
return _scValue;
}
@@ -720,7 +721,7 @@ ScValue *AdObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// SubtitlesPosY
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SubtitlesPosY") == 0) {
+ else if (name == "SubtitlesPosY") {
_scValue->setInt(_subtitlesModY);
return _scValue;
}
@@ -728,7 +729,7 @@ ScValue *AdObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// SubtitlesPosXCenter
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SubtitlesPosXCenter") == 0) {
+ else if (name == "SubtitlesPosXCenter") {
_scValue->setBool(_subtitlesModXCenter);
return _scValue;
}
@@ -736,7 +737,7 @@ ScValue *AdObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// NumItems (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "NumItems") == 0) {
+ else if (name == "NumItems") {
_scValue->setInt(getInventory()->_takenItems.size());
return _scValue;
}
@@ -744,7 +745,7 @@ ScValue *AdObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// ParticleEmitter (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ParticleEmitter") == 0) {
+ else if (name == "ParticleEmitter") {
if (_partEmitter) {
_scValue->setNative(_partEmitter, true);
} else {
@@ -757,7 +758,7 @@ ScValue *AdObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// NumAttachments (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "NumAttachments") == 0) {
+ else if (name == "NumAttachments") {
_scValue->setInt(_attachmentsPre.size() + _attachmentsPost.size());
return _scValue;
} else {
diff --git a/engines/wintermute/ad/ad_object.h b/engines/wintermute/ad/ad_object.h
index 8395f58cff..d1a20908e1 100644
--- a/engines/wintermute/ad/ad_object.h
+++ b/engines/wintermute/ad/ad_object.h
@@ -100,7 +100,7 @@ public:
AdRegion *_currentRegions[MAX_NUM_REGIONS];
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
diff --git a/engines/wintermute/ad/ad_region.cpp b/engines/wintermute/ad/ad_region.cpp
index 88bd8201a2..c9f1553c9a 100644
--- a/engines/wintermute/ad/ad_region.cpp
+++ b/engines/wintermute/ad/ad_region.cpp
@@ -27,12 +27,12 @@
*/
#include "engines/wintermute/ad/ad_region.h"
-#include "engines/wintermute/base/base_parser.h"
#include "engines/wintermute/base/base_dynamic_buffer.h"
-#include "engines/wintermute/base/scriptables/script_value.h"
-#include "engines/wintermute/base/scriptables/script.h"
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/base/base_parser.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/base/scriptables/script.h"
namespace Wintermute {
@@ -242,13 +242,13 @@ bool AdRegion::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack
//////////////////////////////////////////////////////////////////////////
-ScValue *AdRegion::scGetProperty(const char *name) {
+ScValue *AdRegion::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("ad region");
return _scValue;
}
@@ -256,7 +256,7 @@ ScValue *AdRegion::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Name
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Name") == 0) {
+ else if (name == "Name") {
_scValue->setString(getName());
return _scValue;
}
@@ -264,7 +264,7 @@ ScValue *AdRegion::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Blocked
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Blocked") == 0) {
+ else if (name == "Blocked") {
_scValue->setBool(_blocked);
return _scValue;
}
@@ -272,7 +272,7 @@ ScValue *AdRegion::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Decoration
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Decoration") == 0) {
+ else if (name == "Decoration") {
_scValue->setBool(_decoration);
return _scValue;
}
@@ -280,7 +280,7 @@ ScValue *AdRegion::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Scale
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Scale") == 0) {
+ else if (name == "Scale") {
_scValue->setFloat(_zoom);
return _scValue;
}
@@ -288,7 +288,7 @@ ScValue *AdRegion::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// AlphaColor
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AlphaColor") == 0) {
+ else if (name == "AlphaColor") {
_scValue->setInt((int)_alpha);
return _scValue;
} else {
diff --git a/engines/wintermute/ad/ad_region.h b/engines/wintermute/ad/ad_region.h
index a60cb9a3f2..6112900361 100644
--- a/engines/wintermute/ad/ad_region.h
+++ b/engines/wintermute/ad/ad_region.h
@@ -47,7 +47,7 @@ public:
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent);
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
diff --git a/engines/wintermute/ad/ad_response.cpp b/engines/wintermute/ad/ad_response.cpp
index 37f46118bf..a2225f2632 100644
--- a/engines/wintermute/ad/ad_response.cpp
+++ b/engines/wintermute/ad/ad_response.cpp
@@ -28,8 +28,8 @@
#include "engines/wintermute/ad/ad_response.h"
#include "engines/wintermute/base/base_game.h"
-#include "engines/wintermute/base/font/base_font_storage.h"
#include "engines/wintermute/base/base_sprite.h"
+#include "engines/wintermute/base/font/base_font_storage.h"
#include "engines/wintermute/utils/utils.h"
namespace Wintermute {
diff --git a/engines/wintermute/ad/ad_response_box.cpp b/engines/wintermute/ad/ad_response_box.cpp
index a27f1ca54b..fb31aa0bb8 100644
--- a/engines/wintermute/ad/ad_response_box.cpp
+++ b/engines/wintermute/ad/ad_response_box.cpp
@@ -27,19 +27,20 @@
*/
#include "engines/wintermute/ad/ad_game.h"
+#include "engines/wintermute/ad/ad_response.h"
#include "engines/wintermute/ad/ad_response_box.h"
+#include "engines/wintermute/base/base_dynamic_buffer.h"
+#include "engines/wintermute/base/base_file_manager.h"
#include "engines/wintermute/base/base_parser.h"
+#include "engines/wintermute/base/base_sprite.h"
#include "engines/wintermute/base/base_surface_storage.h"
-#include "engines/wintermute/ui/ui_button.h"
-#include "engines/wintermute/ui/ui_window.h"
-#include "engines/wintermute/base/base_dynamic_buffer.h"
#include "engines/wintermute/base/font/base_font_storage.h"
#include "engines/wintermute/base/font/base_font.h"
-#include "engines/wintermute/ad/ad_response.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
#include "engines/wintermute/base/scriptables/script.h"
#include "engines/wintermute/base/scriptables/script_stack.h"
-#include "engines/wintermute/base/base_sprite.h"
-#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/ui/ui_button.h"
+#include "engines/wintermute/ui/ui_window.h"
#include "engines/wintermute/utils/utils.h"
#include "engines/wintermute/platform_osystem.h"
#include "engines/wintermute/wintermute.h"
diff --git a/engines/wintermute/ad/ad_rot_level.cpp b/engines/wintermute/ad/ad_rot_level.cpp
index ca7ed693ad..fb9a4a47b9 100644
--- a/engines/wintermute/ad/ad_rot_level.cpp
+++ b/engines/wintermute/ad/ad_rot_level.cpp
@@ -27,11 +27,11 @@
*/
#include "engines/wintermute/ad/ad_rot_level.h"
-#include "engines/wintermute/base/base_parser.h"
#include "engines/wintermute/base/base_dynamic_buffer.h"
+#include "engines/wintermute/base/base_file_manager.h"
#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_parser.h"
#include "engines/wintermute/base/base_sprite.h"
-#include "engines/wintermute/base/base_file_manager.h"
namespace Wintermute {
diff --git a/engines/wintermute/ad/ad_scale_level.cpp b/engines/wintermute/ad/ad_scale_level.cpp
index 8b68cc5d32..4e9293d875 100644
--- a/engines/wintermute/ad/ad_scale_level.cpp
+++ b/engines/wintermute/ad/ad_scale_level.cpp
@@ -28,9 +28,9 @@
#include "engines/wintermute/ad/ad_scale_level.h"
#include "engines/wintermute/base/base_parser.h"
-#include "engines/wintermute/base/base_dynamic_buffer.h"
-#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_dynamic_buffer.h"
namespace Wintermute {
diff --git a/engines/wintermute/ad/ad_scene.cpp b/engines/wintermute/ad/ad_scene.cpp
index e47acc63c9..8e9beca0c0 100644
--- a/engines/wintermute/ad/ad_scene.cpp
+++ b/engines/wintermute/ad/ad_scene.cpp
@@ -52,6 +52,7 @@
#include "engines/wintermute/base/base_scriptable.h"
#include "engines/wintermute/base/base_sprite.h"
#include "engines/wintermute/base/base_viewport.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
#include "engines/wintermute/base/scriptables/script_stack.h"
#include "engines/wintermute/base/scriptables/script_value.h"
#include "engines/wintermute/base/scriptables/script.h"
@@ -1808,13 +1809,13 @@ bool AdScene::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack,
//////////////////////////////////////////////////////////////////////////
-ScValue *AdScene::scGetProperty(const char *name) {
+ScValue *AdScene::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("scene");
return _scValue;
}
@@ -1822,7 +1823,7 @@ ScValue *AdScene::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// NumLayers (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "NumLayers") == 0) {
+ else if (name == "NumLayers") {
_scValue->setInt(_layers.size());
return _scValue;
}
@@ -1830,7 +1831,7 @@ ScValue *AdScene::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// NumWaypointGroups (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "NumWaypointGroups") == 0) {
+ else if (name == "NumWaypointGroups") {
_scValue->setInt(_waypointGroups.size());
return _scValue;
}
@@ -1838,7 +1839,7 @@ ScValue *AdScene::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// MainLayer (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "MainLayer") == 0) {
+ else if (name == "MainLayer") {
if (_mainLayer) {
_scValue->setNative(_mainLayer, true);
} else {
@@ -1851,7 +1852,7 @@ ScValue *AdScene::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// NumFreeNodes (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "NumFreeNodes") == 0) {
+ else if (name == "NumFreeNodes") {
_scValue->setInt(_objects.size());
return _scValue;
}
@@ -1859,7 +1860,7 @@ ScValue *AdScene::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// MouseX (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "MouseX") == 0) {
+ else if (name == "MouseX") {
int viewportX;
getViewportOffset(&viewportX);
@@ -1870,7 +1871,7 @@ ScValue *AdScene::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// MouseY (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "MouseY") == 0) {
+ else if (name == "MouseY") {
int viewportY;
getViewportOffset(NULL, &viewportY);
@@ -1881,7 +1882,7 @@ ScValue *AdScene::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// AutoScroll
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AutoScroll") == 0) {
+ else if (name == "AutoScroll") {
_scValue->setBool(_autoScroll);
return _scValue;
}
@@ -1889,7 +1890,7 @@ ScValue *AdScene::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// PersistentState
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "PersistentState") == 0) {
+ else if (name == "PersistentState") {
_scValue->setBool(_persistentState);
return _scValue;
}
@@ -1897,7 +1898,7 @@ ScValue *AdScene::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// PersistentStateSprites
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "PersistentStateSprites") == 0) {
+ else if (name == "PersistentStateSprites") {
_scValue->setBool(_persistentStateSprites);
return _scValue;
}
@@ -1905,7 +1906,7 @@ ScValue *AdScene::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// ScrollPixelsX
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ScrollPixelsX") == 0) {
+ else if (name == "ScrollPixelsX") {
_scValue->setInt(_scrollPixelsH);
return _scValue;
}
@@ -1913,7 +1914,7 @@ ScValue *AdScene::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// ScrollPixelsY
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ScrollPixelsY") == 0) {
+ else if (name == "ScrollPixelsY") {
_scValue->setInt(_scrollPixelsV);
return _scValue;
}
@@ -1922,7 +1923,7 @@ ScValue *AdScene::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// ScrollSpeedX
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ScrollSpeedX") == 0) {
+ else if (name == "ScrollSpeedX") {
_scValue->setInt(_scrollTimeH);
return _scValue;
}
@@ -1930,7 +1931,7 @@ ScValue *AdScene::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// ScrollSpeedY
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ScrollSpeedY") == 0) {
+ else if (name == "ScrollSpeedY") {
_scValue->setInt(_scrollTimeV);
return _scValue;
}
@@ -1938,7 +1939,7 @@ ScValue *AdScene::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// OffsetX
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "OffsetX") == 0) {
+ else if (name == "OffsetX") {
_scValue->setInt(_offsetLeft);
return _scValue;
}
@@ -1946,7 +1947,7 @@ ScValue *AdScene::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// OffsetY
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "OffsetY") == 0) {
+ else if (name == "OffsetY") {
_scValue->setInt(_offsetTop);
return _scValue;
}
@@ -1954,7 +1955,7 @@ ScValue *AdScene::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Width (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Width") == 0) {
+ else if (name == "Width") {
if (_mainLayer) {
_scValue->setInt(_mainLayer->_width);
} else {
@@ -1966,7 +1967,7 @@ ScValue *AdScene::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Height (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Height") == 0) {
+ else if (name == "Height") {
if (_mainLayer) {
_scValue->setInt(_mainLayer->_height);
} else {
diff --git a/engines/wintermute/ad/ad_scene.h b/engines/wintermute/ad/ad_scene.h
index c9c0e413bf..3b482403b5 100644
--- a/engines/wintermute/ad/ad_scene.h
+++ b/engines/wintermute/ad/ad_scene.h
@@ -156,7 +156,7 @@ public:
int getPointsDist(BasePoint p1, BasePoint p2, BaseObject *requester = NULL);
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
diff --git a/engines/wintermute/ad/ad_scene_state.cpp b/engines/wintermute/ad/ad_scene_state.cpp
index c09e6a259c..6b34f1af53 100644
--- a/engines/wintermute/ad/ad_scene_state.cpp
+++ b/engines/wintermute/ad/ad_scene_state.cpp
@@ -26,9 +26,9 @@
* Copyright (c) 2011 Jan Nedoma
*/
-#include "engines/wintermute/persistent.h"
#include "engines/wintermute/ad/ad_scene_state.h"
#include "engines/wintermute/ad/ad_node_state.h"
+#include "engines/wintermute/persistent.h"
#include "engines/wintermute/platform_osystem.h"
#include "common/str.h"
diff --git a/engines/wintermute/ad/ad_sentence.cpp b/engines/wintermute/ad/ad_sentence.cpp
index 1f09d3ae0f..cfe4191b07 100644
--- a/engines/wintermute/ad/ad_sentence.cpp
+++ b/engines/wintermute/ad/ad_sentence.cpp
@@ -26,17 +26,18 @@
* Copyright (c) 2011 Jan Nedoma
*/
+#include "engines/wintermute/ad/ad_game.h"
+#include "engines/wintermute/ad/ad_scene.h"
#include "engines/wintermute/ad/ad_sentence.h"
#include "engines/wintermute/ad/ad_talk_def.h"
#include "engines/wintermute/ad/ad_talk_node.h"
-#include "engines/wintermute/ad/ad_game.h"
#include "engines/wintermute/utils/path_util.h"
#include "engines/wintermute/base/base_game.h"
-#include "engines/wintermute/base/sound/base_sound.h"
-#include "engines/wintermute/ad/ad_scene.h"
-#include "engines/wintermute/base/font/base_font.h"
#include "engines/wintermute/base/base_sprite.h"
#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/base/font/base_font.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
+#include "engines/wintermute/base/sound/base_sound.h"
namespace Wintermute {
diff --git a/engines/wintermute/ad/ad_sprite_set.cpp b/engines/wintermute/ad/ad_sprite_set.cpp
index c8cdec03c3..345b483a8f 100644
--- a/engines/wintermute/ad/ad_sprite_set.cpp
+++ b/engines/wintermute/ad/ad_sprite_set.cpp
@@ -27,10 +27,10 @@
*/
#include "engines/wintermute/ad/ad_sprite_set.h"
-#include "engines/wintermute/base/base_parser.h"
#include "engines/wintermute/base/base_dynamic_buffer.h"
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/base/base_parser.h"
#include "engines/wintermute/base/base_sprite.h"
namespace Wintermute {
diff --git a/engines/wintermute/ad/ad_talk_def.cpp b/engines/wintermute/ad/ad_talk_def.cpp
index 8cb489509b..a85cd7f986 100644
--- a/engines/wintermute/ad/ad_talk_def.cpp
+++ b/engines/wintermute/ad/ad_talk_def.cpp
@@ -26,13 +26,13 @@
* Copyright (c) 2011 Jan Nedoma
*/
+#include "engines/wintermute/ad/ad_sprite_set.h"
#include "engines/wintermute/ad/ad_talk_def.h"
#include "engines/wintermute/ad/ad_talk_node.h"
#include "engines/wintermute/base/base_parser.h"
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/base/base_dynamic_buffer.h"
#include "engines/wintermute/base/base_sprite.h"
-#include "engines/wintermute/ad/ad_sprite_set.h"
#include "engines/wintermute/base/base_file_manager.h"
#include "engines/wintermute/utils/utils.h"
diff --git a/engines/wintermute/ad/ad_talk_holder.cpp b/engines/wintermute/ad/ad_talk_holder.cpp
index 1e4ec26459..cca4fdc2cb 100644
--- a/engines/wintermute/ad/ad_talk_holder.cpp
+++ b/engines/wintermute/ad/ad_talk_holder.cpp
@@ -28,13 +28,13 @@
#include "engines/wintermute/ad/ad_talk_holder.h"
#include "engines/wintermute/base/base_dynamic_buffer.h"
+#include "engines/wintermute/base/base_engine.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_sprite.h"
#include "engines/wintermute/base/scriptables/script_value.h"
#include "engines/wintermute/base/scriptables/script.h"
#include "engines/wintermute/base/scriptables/script_stack.h"
-#include "engines/wintermute/base/base_game.h"
-#include "engines/wintermute/base/base_sprite.h"
#include "engines/wintermute/platform_osystem.h"
-#include "engines/wintermute/base/base_engine.h"
#include "common/str.h"
namespace Wintermute {
@@ -334,13 +334,13 @@ bool AdTalkHolder::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisS
//////////////////////////////////////////////////////////////////////////
-ScValue *AdTalkHolder::scGetProperty(const char *name) {
+ScValue *AdTalkHolder::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type (RO)
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("talk-holder");
return _scValue;
} else {
diff --git a/engines/wintermute/ad/ad_talk_holder.h b/engines/wintermute/ad/ad_talk_holder.h
index ce10364b3d..d52ebf63c0 100644
--- a/engines/wintermute/ad/ad_talk_holder.h
+++ b/engines/wintermute/ad/ad_talk_holder.h
@@ -45,7 +45,7 @@ public:
virtual ~AdTalkHolder();
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
diff --git a/engines/wintermute/ad/ad_talk_node.cpp b/engines/wintermute/ad/ad_talk_node.cpp
index b43a2b288e..c909ee27ff 100644
--- a/engines/wintermute/ad/ad_talk_node.cpp
+++ b/engines/wintermute/ad/ad_talk_node.cpp
@@ -26,12 +26,12 @@
* Copyright (c) 2011 Jan Nedoma
*/
+#include "engines/wintermute/ad/ad_sprite_set.h"
#include "engines/wintermute/ad/ad_talk_node.h"
#include "engines/wintermute/base/base_parser.h"
#include "engines/wintermute/base/base_dynamic_buffer.h"
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/base/base_sprite.h"
-#include "engines/wintermute/ad/ad_sprite_set.h"
#include "engines/wintermute/utils/utils.h"
namespace Wintermute {
@@ -264,9 +264,9 @@ bool AdTalkNode::loadSprite() {
bool AdTalkNode::isInTimeInterval(uint32 time, TDirection dir) {
if (time >= _startTime) {
if (_playToEnd) {
- if ((_spriteFilename && _sprite == NULL) || (_sprite && _sprite->_finished == false)) {
+ if ((_spriteFilename && _sprite == NULL) || (_sprite && _sprite->isFinished() == false)) {
return true;
- } else if ((_spriteSetFilename && _spriteSet == NULL) || (_spriteSet && _spriteSet->getSprite(dir) && _spriteSet->getSprite(dir)->_finished == false)) {
+ } else if ((_spriteSetFilename && _spriteSet == NULL) || (_spriteSet && _spriteSet->getSprite(dir) && _spriteSet->getSprite(dir)->isFinished() == false)) {
return true;
} else {
return false;
diff --git a/engines/wintermute/ad/ad_waypoint_group.cpp b/engines/wintermute/ad/ad_waypoint_group.cpp
index 984ed75aeb..81493ce769 100644
--- a/engines/wintermute/ad/ad_waypoint_group.cpp
+++ b/engines/wintermute/ad/ad_waypoint_group.cpp
@@ -27,12 +27,12 @@
*/
#include "engines/wintermute/ad/ad_waypoint_group.h"
-#include "engines/wintermute/base/base_parser.h"
#include "engines/wintermute/base/base_dynamic_buffer.h"
-#include "engines/wintermute/base/scriptables/script_value.h"
#include "engines/wintermute/base/base_game.h"
-#include "engines/wintermute/base/base_region.h"
#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/base/base_parser.h"
+#include "engines/wintermute/base/base_region.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
#include <limits.h>
namespace Wintermute {
@@ -206,13 +206,13 @@ bool AdWaypointGroup::persist(BasePersistenceManager *persistMgr) {
//////////////////////////////////////////////////////////////////////////
-ScValue *AdWaypointGroup::scGetProperty(const char *name) {
+ScValue *AdWaypointGroup::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("waypoint-group");
return _scValue;
}
@@ -220,7 +220,7 @@ ScValue *AdWaypointGroup::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Active
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Active") == 0) {
+ else if (name == "Active") {
_scValue->setBool(_active);
return _scValue;
} else {
diff --git a/engines/wintermute/ad/ad_waypoint_group.h b/engines/wintermute/ad/ad_waypoint_group.h
index 5cf6da1d1a..13d6bbadd7 100644
--- a/engines/wintermute/ad/ad_waypoint_group.h
+++ b/engines/wintermute/ad/ad_waypoint_group.h
@@ -49,7 +49,7 @@ public:
virtual ~AdWaypointGroup();
BaseArray<BasePoint *> _points;
int _editorSelectedPoint;
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
};
diff --git a/engines/wintermute/base/base_active_rect.cpp b/engines/wintermute/base/base_active_rect.cpp
index d754cf0114..4addf15be8 100644
--- a/engines/wintermute/base/base_active_rect.cpp
+++ b/engines/wintermute/base/base_active_rect.cpp
@@ -29,6 +29,7 @@
#include "engines/wintermute/base/base_active_rect.h"
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/base/base_region.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
#include "engines/wintermute/platform_osystem.h"
namespace Wintermute {
diff --git a/engines/wintermute/base/base_dynamic_buffer.h b/engines/wintermute/base/base_dynamic_buffer.h
index b6f3e12b9c..2d1a7fbe48 100644
--- a/engines/wintermute/base/base_dynamic_buffer.h
+++ b/engines/wintermute/base/base_dynamic_buffer.h
@@ -29,14 +29,12 @@
#ifndef WINTERMUTE_BASE_DYNAMIC_BUFFER_H
#define WINTERMUTE_BASE_DYNAMIC_BUFFER_H
-
#include "engines/wintermute/base/base.h"
namespace Wintermute {
class BaseDynamicBuffer {
public:
- bool _initialized;
void putText(const char *fmt, ...);
void putTextIndent(int indent, const char *fmt, ...);
uint32 getDWORD();
@@ -48,12 +46,13 @@ public:
uint32 getSize();
bool init(uint32 initSize = 0);
void cleanup();
- uint32 _size;
- byte *_buffer;
BaseDynamicBuffer(BaseGame *inGame, uint32 initSize = 1000, uint32 growBy = 1000);
virtual ~BaseDynamicBuffer();
private:
+ uint32 _size;
+ byte *_buffer;
+ bool _initialized;
uint32 _realSize;
uint32 _growBy;
uint32 _initSize;
diff --git a/engines/wintermute/base/base_engine.cpp b/engines/wintermute/base/base_engine.cpp
index 2368f8b106..8146d14beb 100644
--- a/engines/wintermute/base/base_engine.cpp
+++ b/engines/wintermute/base/base_engine.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.
@@ -25,7 +25,7 @@
* http://dead-code.org/redir.php?target=wmelite
* Copyright (c) 2011 Jan Nedoma
*/
-
+
#include "engines/wintermute/base/base_file_manager.h"
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/base/base_engine.h"
@@ -71,10 +71,10 @@ void BaseEngine::LOG(bool res, const char *fmt, ...) {
secs = secs % 3600;
uint32 mins = secs / 60;
secs = secs % 60;
-
+
char buff[512];
va_list va;
-
+
va_start(va, fmt);
vsprintf(buff, fmt, va);
va_end(va);
@@ -82,7 +82,7 @@ void BaseEngine::LOG(bool res, const char *fmt, ...) {
if (instance()._gameRef) {
instance()._gameRef->LOG("%s", buff);
} else {
- debugCN(kWintermuteDebugLog, "%02d:%02d:%02d: %s\n", hours, mins, secs, buff);
+ debugCN(kWintermuteDebugLog, "%02d:%02d:%02d: %s\n", hours, mins, secs, buff);
}
}
diff --git a/engines/wintermute/base/base_engine.h b/engines/wintermute/base/base_engine.h
index 1cef7b33ba..1ed0e3ab01 100644
--- a/engines/wintermute/base/base_engine.h
+++ b/engines/wintermute/base/base_engine.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -25,7 +25,7 @@
* http://dead-code.org/redir.php?target=wmelite
* Copyright (c) 2011 Jan Nedoma
*/
-
+
#ifndef WINTERMUTE_BASE_ENGINE_H
#define WINTERMUTE_BASE_ENGINE_H
diff --git a/engines/wintermute/base/base_fader.cpp b/engines/wintermute/base/base_fader.cpp
index 08e6f689ba..985718fcab 100644
--- a/engines/wintermute/base/base_fader.cpp
+++ b/engines/wintermute/base/base_fader.cpp
@@ -28,6 +28,7 @@
#include "engines/wintermute/base/base_fader.h"
#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
#include "common/util.h"
namespace Wintermute {
diff --git a/engines/wintermute/base/base_fader.h b/engines/wintermute/base/base_fader.h
index d3ced4aacc..116c8c963d 100644
--- a/engines/wintermute/base/base_fader.h
+++ b/engines/wintermute/base/base_fader.h
@@ -36,7 +36,6 @@ namespace Wintermute {
class BaseFader : public BaseObject {
public:
- bool _system;
uint32 getCurrentColor();
bool fadeOut(uint32 targetColor, uint32 duration, bool system = false);
bool fadeIn(uint32 sourceColor, uint32 duration, bool system = false);
@@ -47,6 +46,7 @@ public:
BaseFader(BaseGame *inGame);
virtual ~BaseFader();
private:
+ bool _system;
bool _active;
byte _red;
byte _green;
diff --git a/engines/wintermute/base/base_frame.cpp b/engines/wintermute/base/base_frame.cpp
index e1b29a3a5c..7c64144480 100644
--- a/engines/wintermute/base/base_frame.cpp
+++ b/engines/wintermute/base/base_frame.cpp
@@ -87,6 +87,12 @@ bool BaseFrame::draw(int x, int y, BaseObject *registerOwner, float zoomX, float
return STATUS_OK;
}
+void BaseFrame::stopSound() {
+ if (_sound) {
+ _sound->stop();
+ }
+}
+
//////////////////////////////////////////////////////////////////////////
bool BaseFrame::oneTimeDisplay(BaseObject *owner, bool muted) {
@@ -618,7 +624,7 @@ bool BaseFrame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStac
//////////////////////////////////////////////////////////////////////////
-ScValue *BaseFrame::scGetProperty(const char *name) {
+ScValue *BaseFrame::scGetProperty(const Common::String &name) {
if (!_scValue) {
_scValue = new ScValue(_gameRef);
}
@@ -627,7 +633,7 @@ ScValue *BaseFrame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Type (RO)
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("frame");
return _scValue;
}
@@ -635,7 +641,7 @@ ScValue *BaseFrame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Delay
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Delay") == 0) {
+ else if (name == "Delay") {
_scValue->setInt(_delay);
return _scValue;
}
@@ -643,7 +649,7 @@ ScValue *BaseFrame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Keyframe
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Keyframe") == 0) {
+ else if (name == "Keyframe") {
_scValue->setBool(_keyframe);
return _scValue;
}
@@ -651,7 +657,7 @@ ScValue *BaseFrame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// KillSounds
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "KillSounds") == 0) {
+ else if (name == "KillSounds") {
_scValue->setBool(_killSound);
return _scValue;
}
@@ -659,7 +665,7 @@ ScValue *BaseFrame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// MoveX
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "MoveX") == 0) {
+ else if (name == "MoveX") {
_scValue->setInt(_moveX);
return _scValue;
}
@@ -667,7 +673,7 @@ ScValue *BaseFrame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// MoveY
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "MoveY") == 0) {
+ else if (name == "MoveY") {
_scValue->setInt(_moveY);
return _scValue;
}
@@ -675,7 +681,7 @@ ScValue *BaseFrame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// NumSubframes (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "NumSubframes") == 0) {
+ else if (name == "NumSubframes") {
_scValue->setInt(_subframes.size());
return _scValue;
}
@@ -683,7 +689,7 @@ ScValue *BaseFrame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// NumEvents (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "NumEvents") == 0) {
+ else if (name == "NumEvents") {
_scValue->setInt(_applyEvent.size());
return _scValue;
}
diff --git a/engines/wintermute/base/base_frame.h b/engines/wintermute/base/base_frame.h
index ea5467b6fe..7c5d893e70 100644
--- a/engines/wintermute/base/base_frame.h
+++ b/engines/wintermute/base/base_frame.h
@@ -41,11 +41,10 @@ class ScStack;
class BaseFrame: public BaseScriptable {
public:
bool _killSound;
- bool _keyframe;
+ void stopSound();
bool oneTimeDisplay(BaseObject *owner, bool muted = false);
DECLARE_PERSISTENT(BaseFrame, BaseScriptable)
- BaseSound *_sound;
- bool _editorExpanded;
+
bool getBoundingRect(Rect32 *rect, int x, int y, float scaleX = 100, float scaleY = 100);
bool saveAsText(BaseDynamicBuffer *buffer, int indent);
int _moveY;
@@ -61,11 +60,14 @@ public:
BaseArray<const char *> _applyEvent;
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
-
+private:
+ bool _keyframe;
+ bool _editorExpanded;
+ BaseSound *_sound;
};
} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_game.cpp b/engines/wintermute/base/base_game.cpp
index 622e85cc11..b6886b7a33 100644
--- a/engines/wintermute/base/base_game.cpp
+++ b/engines/wintermute/base/base_game.cpp
@@ -64,6 +64,7 @@
#include "engines/wintermute/ui/ui_window.h"
#include "engines/wintermute/wintermute.h"
#include "engines/wintermute/platform_osystem.h"
+#include "base/version.h"
#include "common/config-manager.h"
#include "common/savefile.h"
#include "common/textconsole.h"
@@ -489,7 +490,7 @@ void BaseGame::DEBUG_DebugEnable(const char *filename) {
LOG(0, "********** DEBUG LOG OPENED %02d-%02d-%02d (Release Build) *****************", hours, mins, secs);
#endif
- LOG(0, "%s ver %d.%d.%d%s, Compiled on " __DATE__ ", " __TIME__, DCGF_NAME, DCGF_VER_MAJOR, DCGF_VER_MINOR, DCGF_VER_BUILD, DCGF_VER_SUFFIX);
+ LOG(0, "%s - %s ver %d.%d.%d%s ", gScummVMFullVersion, DCGF_NAME, DCGF_VER_MAJOR, DCGF_VER_MINOR, DCGF_VER_BUILD, DCGF_VER_SUFFIX);
AnsiString platform = BasePlatform::getPlatformName();
LOG(0, "Platform: %s", platform.c_str());
@@ -740,7 +741,7 @@ bool BaseGame::loadBuffer(byte *buffer, bool complete) {
TOKEN_TABLE(LOCAL_SAVE_DIR)
TOKEN_TABLE(COMPAT_KILL_METHOD_THREADS)
TOKEN_TABLE_END
-
+
// Declare a few variables necessary for moving data from these settings over to the renderer:
// The values are the same as the defaults set in BaseRenderer.
int loadImageX = 0;
@@ -2241,27 +2242,27 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack
//////////////////////////////////////////////////////////////////////////
-ScValue *BaseGame::scGetProperty(const char *name) {
+ScValue *BaseGame::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("game");
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// Name
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Name") == 0) {
+ else if (name == "Name") {
_scValue->setString(getName());
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// Hwnd (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Hwnd") == 0) {
+ else if (name == "Hwnd") {
_scValue->setInt((int)_renderer->_window);
return _scValue;
}
@@ -2269,7 +2270,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// CurrentTime (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "CurrentTime") == 0) {
+ else if (name == "CurrentTime") {
_scValue->setInt((int)_timer);
return _scValue;
}
@@ -2277,7 +2278,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// WindowsTime (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "WindowsTime") == 0) {
+ else if (name == "WindowsTime") {
_scValue->setInt((int)g_system->getMillis());
return _scValue;
}
@@ -2285,7 +2286,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// WindowedMode (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "WindowedMode") == 0) {
+ else if (name == "WindowedMode") {
_scValue->setBool(_renderer->_windowed);
return _scValue;
}
@@ -2293,7 +2294,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// MouseX
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "MouseX") == 0) {
+ else if (name == "MouseX") {
_scValue->setInt(_mousePos.x);
return _scValue;
}
@@ -2301,7 +2302,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// MouseY
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "MouseY") == 0) {
+ else if (name == "MouseY") {
_scValue->setInt(_mousePos.y);
return _scValue;
}
@@ -2309,7 +2310,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// MainObject
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "MainObject") == 0) {
+ else if (name == "MainObject") {
_scValue->setNative(_mainObject, true);
return _scValue;
}
@@ -2317,7 +2318,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// ActiveObject (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ActiveObject") == 0) {
+ else if (name == "ActiveObject") {
_scValue->setNative(_activeObject, true);
return _scValue;
}
@@ -2325,7 +2326,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// ScreenWidth (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ScreenWidth") == 0) {
+ else if (name == "ScreenWidth") {
_scValue->setInt(_renderer->_width);
return _scValue;
}
@@ -2333,7 +2334,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// ScreenHeight (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ScreenHeight") == 0) {
+ else if (name == "ScreenHeight") {
_scValue->setInt(_renderer->_height);
return _scValue;
}
@@ -2341,7 +2342,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Interactive
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Interactive") == 0) {
+ else if (name == "Interactive") {
_scValue->setBool(_interactive);
return _scValue;
}
@@ -2349,7 +2350,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// DebugMode (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "DebugMode") == 0) {
+ else if (name == "DebugMode") {
_scValue->setBool(_debugDebugMode);
return _scValue;
}
@@ -2357,7 +2358,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// SoundAvailable (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SoundAvailable") == 0) {
+ else if (name == "SoundAvailable") {
_scValue->setBool(_soundMgr->_soundAvailable);
return _scValue;
}
@@ -2365,7 +2366,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// SFXVolume
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SFXVolume") == 0) {
+ else if (name == "SFXVolume") {
_gameRef->LOG(0, "**Warning** The SFXVolume attribute is obsolete");
_scValue->setInt(_soundMgr->getVolumePercent(Audio::Mixer::kSFXSoundType));
return _scValue;
@@ -2374,7 +2375,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// SpeechVolume
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SpeechVolume") == 0) {
+ else if (name == "SpeechVolume") {
_gameRef->LOG(0, "**Warning** The SpeechVolume attribute is obsolete");
_scValue->setInt(_soundMgr->getVolumePercent(Audio::Mixer::kSpeechSoundType));
return _scValue;
@@ -2383,7 +2384,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// MusicVolume
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "MusicVolume") == 0) {
+ else if (name == "MusicVolume") {
_gameRef->LOG(0, "**Warning** The MusicVolume attribute is obsolete");
_scValue->setInt(_soundMgr->getVolumePercent(Audio::Mixer::kMusicSoundType));
return _scValue;
@@ -2392,7 +2393,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// MasterVolume
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "MasterVolume") == 0) {
+ else if (name == "MasterVolume") {
_gameRef->LOG(0, "**Warning** The MasterVolume attribute is obsolete");
_scValue->setInt(_soundMgr->getMasterVolumePercent());
return _scValue;
@@ -2401,7 +2402,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Keyboard (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Keyboard") == 0) {
+ else if (name == "Keyboard") {
if (_keyboardState) {
_scValue->setNative(_keyboardState, true);
} else {
@@ -2414,7 +2415,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Subtitles
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Subtitles") == 0) {
+ else if (name == "Subtitles") {
_scValue->setBool(_subtitles);
return _scValue;
}
@@ -2422,14 +2423,14 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// SubtitlesSpeed
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SubtitlesSpeed") == 0) {
+ else if (name == "SubtitlesSpeed") {
_scValue->setInt(_subtitlesSpeed);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// VideoSubtitles
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "VideoSubtitles") == 0) {
+ else if (name == "VideoSubtitles") {
_scValue->setBool(_videoSubtitles);
return _scValue;
}
@@ -2437,7 +2438,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// FPS (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "FPS") == 0) {
+ else if (name == "FPS") {
_scValue->setInt(_fps);
return _scValue;
}
@@ -2445,7 +2446,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// AcceleratedMode / Accelerated (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AcceleratedMode") == 0 || strcmp(name, "Accelerated") == 0) {
+ else if (name == "AcceleratedMode" || name == "Accelerated") {
_scValue->setBool(_useD3D);
return _scValue;
}
@@ -2453,7 +2454,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// TextEncoding
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "TextEncoding") == 0) {
+ else if (name == "TextEncoding") {
_scValue->setInt(_textEncoding);
return _scValue;
}
@@ -2461,7 +2462,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// TextRTL
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "TextRTL") == 0) {
+ else if (name == "TextRTL") {
_scValue->setBool(_textRTL);
return _scValue;
}
@@ -2469,7 +2470,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// SoundBufferSize
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SoundBufferSize") == 0) {
+ else if (name == "SoundBufferSize") {
_scValue->setInt(_soundBufferSizeSec);
return _scValue;
}
@@ -2477,7 +2478,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// SuspendedRendering
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SuspendedRendering") == 0) {
+ else if (name == "SuspendedRendering") {
_scValue->setBool(_suspendedRendering);
return _scValue;
}
@@ -2485,7 +2486,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// SuppressScriptErrors
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SuppressScriptErrors") == 0) {
+ else if (name == "SuppressScriptErrors") {
_scValue->setBool(_suppressScriptErrors);
return _scValue;
}
@@ -2494,7 +2495,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Frozen
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Frozen") == 0) {
+ else if (name == "Frozen") {
_scValue->setBool(_state == GAME_FROZEN);
return _scValue;
}
@@ -2502,7 +2503,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// AccTTSEnabled
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AccTTSEnabled") == 0) {
+ else if (name == "AccTTSEnabled") {
_scValue->setBool(false);
return _scValue;
}
@@ -2510,7 +2511,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// AccTTSTalk
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AccTTSTalk") == 0) {
+ else if (name == "AccTTSTalk") {
_scValue->setBool(false);
return _scValue;
}
@@ -2518,7 +2519,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// AccTTSCaptions
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AccTTSCaptions") == 0) {
+ else if (name == "AccTTSCaptions") {
_scValue->setBool(false);
return _scValue;
}
@@ -2526,7 +2527,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// AccTTSKeypress
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AccTTSKeypress") == 0) {
+ else if (name == "AccTTSKeypress") {
_scValue->setBool(false);
return _scValue;
}
@@ -2534,7 +2535,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// AccKeyboardEnabled
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AccKeyboardEnabled") == 0) {
+ else if (name == "AccKeyboardEnabled") {
_scValue->setBool(false);
return _scValue;
}
@@ -2542,7 +2543,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// AccKeyboardCursorSkip
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AccKeyboardCursorSkip") == 0) {
+ else if (name == "AccKeyboardCursorSkip") {
_scValue->setBool(false);
return _scValue;
}
@@ -2550,7 +2551,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// AccKeyboardPause
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AccKeyboardPause") == 0) {
+ else if (name == "AccKeyboardPause") {
_scValue->setBool(false);
return _scValue;
}
@@ -2558,7 +2559,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// AutorunDisabled
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AutorunDisabled") == 0) {
+ else if (name == "AutorunDisabled") {
_scValue->setBool(_autorunDisabled);
return _scValue;
}
@@ -2566,7 +2567,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// SaveDirectory (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SaveDirectory") == 0) {
+ else if (name == "SaveDirectory") {
AnsiString dataDir = "saves/"; // TODO: This is just to avoid telling the engine actual paths.
_scValue->setString(dataDir.c_str());
return _scValue;
@@ -2575,7 +2576,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// AutoSaveOnExit
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AutoSaveOnExit") == 0) {
+ else if (name == "AutoSaveOnExit") {
_scValue->setBool(_autoSaveOnExit);
return _scValue;
}
@@ -2583,7 +2584,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// AutoSaveSlot
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AutoSaveSlot") == 0) {
+ else if (name == "AutoSaveSlot") {
_scValue->setInt(_autoSaveSlot);
return _scValue;
}
@@ -2591,7 +2592,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// CursorHidden
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "CursorHidden") == 0) {
+ else if (name == "CursorHidden") {
_scValue->setBool(_cursorHidden);
return _scValue;
}
@@ -2599,7 +2600,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Platform (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Platform") == 0) {
+ else if (name == "Platform") {
_scValue->setString(BasePlatform::getPlatformName().c_str());
return _scValue;
}
@@ -2607,7 +2608,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// DeviceType (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "DeviceType") == 0) {
+ else if (name == "DeviceType") {
_scValue->setString(getDeviceType().c_str());
return _scValue;
}
@@ -2615,7 +2616,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// MostRecentSaveSlot (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "MostRecentSaveSlot") == 0) {
+ else if (name == "MostRecentSaveSlot") {
if (!ConfMan.hasKey("most_recent_saveslot")) {
_scValue->setInt(-1);
} else {
@@ -2627,7 +2628,7 @@ ScValue *BaseGame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Store (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Store") == 0) {
+ else if (name == "Store") {
_scValue->setNULL();
error("Request for a SXStore-object, which is not supported by ScummVM");
@@ -3624,7 +3625,7 @@ bool BaseGame::persist(BasePersistenceManager *persistMgr) {
persistMgr->transfer(TMEMBER(_musicCrossfadeChannel1));
persistMgr->transfer(TMEMBER(_musicCrossfadeChannel2));
persistMgr->transfer(TMEMBER(_musicCrossfadeSwap));
-
+
_renderer->persistSaveLoadImages(persistMgr);
persistMgr->transfer(TMEMBER_INT(_textEncoding));
diff --git a/engines/wintermute/base/base_game.h b/engines/wintermute/base/base_game.h
index 93cbc4536b..0f764b3d03 100644
--- a/engines/wintermute/base/base_game.h
+++ b/engines/wintermute/base/base_game.h
@@ -29,7 +29,6 @@
#ifndef WINTERMUTE_BASE_GAME_H
#define WINTERMUTE_BASE_GAME_H
-#include "engines/wintermute/base/gfx/base_renderer.h"
#include "engines/wintermute/base/base_object.h"
#include "engines/wintermute/persistent.h"
#include "engines/wintermute/coll_templ.h"
@@ -165,7 +164,7 @@ public:
virtual bool externalCall(ScScript *script, ScStack *stack, ScStack *thisStack, char *name);
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
diff --git a/engines/wintermute/base/base_keyboard_state.cpp b/engines/wintermute/base/base_keyboard_state.cpp
index fd5f2b0e1d..da7baafd2d 100644
--- a/engines/wintermute/base/base_keyboard_state.cpp
+++ b/engines/wintermute/base/base_keyboard_state.cpp
@@ -103,13 +103,13 @@ bool BaseKeyboardState::scCallMethod(ScScript *script, ScStack *stack, ScStack *
//////////////////////////////////////////////////////////////////////////
-ScValue *BaseKeyboardState::scGetProperty(const char *name) {
+ScValue *BaseKeyboardState::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("keyboard");
return _scValue;
}
@@ -117,7 +117,7 @@ ScValue *BaseKeyboardState::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Key
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Key") == 0) {
+ else if (name == "Key") {
if (_currentPrintable) {
char key[2];
key[0] = (char)_currentCharCode;
@@ -133,7 +133,7 @@ ScValue *BaseKeyboardState::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Printable
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Printable") == 0) {
+ else if (name == "Printable") {
_scValue->setBool(_currentPrintable);
return _scValue;
}
@@ -141,7 +141,7 @@ ScValue *BaseKeyboardState::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// KeyCode
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "KeyCode") == 0) {
+ else if (name == "KeyCode") {
_scValue->setInt(_currentCharCode);
return _scValue;
}
@@ -149,7 +149,7 @@ ScValue *BaseKeyboardState::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// IsShift
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "IsShift") == 0) {
+ else if (name == "IsShift") {
_scValue->setBool(_currentShift);
return _scValue;
}
@@ -157,7 +157,7 @@ ScValue *BaseKeyboardState::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// IsAlt
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "IsAlt") == 0) {
+ else if (name == "IsAlt") {
_scValue->setBool(_currentAlt);
return _scValue;
}
@@ -165,7 +165,7 @@ ScValue *BaseKeyboardState::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// IsControl
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "IsControl") == 0) {
+ else if (name == "IsControl") {
_scValue->setBool(_currentControl);
return _scValue;
} else {
diff --git a/engines/wintermute/base/base_keyboard_state.h b/engines/wintermute/base/base_keyboard_state.h
index ebc0c83ee1..dfd0efdec0 100644
--- a/engines/wintermute/base/base_keyboard_state.h
+++ b/engines/wintermute/base/base_keyboard_state.h
@@ -59,7 +59,7 @@ public:
static bool isAltDown();
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
diff --git a/engines/wintermute/base/base_object.cpp b/engines/wintermute/base/base_object.cpp
index b6a6887624..eba8416485 100644
--- a/engines/wintermute/base/base_object.cpp
+++ b/engines/wintermute/base/base_object.cpp
@@ -531,13 +531,13 @@ bool BaseObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisSta
//////////////////////////////////////////////////////////////////////////
-ScValue *BaseObject::scGetProperty(const char *name) {
+ScValue *BaseObject::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("object");
return _scValue;
}
@@ -545,7 +545,7 @@ ScValue *BaseObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Caption
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Caption") == 0) {
+ else if (name == "Caption") {
_scValue->setString(getCaption(1));
return _scValue;
}
@@ -553,7 +553,7 @@ ScValue *BaseObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// X
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "X") == 0) {
+ else if (name == "X") {
_scValue->setInt(_posX);
return _scValue;
}
@@ -561,7 +561,7 @@ ScValue *BaseObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Y
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Y") == 0) {
+ else if (name == "Y") {
_scValue->setInt(_posY);
return _scValue;
}
@@ -569,7 +569,7 @@ ScValue *BaseObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Height (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Height") == 0) {
+ else if (name == "Height") {
_scValue->setInt(getHeight());
return _scValue;
}
@@ -577,7 +577,7 @@ ScValue *BaseObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Ready (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Ready") == 0) {
+ else if (name == "Ready") {
_scValue->setBool(_ready);
return _scValue;
}
@@ -585,7 +585,7 @@ ScValue *BaseObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Movable
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Movable") == 0) {
+ else if (name == "Movable") {
_scValue->setBool(_movable);
return _scValue;
}
@@ -593,7 +593,7 @@ ScValue *BaseObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Registrable/Interactive
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Registrable") == 0 || strcmp(name, "Interactive") == 0) {
+ else if (name == "Registrable" || name == "Interactive") {
_scValue->setBool(_registrable);
return _scValue;
}
@@ -601,21 +601,21 @@ ScValue *BaseObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Zoomable/Scalable
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Zoomable") == 0 || strcmp(name, "Scalable") == 0) {
+ else if (name == "Zoomable" || name == "Scalable") {
_scValue->setBool(_zoomable);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// Rotatable
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Rotatable") == 0) {
+ else if (name == "Rotatable") {
_scValue->setBool(_rotatable);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// AlphaColor
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AlphaColor") == 0) {
+ else if (name == "AlphaColor") {
_scValue->setInt((int)_alphaColor);
return _scValue;
}
@@ -623,7 +623,7 @@ ScValue *BaseObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// BlendMode
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "BlendMode") == 0) {
+ else if (name == "BlendMode") {
_scValue->setInt((int)_blendMode);
return _scValue;
}
@@ -631,7 +631,7 @@ ScValue *BaseObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Scale
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Scale") == 0) {
+ else if (name == "Scale") {
if (_scale < 0) {
_scValue->setNULL();
} else {
@@ -643,7 +643,7 @@ ScValue *BaseObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// ScaleX
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ScaleX") == 0) {
+ else if (name == "ScaleX") {
if (_scaleX < 0) {
_scValue->setNULL();
} else {
@@ -655,7 +655,7 @@ ScValue *BaseObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// ScaleY
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ScaleY") == 0) {
+ else if (name == "ScaleY") {
if (_scaleY < 0) {
_scValue->setNULL();
} else {
@@ -667,7 +667,7 @@ ScValue *BaseObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// RelativeScale
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "RelativeScale") == 0) {
+ else if (name == "RelativeScale") {
_scValue->setFloat((double)_relativeScale);
return _scValue;
}
@@ -675,7 +675,7 @@ ScValue *BaseObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Rotate
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Rotate") == 0) {
+ else if (name == "Rotate") {
if (!_rotateValid) {
_scValue->setNULL();
} else {
@@ -687,7 +687,7 @@ ScValue *BaseObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// RelativeRotate
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "RelativeRotate") == 0) {
+ else if (name == "RelativeRotate") {
_scValue->setFloat((double)_relativeRotate);
return _scValue;
}
@@ -695,14 +695,14 @@ ScValue *BaseObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Colorable
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Colorable") == 0) {
+ else if (name == "Colorable") {
_scValue->setBool(_shadowable);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// SoundPanning
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SoundPanning") == 0) {
+ else if (name == "SoundPanning") {
_scValue->setBool(_autoSoundPanning);
return _scValue;
}
@@ -710,7 +710,7 @@ ScValue *BaseObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// SaveState
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SaveState") == 0) {
+ else if (name == "SaveState") {
_scValue->setBool(_saveState);
return _scValue;
}
@@ -718,7 +718,7 @@ ScValue *BaseObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// NonIntMouseEvents
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "NonIntMouseEvents") == 0) {
+ else if (name == "NonIntMouseEvents") {
_scValue->setBool(_nonIntMouseEvents);
return _scValue;
}
@@ -726,7 +726,7 @@ ScValue *BaseObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// AccCaption
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AccCaption") == 0) {
+ else if (name == "AccCaption") {
_scValue->setNULL();
return _scValue;
} else {
diff --git a/engines/wintermute/base/base_object.h b/engines/wintermute/base/base_object.h
index 34adbdb585..d7d91a25f6 100644
--- a/engines/wintermute/base/base_object.h
+++ b/engines/wintermute/base/base_object.h
@@ -136,7 +136,7 @@ public:
public:
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
diff --git a/engines/wintermute/base/base_quick_msg.h b/engines/wintermute/base/base_quick_msg.h
index 4fed5ffc2e..67f9613461 100644
--- a/engines/wintermute/base/base_quick_msg.h
+++ b/engines/wintermute/base/base_quick_msg.h
@@ -37,10 +37,10 @@ class BaseQuickMsg : public BaseClass {
public:
char *getText();
uint32 _startTime;
- char *_text;
- BaseQuickMsg(BaseGame *inGame, const char *Text);
+ BaseQuickMsg(BaseGame *inGame, const char *text);
virtual ~BaseQuickMsg();
-
+private:
+ char *_text;
};
} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_region.cpp b/engines/wintermute/base/base_region.cpp
index e332ffe9ff..0bc5975e51 100644
--- a/engines/wintermute/base/base_region.cpp
+++ b/engines/wintermute/base/base_region.cpp
@@ -327,13 +327,13 @@ bool BaseRegion::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisSta
//////////////////////////////////////////////////////////////////////////
-ScValue *BaseRegion::scGetProperty(const char *name) {
+ScValue *BaseRegion::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("region");
return _scValue;
}
@@ -341,7 +341,7 @@ ScValue *BaseRegion::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Name
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Name") == 0) {
+ else if (name == "Name") {
_scValue->setString(getName());
return _scValue;
}
@@ -349,7 +349,7 @@ ScValue *BaseRegion::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Active
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Active") == 0) {
+ else if (name == "Active") {
_scValue->setBool(_active);
return _scValue;
}
@@ -357,7 +357,7 @@ ScValue *BaseRegion::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// NumPoints
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "NumPoints") == 0) {
+ else if (name == "NumPoints") {
_scValue->setInt(_points.size());
return _scValue;
} else {
diff --git a/engines/wintermute/base/base_region.h b/engines/wintermute/base/base_region.h
index 8dd02fe928..464f25be2f 100644
--- a/engines/wintermute/base/base_region.h
+++ b/engines/wintermute/base/base_region.h
@@ -36,9 +36,6 @@ namespace Wintermute {
class BaseRegion : public BaseObject {
public:
- float _lastMimicScale;
- int _lastMimicX;
- int _lastMimicY;
void cleanup();
bool mimic(BaseRegion *region, float scale = 100.0f, int x = 0, int y = 0);
bool getBoundingRect(Rect32 *rect);
@@ -58,10 +55,14 @@ public:
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent, const char *nameOverride);
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
+private:
+ float _lastMimicScale;
+ int _lastMimicX;
+ int _lastMimicY;
};
} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_save_thumb_helper.cpp b/engines/wintermute/base/base_save_thumb_helper.cpp
index 186e1234a8..b4205c21c4 100644
--- a/engines/wintermute/base/base_save_thumb_helper.cpp
+++ b/engines/wintermute/base/base_save_thumb_helper.cpp
@@ -28,6 +28,7 @@
#include "engines/wintermute/base/base_save_thumb_helper.h"
#include "engines/wintermute/base/gfx/base_image.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
#include "engines/wintermute/base/base_game.h"
namespace Wintermute {
diff --git a/engines/wintermute/base/base_script_holder.cpp b/engines/wintermute/base/base_script_holder.cpp
index d3e6078d43..c5d5e82f76 100644
--- a/engines/wintermute/base/base_script_holder.cpp
+++ b/engines/wintermute/base/base_script_holder.cpp
@@ -219,13 +219,13 @@ bool BaseScriptHolder::scCallMethod(ScScript *script, ScStack *stack, ScStack *t
//////////////////////////////////////////////////////////////////////////
-ScValue *BaseScriptHolder::scGetProperty(const char *name) {
+ScValue *BaseScriptHolder::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("script_holder");
return _scValue;
}
@@ -233,7 +233,7 @@ ScValue *BaseScriptHolder::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Name
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Name") == 0) {
+ else if (name == "Name") {
_scValue->setString(getName());
return _scValue;
}
@@ -241,7 +241,7 @@ ScValue *BaseScriptHolder::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Filename (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Filename") == 0) {
+ else if (name == "Filename") {
_scValue->setString(_filename);
return _scValue;
} else {
diff --git a/engines/wintermute/base/base_script_holder.h b/engines/wintermute/base/base_script_holder.h
index 0c3d7a1a70..5fd0dbec9c 100644
--- a/engines/wintermute/base/base_script_holder.h
+++ b/engines/wintermute/base/base_script_holder.h
@@ -59,7 +59,7 @@ public:
BaseArray<ScScript *> _scripts;
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
diff --git a/engines/wintermute/base/base_scriptable.cpp b/engines/wintermute/base/base_scriptable.cpp
index 143934402b..a2dd8b00e7 100644
--- a/engines/wintermute/base/base_scriptable.cpp
+++ b/engines/wintermute/base/base_scriptable.cpp
@@ -76,12 +76,12 @@ bool BaseScriptable::scCallMethod(ScScript *script, ScStack *stack, ScStack *thi
//////////////////////////////////////////////////////////////////////////
-ScValue *BaseScriptable::scGetProperty(const char *name) {
+ScValue *BaseScriptable::scGetProperty(const Common::String &name) {
if (!_scProp) {
_scProp = new ScValue(_gameRef);
}
if (_scProp) {
- return _scProp->getProp(name);
+ return _scProp->getProp(name.c_str()); // TODO: Change to Common::String
} else {
return NULL;
}
diff --git a/engines/wintermute/base/base_scriptable.h b/engines/wintermute/base/base_scriptable.h
index b006e6e07c..fbe14fc299 100644
--- a/engines/wintermute/base/base_scriptable.h
+++ b/engines/wintermute/base/base_scriptable.h
@@ -50,7 +50,7 @@ public:
// high level scripting interface
virtual bool canHandleMethod(const char *eventMethod);
virtual bool scSetProperty(const char *name, ScValue *value);
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
virtual void *scToMemBuffer();
diff --git a/engines/wintermute/base/base_sprite.cpp b/engines/wintermute/base/base_sprite.cpp
index e2dd8bbd39..468af1bd75 100644
--- a/engines/wintermute/base/base_sprite.cpp
+++ b/engines/wintermute/base/base_sprite.cpp
@@ -121,6 +121,13 @@ bool BaseSprite::draw(int x, int y, BaseObject *registerOwner, float zoomX, floa
return display(x, y, registerOwner, zoomX, zoomY, alpha);
}
+bool BaseSprite::isChanged() {
+ return _changed;
+}
+
+bool BaseSprite::isFinished() {
+ return _finished;
+}
//////////////////////////////////////////////////////////////////////
bool BaseSprite::loadFile(const Common::String &filename, int lifeTime, TSpriteCacheType cacheType) {
@@ -686,13 +693,13 @@ bool BaseSprite::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisSta
//////////////////////////////////////////////////////////////////////////
-ScValue *BaseSprite::scGetProperty(const char *name) {
+ScValue *BaseSprite::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("sprite");
return _scValue;
}
@@ -700,7 +707,7 @@ ScValue *BaseSprite::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// NumFrames (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "NumFrames") == 0) {
+ else if (name == "NumFrames") {
_scValue->setInt(_frames.size());
return _scValue;
}
@@ -708,7 +715,7 @@ ScValue *BaseSprite::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// CurrentFrame
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "CurrentFrame") == 0) {
+ else if (name == "CurrentFrame") {
_scValue->setInt(_currentFrame);
return _scValue;
}
@@ -716,7 +723,7 @@ ScValue *BaseSprite::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// PixelPerfect
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "PixelPerfect") == 0) {
+ else if (name == "PixelPerfect") {
_scValue->setBool(_precise);
return _scValue;
}
@@ -724,7 +731,7 @@ ScValue *BaseSprite::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Looping
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Looping") == 0) {
+ else if (name == "Looping") {
_scValue->setBool(_looping);
return _scValue;
}
@@ -732,7 +739,7 @@ ScValue *BaseSprite::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Owner (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Owner") == 0) {
+ else if (name == "Owner") {
if (_owner == NULL) {
_scValue->setNULL();
} else {
@@ -744,7 +751,7 @@ ScValue *BaseSprite::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Finished (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Finished") == 0) {
+ else if (name == "Finished") {
_scValue->setBool(_finished);
return _scValue;
}
@@ -752,7 +759,7 @@ ScValue *BaseSprite::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Paused (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Paused") == 0) {
+ else if (name == "Paused") {
_scValue->setBool(_paused);
return _scValue;
} else {
@@ -804,9 +811,7 @@ const char *BaseSprite::scToString() {
//////////////////////////////////////////////////////////////////////////
bool BaseSprite::killAllSounds() {
for (uint32 i = 0; i < _frames.size(); i++) {
- if (_frames[i]->_sound) {
- _frames[i]->_sound->stop();
- }
+ _frames[i]->stopSound();
}
return STATUS_OK;
}
diff --git a/engines/wintermute/base/base_sprite.h b/engines/wintermute/base/base_sprite.h
index c861ca9930..1d244c3a52 100644
--- a/engines/wintermute/base/base_sprite.h
+++ b/engines/wintermute/base/base_sprite.h
@@ -39,36 +39,21 @@ class BaseSurface;
class BaseObject;
class BaseSprite: public BaseScriptHolder {
public:
- bool killAllSounds();
BaseSurface *getSurface();
- char *_editorBgFile;
- int _editorBgOffsetX;
- int _editorBgOffsetY;
- int _editorBgAlpha;
- bool _streamed;
- bool _streamedKeepLoaded;
void cleanup();
void setDefaults();
- bool _precise;
DECLARE_PERSISTENT(BaseSprite, BaseScriptHolder)
- bool _editorAllFrames;
bool getBoundingRect(Rect32 *rect, int x, int y, float scaleX = 100, float scaleY = 100);
int _moveY;
int _moveX;
bool display(int x, int y, BaseObject *registerOwner = NULL, 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 _canBreak;
- bool _editorMuted;
- bool _continuous;
void reset();
- BaseObject *_owner;
- bool _changed;
- bool _paused;
- bool _finished;
+ bool isChanged();
+ bool isFinished();
bool loadBuffer(byte *buffer, bool compete = true, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL);
bool loadFile(const Common::String &filename, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL);
- uint32 _lastFrameTime;
bool draw(int x, int y, BaseObject *Register = NULL, float zoomX = 100, float zoomY = 100, uint32 alpha = 0xFFFFFFFF);
bool _looping;
int _currentFrame;
@@ -79,10 +64,28 @@ public:
bool saveAsText(BaseDynamicBuffer *buffer, int indent);
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
+private:
+ BaseObject *_owner;
+ bool _canBreak;
+ bool _changed;
+ bool _editorAllFrames;
+ char *_editorBgFile;
+ int _editorBgOffsetX;
+ int _editorBgOffsetY;
+ int _editorBgAlpha;
+ bool _editorMuted;
+ bool _finished;
+ bool _continuous;
+ uint32 _lastFrameTime;
+ bool _precise;
+ bool _paused;
+ bool _streamed;
+ bool _streamedKeepLoaded;
+ bool killAllSounds();
};
} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_sub_frame.cpp b/engines/wintermute/base/base_sub_frame.cpp
index 6a9246efd4..77cc522ae7 100644
--- a/engines/wintermute/base/base_sub_frame.cpp
+++ b/engines/wintermute/base/base_sub_frame.cpp
@@ -34,6 +34,7 @@
#include "engines/wintermute/base/base_surface_storage.h"
#include "engines/wintermute/base/base_game.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"
@@ -225,6 +226,9 @@ void BaseSubFrame::setRect(Rect32 rect) {
_rect = rect;
}
+const char* BaseSubFrame::getSurfaceFilename() {
+ return _surfaceFilename;
+}
//////////////////////////////////////////////////////////////////////
bool BaseSubFrame::draw(int x, int y, BaseObject *registerOwner, float zoomX, float zoomY, bool precise, uint32 alpha, float rotate, TSpriteBlendMode blendMode) {
@@ -442,7 +446,7 @@ bool BaseSubFrame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisS
//////////////////////////////////////////////////////////////////////////
-ScValue *BaseSubFrame::scGetProperty(const char *name) {
+ScValue *BaseSubFrame::scGetProperty(const Common::String &name) {
if (!_scValue) {
_scValue = new ScValue(_gameRef);
}
@@ -451,7 +455,7 @@ ScValue *BaseSubFrame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Type (RO)
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("subframe");
return _scValue;
}
@@ -459,7 +463,7 @@ ScValue *BaseSubFrame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// AlphaColor
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AlphaColor") == 0) {
+ else if (name == "AlphaColor") {
_scValue->setInt((int)_alpha);
return _scValue;
@@ -468,7 +472,7 @@ ScValue *BaseSubFrame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// TransparentColor (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "TransparentColor") == 0) {
+ else if (name == "TransparentColor") {
_scValue->setInt((int)_transparent);
return _scValue;
}
@@ -476,7 +480,7 @@ ScValue *BaseSubFrame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Is2DOnly
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Is2DOnly") == 0) {
+ else if (name == "Is2DOnly") {
_scValue->setBool(_2DOnly);
return _scValue;
}
@@ -484,7 +488,7 @@ ScValue *BaseSubFrame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Is3DOnly
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Is3DOnly") == 0) {
+ else if (name == "Is3DOnly") {
_scValue->setBool(_3DOnly);
return _scValue;
}
@@ -492,7 +496,7 @@ ScValue *BaseSubFrame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// MirrorX
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "MirrorX") == 0) {
+ else if (name == "MirrorX") {
_scValue->setBool(_mirrorX);
return _scValue;
}
@@ -500,7 +504,7 @@ ScValue *BaseSubFrame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// MirrorY
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "MirrorY") == 0) {
+ else if (name == "MirrorY") {
_scValue->setBool(_mirrorY);
return _scValue;
}
@@ -508,7 +512,7 @@ ScValue *BaseSubFrame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Decoration
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Decoration") == 0) {
+ else if (name == "Decoration") {
_scValue->setBool(_decoration);
return _scValue;
}
@@ -516,7 +520,7 @@ ScValue *BaseSubFrame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// HotspotX
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "HotspotX") == 0) {
+ else if (name == "HotspotX") {
_scValue->setInt(_hotspotX);
return _scValue;
}
@@ -524,7 +528,7 @@ ScValue *BaseSubFrame::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// HotspotY
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "HotspotY") == 0) {
+ else if (name == "HotspotY") {
_scValue->setInt(_hotspotY);
return _scValue;
} else {
diff --git a/engines/wintermute/base/base_sub_frame.h b/engines/wintermute/base/base_sub_frame.h
index b174c6e5f0..c173ae69d1 100644
--- a/engines/wintermute/base/base_sub_frame.h
+++ b/engines/wintermute/base/base_sub_frame.h
@@ -54,6 +54,7 @@ public:
bool loadBuffer(byte *buffer, int lifeTime, bool keepLoaded);
bool draw(int x, int y, BaseObject *registerOwner = NULL, 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();
int _hotspotX;
int _hotspotY;
@@ -65,6 +66,7 @@ public:
private:
bool _wantsDefaultRect;
Rect32 _rect;
+ char *_surfaceFilename;
public:
bool _cKDefault;
byte _cKRed;
@@ -72,7 +74,6 @@ public:
byte _cKBlue;
int _lifeTime;
bool _keepLoaded;
- char *_surfaceFilename;
bool _2DOnly;
bool _3DOnly;
@@ -80,7 +81,7 @@ public:
BaseSurface *_surface;
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
diff --git a/engines/wintermute/base/base_surface_storage.cpp b/engines/wintermute/base/base_surface_storage.cpp
index 1dcebb0595..4e795ca813 100644
--- a/engines/wintermute/base/base_surface_storage.cpp
+++ b/engines/wintermute/base/base_surface_storage.cpp
@@ -28,6 +28,7 @@
#include "engines/wintermute/base/base_surface_storage.h"
#include "engines/wintermute/base/gfx/base_surface.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/base/base_file_manager.h"
#include "engines/wintermute/platform_osystem.h"
diff --git a/engines/wintermute/base/base_transition_manager.cpp b/engines/wintermute/base/base_transition_manager.cpp
index 5c28f36d30..7785f3d5af 100644
--- a/engines/wintermute/base/base_transition_manager.cpp
+++ b/engines/wintermute/base/base_transition_manager.cpp
@@ -28,6 +28,7 @@
#include "engines/wintermute/base/base_transition_manager.h"
#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
namespace Wintermute {
diff --git a/engines/wintermute/base/base_viewport.cpp b/engines/wintermute/base/base_viewport.cpp
index 3b003e1c49..7ec995449f 100644
--- a/engines/wintermute/base/base_viewport.cpp
+++ b/engines/wintermute/base/base_viewport.cpp
@@ -29,6 +29,7 @@
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/platform_osystem.h"
#include "engines/wintermute/base/base_viewport.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
namespace Wintermute {
diff --git a/engines/wintermute/base/file/base_disk_file.cpp b/engines/wintermute/base/file/base_disk_file.cpp
index 2d3951b026..25be3dad2d 100644
--- a/engines/wintermute/base/file/base_disk_file.cpp
+++ b/engines/wintermute/base/file/base_disk_file.cpp
@@ -178,10 +178,8 @@ Common::SeekableReadStream *openDiskFile(const Common::String &filename) {
}
delete[] compBuffer;
-
- return new Common::MemoryReadStream(data, uncompSize, DisposeAfterUse::YES);
delete file;
- file = NULL;
+ return new Common::MemoryReadStream(data, uncompSize, DisposeAfterUse::YES);
} else {
file->seek(0, SEEK_SET);
return file;
diff --git a/engines/wintermute/base/file/base_package.cpp b/engines/wintermute/base/file/base_package.cpp
index 9780992652..51a1558a7c 100644
--- a/engines/wintermute/base/file/base_package.cpp
+++ b/engines/wintermute/base/file/base_package.cpp
@@ -86,16 +86,16 @@ void TPackageHeader::readFromStream(Common::ReadStream *stream) {
_magic1 = stream->readUint32LE();
_magic2 = stream->readUint32LE();
_packageVersion = stream->readUint32LE();
-
+
_gameVersion = stream->readUint32LE();
-
+
_priority = stream->readByte();
_cd = stream->readByte();
_masterIndex = stream->readByte();
stream->readByte(); // To align the next byte...
-
+
_creationTime = stream->readUint32LE();
-
+
stream->read(_desc, 100);
_numDirs = stream->readUint32LE();
}
diff --git a/engines/wintermute/base/file/base_save_thumb_file.cpp b/engines/wintermute/base/file/base_save_thumb_file.cpp
index 5bdab0853e..94d3e5a94e 100644
--- a/engines/wintermute/base/file/base_save_thumb_file.cpp
+++ b/engines/wintermute/base/file/base_save_thumb_file.cpp
@@ -28,7 +28,6 @@
#include "engines/wintermute/base/base_persistence_manager.h"
#include "engines/wintermute/base/file/base_save_thumb_file.h"
-#include "engines/wintermute/platform_osystem.h"
namespace Wintermute {
diff --git a/engines/wintermute/base/font/base_font_bitmap.cpp b/engines/wintermute/base/font/base_font_bitmap.cpp
index fced08c7e2..55f46c476b 100644
--- a/engines/wintermute/base/font/base_font_bitmap.cpp
+++ b/engines/wintermute/base/font/base_font_bitmap.cpp
@@ -31,6 +31,7 @@
#include "engines/wintermute/base/base_parser.h"
#include "engines/wintermute/base/base_frame.h"
#include "engines/wintermute/base/gfx/base_surface.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/base/base_sub_frame.h"
#include "engines/wintermute/base/base_frame.h"
diff --git a/engines/wintermute/base/font/base_font_storage.cpp b/engines/wintermute/base/font/base_font_storage.cpp
index d26fa1d593..8128ffe897 100644
--- a/engines/wintermute/base/font/base_font_storage.cpp
+++ b/engines/wintermute/base/font/base_font_storage.cpp
@@ -29,7 +29,6 @@
#include "engines/wintermute/base/font/base_font_storage.h"
#include "engines/wintermute/base/font/base_font.h"
#include "engines/wintermute/base/base_game.h"
-#include "engines/wintermute/platform_osystem.h"
#include "common/str.h"
namespace Wintermute {
diff --git a/engines/wintermute/base/font/base_font_truetype.cpp b/engines/wintermute/base/font/base_font_truetype.cpp
index 599010bbd5..f236329fcd 100644
--- a/engines/wintermute/base/font/base_font_truetype.cpp
+++ b/engines/wintermute/base/font/base_font_truetype.cpp
@@ -26,11 +26,8 @@
* Copyright (c) 2011 Jan Nedoma
*/
-#include "engines/wintermute/base/file/base_file.h"
#include "engines/wintermute/base/font/base_font_truetype.h"
-#include "engines/wintermute/utils/path_util.h"
#include "engines/wintermute/utils/string_util.h"
-#include "engines/wintermute/math/math_util.h"
#include "engines/wintermute/base/gfx/base_renderer.h"
#include "engines/wintermute/base/gfx/base_surface.h"
#include "engines/wintermute/base/base_parser.h"
@@ -162,6 +159,11 @@ void BaseFontTT::drawText(const byte *text, int x, int y, int width, TTextAlign
// 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) {
+ textStr = StringUtil::ansiToWide((char *)text);
+ }
if (maxLength >= 0 && textStr.size() > (uint32)maxLength) {
textStr = Common::String(textStr.c_str(), (uint32)maxLength);
diff --git a/engines/wintermute/base/gfx/base_renderer.cpp b/engines/wintermute/base/gfx/base_renderer.cpp
index 9205438a5b..e7ffc14c25 100644
--- a/engines/wintermute/base/gfx/base_renderer.cpp
+++ b/engines/wintermute/base/gfx/base_renderer.cpp
@@ -129,13 +129,13 @@ void BaseRenderer::initSaveLoad(bool isSaving, bool quickSave) {
_indicatorDisplay = true;
_indicatorProgress = 0;
_hasDrawnSaveLoadImage = false;
-
+
if (isSaving && !quickSave) {
delete _saveLoadImage;
_saveLoadImage = NULL;
if (_saveImageName.size()) {
_saveLoadImage = createSurface();
-
+
if (!_saveLoadImage || DID_FAIL(_saveLoadImage->create(_saveImageName, true, 0, 0, 0))) {
delete _saveLoadImage;
_saveLoadImage = NULL;
@@ -146,7 +146,7 @@ void BaseRenderer::initSaveLoad(bool isSaving, bool quickSave) {
_saveLoadImage = NULL;
if (_loadImageName.size()) {
_saveLoadImage = createSurface();
-
+
if (!_saveLoadImage || DID_FAIL(_saveLoadImage->create(_loadImageName, true, 0, 0, 0))) {
delete _saveLoadImage;
_saveLoadImage = NULL;
@@ -360,7 +360,7 @@ bool BaseRenderer::displayIndicator() {
flip();
_hasDrawnSaveLoadImage = true;
}
-
+
if ((!_indicatorDisplay && _indicatorWidth <= 0) || _indicatorHeight <= 0) {
return STATUS_OK;
}
@@ -369,7 +369,7 @@ bool BaseRenderer::displayIndicator() {
for (int i = 0; i < _indicatorHeight; i++) {
drawLine(_indicatorX, _indicatorY + i, _indicatorX + curWidth, _indicatorY + i, _indicatorColor);
}
-
+
setup2D();
_indicatorWidthDrawn = curWidth;
if (_indicatorWidthDrawn) {
diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
index 6d67253038..7970a25300 100644
--- a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
+++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
@@ -261,7 +261,7 @@ void BaseRenderOSystem::fade(uint16 alpha) {
void BaseRenderOSystem::fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect) {
// This particular warning is rather messy, as this function is called a ton,
// thus we avoid printing it more than once.
-
+
// TODO: Add fading with dirty rects.
if (!_disableDirtyRects) {
warning("BaseRenderOSystem::FadeToColor - Breaks when using dirty rects");
@@ -573,6 +573,11 @@ 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));
diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
index d5464782a3..bee876bb65 100644
--- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
+++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
@@ -26,7 +26,6 @@
* Copyright (c) 2011 Jan Nedoma
*/
-#include "engines/wintermute/base/file/base_file.h"
#include "engines/wintermute/base/base_file_manager.h"
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/base/gfx/osystem/base_surface_osystem.h"
diff --git a/engines/wintermute/base/particles/part_emitter.cpp b/engines/wintermute/base/particles/part_emitter.cpp
index 3655b89131..bab4d4609e 100644
--- a/engines/wintermute/base/particles/part_emitter.cpp
+++ b/engines/wintermute/base/particles/part_emitter.cpp
@@ -35,6 +35,7 @@
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/base/base_region.h"
#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"
@@ -603,41 +604,41 @@ bool PartEmitter::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisSt
}
//////////////////////////////////////////////////////////////////////////
-ScValue *PartEmitter::scGetProperty(const char *name) {
+ScValue *PartEmitter::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("particle-emitter");
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// X
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "X") == 0) {
+ else if (name == "X") {
_scValue->setInt(_posX);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// Y
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Y") == 0) {
+ else if (name == "Y") {
_scValue->setInt(_posY);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// Width
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Width") == 0) {
+ else if (name == "Width") {
_scValue->setInt(_width);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// Height
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Height") == 0) {
+ else if (name == "Height") {
_scValue->setInt(_height);
return _scValue;
}
@@ -645,21 +646,21 @@ ScValue *PartEmitter::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Scale1
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Scale1") == 0) {
+ else if (name == "Scale1") {
_scValue->setFloat(_scale1);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// Scale2
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Scale2") == 0) {
+ else if (name == "Scale2") {
_scValue->setFloat(_scale2);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// ScaleZBased
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ScaleZBased") == 0) {
+ else if (name == "ScaleZBased") {
_scValue->setBool(_scaleZBased);
return _scValue;
}
@@ -667,21 +668,21 @@ ScValue *PartEmitter::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Velocity1
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Velocity1") == 0) {
+ else if (name == "Velocity1") {
_scValue->setFloat(_velocity1);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// Velocity2
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Velocity2") == 0) {
+ else if (name == "Velocity2") {
_scValue->setFloat(_velocity2);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// VelocityZBased
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "VelocityZBased") == 0) {
+ else if (name == "VelocityZBased") {
_scValue->setBool(_velocityZBased);
return _scValue;
}
@@ -689,21 +690,21 @@ ScValue *PartEmitter::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// LifeTime1
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "LifeTime1") == 0) {
+ else if (name == "LifeTime1") {
_scValue->setInt(_lifeTime1);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// LifeTime2
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "LifeTime2") == 0) {
+ else if (name == "LifeTime2") {
_scValue->setInt(_lifeTime2);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// LifeTimeZBased
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "LifeTimeZBased") == 0) {
+ else if (name == "LifeTimeZBased") {
_scValue->setBool(_lifeTimeZBased);
return _scValue;
}
@@ -711,14 +712,14 @@ ScValue *PartEmitter::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Angle1
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Angle1") == 0) {
+ else if (name == "Angle1") {
_scValue->setInt(_angle1);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// Angle2
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Angle2") == 0) {
+ else if (name == "Angle2") {
_scValue->setInt(_angle2);
return _scValue;
}
@@ -726,14 +727,14 @@ ScValue *PartEmitter::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// AngVelocity1
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AngVelocity1") == 0) {
+ else if (name == "AngVelocity1") {
_scValue->setFloat(_angVelocity1);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// AngVelocity2
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AngVelocity2") == 0) {
+ else if (name == "AngVelocity2") {
_scValue->setFloat(_angVelocity2);
return _scValue;
}
@@ -741,14 +742,14 @@ ScValue *PartEmitter::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Rotation1
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Rotation1") == 0) {
+ else if (name == "Rotation1") {
_scValue->setFloat(_rotation1);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// Rotation2
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Rotation2") == 0) {
+ else if (name == "Rotation2") {
_scValue->setFloat(_rotation2);
return _scValue;
}
@@ -756,21 +757,21 @@ ScValue *PartEmitter::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Alpha1
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Alpha1") == 0) {
+ else if (name == "Alpha1") {
_scValue->setInt(_alpha1);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// Alpha2
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Alpha2") == 0) {
+ else if (name == "Alpha2") {
_scValue->setInt(_alpha2);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// AlphaTimeBased
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AlphaTimeBased") == 0) {
+ else if (name == "AlphaTimeBased") {
_scValue->setBool(_alphaTimeBased);
return _scValue;
}
@@ -778,14 +779,14 @@ ScValue *PartEmitter::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// MaxParticles
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "MaxParticles") == 0) {
+ else if (name == "MaxParticles") {
_scValue->setInt(_maxParticles);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// NumLiveParticles (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "NumLiveParticles") == 0) {
+ else if (name == "NumLiveParticles") {
int numAlive = 0;
for (uint32 i = 0; i < _particles.size(); i++) {
if (_particles[i] && !_particles[i]->_isDead) {
@@ -799,21 +800,21 @@ ScValue *PartEmitter::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// GenerationInterval
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GenerationInterval") == 0) {
+ else if (name == "GenerationInterval") {
_scValue->setInt(_genInterval);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// GenerationAmount
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GenerationAmount") == 0) {
+ else if (name == "GenerationAmount") {
_scValue->setInt(_genAmount);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// MaxBatches
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "MaxBatches") == 0) {
+ else if (name == "MaxBatches") {
_scValue->setInt(_maxBatches);
return _scValue;
}
@@ -821,14 +822,14 @@ ScValue *PartEmitter::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// FadeInTime
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "FadeInTime") == 0) {
+ else if (name == "FadeInTime") {
_scValue->setInt(_fadeInTime);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// FadeOutTime
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "FadeOutTime") == 0) {
+ else if (name == "FadeOutTime") {
_scValue->setInt(_fadeOutTime);
return _scValue;
}
@@ -836,21 +837,21 @@ ScValue *PartEmitter::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// GrowthRate1
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GrowthRate1") == 0) {
+ else if (name == "GrowthRate1") {
_scValue->setFloat(_growthRate1);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// GrowthRate2
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GrowthRate2") == 0) {
+ else if (name == "GrowthRate2") {
_scValue->setFloat(_growthRate2);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// ExponentialGrowth
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ExponentialGrowth") == 0) {
+ else if (name == "ExponentialGrowth") {
_scValue->setBool(_exponentialGrowth);
return _scValue;
}
@@ -858,7 +859,7 @@ ScValue *PartEmitter::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// UseRegion
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "UseRegion") == 0) {
+ else if (name == "UseRegion") {
_scValue->setBool(_useRegion);
return _scValue;
}
@@ -866,7 +867,7 @@ ScValue *PartEmitter::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// EmitEvent
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "EmitEvent") == 0) {
+ else if (name == "EmitEvent") {
if (!_emitEvent) {
_scValue->setNULL();
} else {
diff --git a/engines/wintermute/base/particles/part_emitter.h b/engines/wintermute/base/particles/part_emitter.h
index 9a35cd9bbc..f2c8f139f1 100644
--- a/engines/wintermute/base/particles/part_emitter.h
+++ b/engines/wintermute/base/particles/part_emitter.h
@@ -63,7 +63,7 @@ public:
BaseArray<PartForce *> _forces;
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
diff --git a/engines/wintermute/base/saveload.cpp b/engines/wintermute/base/saveload.cpp
index 06e9fd2565..12204e1b35 100644
--- a/engines/wintermute/base/saveload.cpp
+++ b/engines/wintermute/base/saveload.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.
@@ -35,6 +35,7 @@
#include "engines/wintermute/base/base_region.h"
#include "engines/wintermute/base/base_sub_frame.h"
#include "engines/wintermute/base/font/base_font.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
#include "engines/wintermute/base/sound/base_sound.h"
#include "engines/wintermute/base/scriptables/script.h"
#include "common/savefile.h"
@@ -44,11 +45,11 @@ namespace Wintermute {
bool SaveLoad::loadGame(const Common::String &filename, BaseGame *gameRef) {
gameRef->LOG(0, "Loading game '%s'...", filename.c_str());
-
+
bool ret;
-
+
gameRef->_renderer->initSaveLoad(false);
-
+
gameRef->_loadInProgress = true;
BasePersistenceManager *pm = new BasePersistenceManager();
if (DID_SUCCEED(ret = pm->initLoad(filename))) {
@@ -60,20 +61,20 @@ bool SaveLoad::loadGame(const Common::String &filename, BaseGame *gameRef) {
// data initialization after load
SaveLoad::initAfterLoad();
-
+
gameRef->applyEvent("AfterLoad", true);
-
+
gameRef->displayContent(true, false);
//_renderer->flip();
}
}
}
-
+
delete pm;
gameRef->_loadInProgress = false;
-
+
gameRef->_renderer->endSaveLoad();
-
+
//_gameRef->LOG(0, "Load end %d", BaseUtils::GetUsedMemMB());
// AdGame:
if (DID_SUCCEED(ret)) {
@@ -84,13 +85,13 @@ bool SaveLoad::loadGame(const Common::String &filename, BaseGame *gameRef) {
bool SaveLoad::saveGame(int slot, const char *desc, bool quickSave, BaseGame *gameRef) {
Common::String filename = SaveLoad::getSaveSlotFilename(slot);
-
+
gameRef->LOG(0, "Saving game '%s'...", filename.c_str());
-
+
gameRef->applyEvent("BeforeSave", true);
-
+
bool ret;
-
+
BasePersistenceManager *pm = new BasePersistenceManager();
if (DID_SUCCEED(ret = pm->initSave(desc))) {
gameRef->_renderer->initSaveLoad(true, quickSave); // TODO: The original code inited the indicator before the conditionals
@@ -103,11 +104,11 @@ bool SaveLoad::saveGame(int slot, const char *desc, bool quickSave, BaseGame *ga
}
}
}
-
+
delete pm;
-
+
gameRef->_renderer->endSaveLoad();
-
+
return ret;
}
@@ -165,21 +166,21 @@ Common::String SaveLoad::getSaveSlotFilename(int slot) {
bool SaveLoad::getSaveSlotDescription(int slot, char *buffer) {
buffer[0] = '\0';
-
+
Common::String filename = getSaveSlotFilename(slot);
BasePersistenceManager *pm = new BasePersistenceManager();
if (!pm) {
return false;
}
-
+
if (!(pm->initLoad(filename))) {
delete pm;
return false;
}
-
+
strcpy(buffer, pm->_savedDescription);
delete pm;
-
+
return true;
}
@@ -198,6 +199,6 @@ bool SaveLoad::emptySaveSlot(int slot) {
delete pm;
return true;
}
-
-
+
+
} // end of namespace Wintermute
diff --git a/engines/wintermute/base/saveload.h b/engines/wintermute/base/saveload.h
index e448cc8814..722f7a89b6 100644
--- a/engines/wintermute/base/saveload.h
+++ b/engines/wintermute/base/saveload.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -25,7 +25,7 @@
* http://dead-code.org/redir.php?target=wmelite
* Copyright (c) 2011 Jan Nedoma
*/
-
+
#ifndef WINTERMUTE_SAVEGAME_H
#define WINTERMUTE_SAVEGAME_H
@@ -39,7 +39,7 @@ public:
static bool isSaveSlotUsed(int slot);
static bool getSaveSlotDescription(int slot, char *buffer);
static Common::String getSaveSlotFilename(int slot);
-
+
static bool loadGame(const Common::String &filename, BaseGame *gameRef);
static bool saveGame(int slot, const char *desc, bool quickSave, BaseGame *gameRef);
static bool initAfterLoad();
diff --git a/engines/wintermute/base/scriptables/script_engine.cpp b/engines/wintermute/base/scriptables/script_engine.cpp
index 20e2ccadd1..3d1863946e 100644
--- a/engines/wintermute/base/scriptables/script_engine.cpp
+++ b/engines/wintermute/base/scriptables/script_engine.cpp
@@ -33,7 +33,6 @@
#include "engines/wintermute/base/scriptables/script_ext_math.h"
#include "engines/wintermute/base/base_engine.h"
#include "engines/wintermute/base/base_game.h"
-#include "engines/wintermute/base/sound/base_sound.h"
#include "engines/wintermute/base/base_file_manager.h"
#include "engines/wintermute/utils/utils.h"
diff --git a/engines/wintermute/base/scriptables/script_ext_array.cpp b/engines/wintermute/base/scriptables/script_ext_array.cpp
index 5ed07f0da6..613cbd0758 100644
--- a/engines/wintermute/base/scriptables/script_ext_array.cpp
+++ b/engines/wintermute/base/scriptables/script_ext_array.cpp
@@ -140,13 +140,13 @@ bool SXArray::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack,
//////////////////////////////////////////////////////////////////////////
-ScValue *SXArray::scGetProperty(const char *name) {
+ScValue *SXArray::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("array");
return _scValue;
}
@@ -154,7 +154,7 @@ ScValue *SXArray::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Length
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Length") == 0) {
+ else if (name == "Length") {
_scValue->setInt(_length);
return _scValue;
}
@@ -164,7 +164,7 @@ ScValue *SXArray::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
else {
char paramName[20];
- if (validNumber(name, paramName)) {
+ if (validNumber(name.c_str(), paramName)) { // TODO: Change to Common::String
return _values->getProp(paramName);
} else {
return _scValue;
diff --git a/engines/wintermute/base/scriptables/script_ext_array.h b/engines/wintermute/base/scriptables/script_ext_array.h
index d9805ef94f..284c547a27 100644
--- a/engines/wintermute/base/scriptables/script_ext_array.h
+++ b/engines/wintermute/base/scriptables/script_ext_array.h
@@ -41,7 +41,7 @@ public:
SXArray(BaseGame *inGame, ScStack *stack);
SXArray(BaseGame *inGame);
virtual ~SXArray();
- ScValue *scGetProperty(const char *name);
+ ScValue *scGetProperty(const Common::String &name);
bool scSetProperty(const char *name, ScValue *value);
bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
const char *scToString();
diff --git a/engines/wintermute/base/scriptables/script_ext_date.cpp b/engines/wintermute/base/scriptables/script_ext_date.cpp
index 11eead3b9c..5aa069d0b2 100644
--- a/engines/wintermute/base/scriptables/script_ext_date.cpp
+++ b/engines/wintermute/base/scriptables/script_ext_date.cpp
@@ -203,13 +203,13 @@ bool SXDate::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack,
//////////////////////////////////////////////////////////////////////////
-ScValue *SXDate::scGetProperty(const char *name) {
+ScValue *SXDate::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("date");
return _scValue;
} else {
@@ -224,7 +224,7 @@ bool SXDate::scSetProperty(const char *name, ScValue *value) {
//////////////////////////////////////////////////////////////////////////
// Name
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Name")==0){
+ if (name == "Name")==0){
setName(value->getString());
return STATUS_OK;
}
diff --git a/engines/wintermute/base/scriptables/script_ext_date.h b/engines/wintermute/base/scriptables/script_ext_date.h
index f6f04dd7e6..062b7c55c7 100644
--- a/engines/wintermute/base/scriptables/script_ext_date.h
+++ b/engines/wintermute/base/scriptables/script_ext_date.h
@@ -40,7 +40,7 @@ public:
DECLARE_PERSISTENT(SXDate, BaseScriptable)
SXDate(BaseGame *inGame, ScStack *Stack);
virtual ~SXDate();
- ScValue *scGetProperty(const char *name);
+ ScValue *scGetProperty(const Common::String &name);
bool scSetProperty(const char *name, ScValue *value);
bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
const char *scToString();
diff --git a/engines/wintermute/base/scriptables/script_ext_file.cpp b/engines/wintermute/base/scriptables/script_ext_file.cpp
index ab574d464b..a1d39c5d0a 100644
--- a/engines/wintermute/base/scriptables/script_ext_file.cpp
+++ b/engines/wintermute/base/scriptables/script_ext_file.cpp
@@ -33,7 +33,6 @@
#include "engines/wintermute/base/scriptables/script.h"
#include "engines/wintermute/utils/utils.h"
#include "engines/wintermute/base/base_game.h"
-#include "engines/wintermute/base/file/base_file.h"
#include "engines/wintermute/base/base_file_manager.h"
#include "engines/wintermute/platform_osystem.h"
#include "engines/wintermute/base/scriptables/script_ext_file.h"
@@ -641,13 +640,13 @@ bool SXFile::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack,
//////////////////////////////////////////////////////////////////////////
-ScValue *SXFile::scGetProperty(const char *name) {
+ScValue *SXFile::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type (RO)
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("file");
return _scValue;
}
@@ -655,7 +654,7 @@ ScValue *SXFile::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Filename (RO)
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Filename") == 0) {
+ if (name == "Filename") {
_scValue->setString(_filename);
return _scValue;
}
@@ -663,7 +662,7 @@ ScValue *SXFile::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Position (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Position") == 0) {
+ else if (name == "Position") {
_scValue->setInt(getPos());
return _scValue;
}
@@ -671,7 +670,7 @@ ScValue *SXFile::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Length (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Length") == 0) {
+ else if (name == "Length") {
_scValue->setInt(getLength());
return _scValue;
}
@@ -679,7 +678,7 @@ ScValue *SXFile::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// TextMode (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "TextMode") == 0) {
+ else if (name == "TextMode") {
_scValue->setBool(_textMode);
return _scValue;
}
@@ -687,7 +686,7 @@ ScValue *SXFile::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// AccessMode (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AccessMode") == 0) {
+ else if (name == "AccessMode") {
_scValue->setInt(_mode);
return _scValue;
} else {
diff --git a/engines/wintermute/base/scriptables/script_ext_file.h b/engines/wintermute/base/scriptables/script_ext_file.h
index b91a53e695..f7c72fcfb3 100644
--- a/engines/wintermute/base/scriptables/script_ext_file.h
+++ b/engines/wintermute/base/scriptables/script_ext_file.h
@@ -40,7 +40,7 @@ class BaseFile;
class SXFile : public BaseScriptable {
public:
DECLARE_PERSISTENT(SXFile, BaseScriptable)
- ScValue *scGetProperty(const char *name);
+ ScValue *scGetProperty(const Common::String &name);
bool scSetProperty(const char *name, ScValue *value);
bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
const char *scToString();
diff --git a/engines/wintermute/base/scriptables/script_ext_math.cpp b/engines/wintermute/base/scriptables/script_ext_math.cpp
index 598b80cff3..d816fbec65 100644
--- a/engines/wintermute/base/scriptables/script_ext_math.cpp
+++ b/engines/wintermute/base/scriptables/script_ext_math.cpp
@@ -250,13 +250,13 @@ bool SXMath::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack,
//////////////////////////////////////////////////////////////////////////
-ScValue *SXMath::scGetProperty(const char *name) {
+ScValue *SXMath::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("math");
return _scValue;
}
@@ -264,7 +264,7 @@ ScValue *SXMath::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// PI
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "PI") == 0) {
+ else if (name == "PI") {
_scValue->setFloat(M_PI);
return _scValue;
} else {
diff --git a/engines/wintermute/base/scriptables/script_ext_math.h b/engines/wintermute/base/scriptables/script_ext_math.h
index f86d59fe7b..48c43ea7e8 100644
--- a/engines/wintermute/base/scriptables/script_ext_math.h
+++ b/engines/wintermute/base/scriptables/script_ext_math.h
@@ -39,7 +39,7 @@ public:
DECLARE_PERSISTENT(SXMath, BaseScriptable)
SXMath(BaseGame *inGame);
virtual ~SXMath();
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
private:
diff --git a/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp b/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp
index 5ed9bd5313..8f05b7bff6 100644
--- a/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp
+++ b/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp
@@ -447,13 +447,13 @@ bool SXMemBuffer::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisSt
//////////////////////////////////////////////////////////////////////////
-ScValue *SXMemBuffer::scGetProperty(const char *name) {
+ScValue *SXMemBuffer::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type (RO)
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("membuffer");
return _scValue;
}
@@ -461,7 +461,7 @@ ScValue *SXMemBuffer::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Size (RO)
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Size") == 0) {
+ if (name == "Size") {
_scValue->setInt(_size);
return _scValue;
} else {
diff --git a/engines/wintermute/base/scriptables/script_ext_mem_buffer.h b/engines/wintermute/base/scriptables/script_ext_mem_buffer.h
index d2662b3036..1527a323dc 100644
--- a/engines/wintermute/base/scriptables/script_ext_mem_buffer.h
+++ b/engines/wintermute/base/scriptables/script_ext_mem_buffer.h
@@ -38,7 +38,7 @@ class SXMemBuffer : public BaseScriptable {
public:
virtual int scCompare(BaseScriptable *Val);
DECLARE_PERSISTENT(SXMemBuffer, BaseScriptable)
- ScValue *scGetProperty(const char *name);
+ ScValue *scGetProperty(const Common::String &name);
bool scSetProperty(const char *name, ScValue *value);
bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
const char *scToString();
diff --git a/engines/wintermute/base/scriptables/script_ext_string.cpp b/engines/wintermute/base/scriptables/script_ext_string.cpp
index 8d87a92dc1..5f7da1c2dd 100644
--- a/engines/wintermute/base/scriptables/script_ext_string.cpp
+++ b/engines/wintermute/base/scriptables/script_ext_string.cpp
@@ -343,20 +343,20 @@ bool SXString::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack
//////////////////////////////////////////////////////////////////////////
-ScValue *SXString::scGetProperty(const char *name) {
+ScValue *SXString::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type (RO)
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("string");
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// Length (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Length") == 0) {
+ else if (name == "Length") {
if (_gameRef->_textEncoding == TEXT_UTF8) {
WideString wstr = StringUtil::utf8ToWide(_string);
_scValue->setInt(wstr.size());
@@ -369,7 +369,7 @@ ScValue *SXString::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Capacity
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Capacity") == 0) {
+ else if (name == "Capacity") {
_scValue->setInt(_capacity);
return _scValue;
} else {
diff --git a/engines/wintermute/base/scriptables/script_ext_string.h b/engines/wintermute/base/scriptables/script_ext_string.h
index 255b9c57eb..00bffab3a9 100644
--- a/engines/wintermute/base/scriptables/script_ext_string.h
+++ b/engines/wintermute/base/scriptables/script_ext_string.h
@@ -38,7 +38,7 @@ class SXString : public BaseScriptable {
public:
virtual int scCompare(BaseScriptable *Val);
DECLARE_PERSISTENT(SXString, BaseScriptable)
- ScValue *scGetProperty(const char *name);
+ ScValue *scGetProperty(const Common::String &name);
bool scSetProperty(const char *name, ScValue *value);
bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
void scSetString(const char *val);
diff --git a/engines/wintermute/base/sound/base_sound_buffer.cpp b/engines/wintermute/base/sound/base_sound_buffer.cpp
index 3fd6c4d5f2..250570f2b8 100644
--- a/engines/wintermute/base/sound/base_sound_buffer.cpp
+++ b/engines/wintermute/base/sound/base_sound_buffer.cpp
@@ -26,12 +26,10 @@
* Copyright (c) 2011 Jan Nedoma
*/
-#include "engines/wintermute/base/file/base_file.h"
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/base/sound/base_sound_manager.h"
#include "engines/wintermute/base/sound/base_sound_buffer.h"
#include "engines/wintermute/base/base_file_manager.h"
-#include "engines/wintermute/utils/utils.h"
#include "engines/wintermute/wintermute.h"
#include "audio/audiostream.h"
#include "audio/mixer.h"
diff --git a/engines/wintermute/base/sound/base_sound_manager.cpp b/engines/wintermute/base/sound/base_sound_manager.cpp
index f7788cd255..441793144d 100644
--- a/engines/wintermute/base/sound/base_sound_manager.cpp
+++ b/engines/wintermute/base/sound/base_sound_manager.cpp
@@ -32,6 +32,7 @@
#include "engines/wintermute/utils/string_util.h"
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
#include "engines/wintermute/base/sound/base_sound_buffer.h"
#include "engines/wintermute/wintermute.h"
#include "common/config-manager.h"
diff --git a/engines/wintermute/graphics/transparent_surface.cpp b/engines/wintermute/graphics/transparent_surface.cpp
index da01259b1b..9319899495 100644
--- a/engines/wintermute/graphics/transparent_surface.cpp
+++ b/engines/wintermute/graphics/transparent_surface.cpp
@@ -52,13 +52,13 @@ TransparentSurface::TransparentSurface(const Surface &surf, bool copyData) : Sur
void doBlitOpaque(byte *ino, byte* outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) {
byte *in, *out;
-
+
#ifdef SCUMM_LITTLE_ENDIAN
const int aIndex = 3;
#else
const int aIndex = 0;
#endif
-
+
for (uint32 i = 0; i < height; i++) {
out = outo;
in = ino;
@@ -121,7 +121,7 @@ void TransparentSurface::doBlitAlpha(byte *ino, byte* outo, uint32 width, uint32
int a = (pix >> aShift) & 0xff;
int outb, outg, outr, outa;
in += inStep;
-
+
switch (a) {
case 0: // Full transparency
out += 4;
diff --git a/engines/wintermute/persistent.h b/engines/wintermute/persistent.h
index 5bcf30787d..c862df5d6b 100644
--- a/engines/wintermute/persistent.h
+++ b/engines/wintermute/persistent.h
@@ -52,7 +52,7 @@ namespace Wintermute {
virtual bool persist(BasePersistenceManager* PersistMgr);\
void* operator new (size_t size);\
void operator delete(void* p);\
-
+
#define IMPLEMENT_PERSISTENT(class_name, persistent_class)\
const char class_name::_className[] = #class_name;\
@@ -80,7 +80,7 @@ namespace Wintermute {
SystemClassRegistry::getInstance()->unregisterInstance(#class_name, p);\
::operator delete(p);\
}\
-
+
#define TMEMBER(member_name) #member_name, &member_name
#define TMEMBER_INT(member_name) #member_name, (int*)&member_name
diff --git a/engines/wintermute/readme.txt b/engines/wintermute/readme.txt
deleted file mode 100644
index 57592dac2a..0000000000
--- a/engines/wintermute/readme.txt
+++ /dev/null
@@ -1,155 +0,0 @@
-Wintermute Engine - Copyright (c) 2011 Jan Nedoma
-ScummVM port by Einar Johan TrУИan SУИmУЅen (somaen)
-
-***************************
-*** General information ***
-***************************
-The Wintermute Engine is a game engine mainly aimed at creating adventure
-games, it supports both 3D, 2.5D, 2D and First-Person games, and has numerous
-games both free, open-source and commercial created with it. This port was
-created by somaen as part of Google Summer of Code 2012.
-
-****************
-*** Features ***
-****************
-This port of the Wintermute Engine (WME) is based on WME Lite, which lacks the following functionality
-originally found in WME: (from http://res.dead-code.org/doku.php/wmelite:start)
-
-The following features of WME 1.x are NOT supported by WME Lite:
-* 3D characters. WME Lite only supports 2D games.
-* Sprite frame mirroring.
-* Sprite rotations.
-* Sprite blending modes.
-* Video playback.
-* Plugins.
-* Calling external functions from DLL libraries from scripts.
-* Game Explorer support.
-* 'Directory' script object.
-
-This port does reimplement a few of these features, currently:
-* Sprite frame mirroring - WORKS.
-* Video playback - Theora PARTIALLY WORKING. (Slow, and doesn't support seeking)
-
-In addition, this port removes a few additional features that were never/rarely used:
-* 'File' script object - ScummVM doesn't have any easy way to write/read arbitrary files.
-* Debugger/Compiler - weren't properly accessible in WME Lite anyhow.
-* CD-numbering support in .dcp-files - was never used.
-* 'SaveDirectory'-property of 'Game' will not return anything usefull to the game-scripts (saving is handled through SaveFileMan)
-
-*******************************
-*** Additional limitations: ***
-*******************************
-* Only .OGG and RAW-.WAV sounds are supported at this point
-* TTF-fonts might behave a bit differently, owing to both the change to FreeType in WME Lite
- and the change in dpi in this port of WME.
-* The window-caption-setting in-game will be ignored, for the sake of concistency with ScummVM.
-* Most VKey-combinations might still be missing (as they already were in WME Lite)
-* Since we don't use FreeImage, some games might use odd files that weren't expected when the
- image-decoders in ScummVM were written. One example here is interlaced-PNGs.
-* UTF8-support is not ported, which means only games with western charsets will work for now.
-* Games that select language by moving .dcp-files around still need a bit more handling on detection/load
- adding support for those languages on a language-by-language basis.
-* Most games assume the availability of the Windows-fonts (particularly arial.ttf)
- at this point no fallback has been put in place for using FreeFonts as replacements,
- simply for lack of having them easily accessible to the engines at this point. So, at least
- arial.ttf should be put in either the game-folder or made available through the extras-folder
- for now, otherwise kGUIBigFont will be used as a replacement.
-
-
-*********************************
-*** Advanced engine-features: ***
-*********************************
-At this point the engine implements the following "advanced engine features":
-* RTL ("Return to Launcher") support
-* Global options dialog support
-* Listing savestates via command line or Launcher
-* Loading savestates via command line or Launcher
-* Deleting savestates via the Launcher and GMM
-* Savestate metadata support
-* Loading/Saving during run time
-
-and NOT the following:
-* Enhanced debug/error messages
-
-*****************
-*** Detection ***
-*****************
-Since Wintermute has authoring tools available, there will at any point in
-time be atleast a few games that are works-in-progress, and as the authors
-of these games might want to test their games in ScummVM, the engine has
-to be able to detect arbitrary Wintermute-games, to this end the detector
-code in this engine will check any folder containing "data.dcp", and try to
-read "startup.settings" and "default.game" (or optionally any other .game-file
-defined in startup.settings), the Name/Caption fields in the .game-file will
-be used as gameid/title (prefixing the gameid with "wmefan-" to avoid confusion
-with any other WME game that might happen to have taken that id.
-
-All COMPLETED games should have their md5s and gameid's properly added, IFF
-they don't require 3D.
-
-3D games may also be added, for the purpose of giving the user feedback
-as to why their game won't run, but at this point, any such MD5 should
-be added as a comment only, to avoid confusion, as no mechanism for giving
-the user feedback about 3D-games not being supported is currently added.
-
-*************************************
-*** Games targeted by the engine: ***
-*************************************
-This engine potentially targets a very large amount of games:
-http://res.dead-code.org/doku.php/games:start
-
-Since the feature-set of WME Lite differs from that of the full Wintermute Engine,
-games will need to be targeted on a case-by-case, feature-by-feature basis, this is
-a list of the games that are currently known to work (although perhaps with minor
-issues) through to completion:
-
-* Dirty Split (dirtysplit)
-* the white chamber (twc)
-* Chivalry is NOT dead (chivalry)
-* Rosemary (rosemary)
-* The Box (thebox)
-* J.U.L.I.A. (Demo) (julia)
-* Pigeons in the park (pigeons)
-
-Untested, but starts:
-* East Side Story (Demo) (eastside)
-* Actual Destination (actualdest)
-* Ghost in the sheet (ghostsheet)
-
-********************************
-*** Games with known issues: ***
-********************************
-Certain games will work mostly fine with this engine, but can still
-be impossible to complete for various reasons, this is a list of games
-that technically qualify (as in they do not require the 3D-parts of the engine)
-but have issues that make them problematic or not completable:
-
-Won't start:
-* Five Lethal Demons (5ld) - Requires support for interlaced PNGs
-* Five Magical Amulets (5ma) - Requires support for interlaced PNGs
-* Kulivoeko - Requires support for interlaced PNGs
-* Reversion (reversion) - Requires support for Non-V1.1 JPEGs and interlaced PNGs
-* Mirage (mirage) - Tries to seek in a vorbis-stream inside a ZipStream
-* Hamlet or the last game without MMORPS features, shaders and product placement (hamlet)
- - Requires support for interlaced PNGs
-
-Gameplay broken:
-* J.U.L.I.A. (Full game) (julia) - Requires sprite-rotation for a puzzle.
-
-Non-critical:
-* Ghost in the sheet (ghostsheet) - uses Non-V1.1-JPEGs
-* East Side Story (eastside) - wants "framd.ttf"
-
-*****************************
-*** General known issues: ***
-*****************************
-
-Mostly a TODO-section, to not forget fixing outstanding general issues:
-* Save/Load-screens are not shown during save/load
- this is probably a result of reducing the amount of redrawing done
- during save/load, and I'm not sure it should be put back, if that means
- making saves slower again.
-* Font-sizes are wrong enough to allow Dirty Split to draw text that is hidden in
- the original game (most visible on the coin-interface)
-* Alpha-masks for Theora-videos are broken on big-endian platforms
-
diff --git a/engines/wintermute/system/sys_class_registry.cpp b/engines/wintermute/system/sys_class_registry.cpp
index 5e3b968c5c..7c1911c2bf 100644
--- a/engines/wintermute/system/sys_class_registry.cpp
+++ b/engines/wintermute/system/sys_class_registry.cpp
@@ -29,6 +29,7 @@
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/platform_osystem.h"
#include "engines/wintermute/base/base_engine.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
#include "engines/wintermute/system/sys_instance.h"
#include "engines/wintermute/system/sys_class_registry.h"
#include "engines/wintermute/system/sys_class.h"
diff --git a/engines/wintermute/ui/ui_button.cpp b/engines/wintermute/ui/ui_button.cpp
index f2ac5b2fdd..7967d566f9 100644
--- a/engines/wintermute/ui/ui_button.cpp
+++ b/engines/wintermute/ui/ui_button.cpp
@@ -37,6 +37,7 @@
#include "engines/wintermute/base/base_string_table.h"
#include "engines/wintermute/base/base_sprite.h"
#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
#include "engines/wintermute/base/scriptables/script_value.h"
#include "engines/wintermute/base/scriptables/script.h"
#include "engines/wintermute/base/scriptables/script_stack.h"
@@ -1081,13 +1082,13 @@ bool UIButton::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack
//////////////////////////////////////////////////////////////////////////
-ScValue *UIButton::scGetProperty(const char *name) {
+ScValue *UIButton::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("button");
return _scValue;
}
@@ -1095,7 +1096,7 @@ ScValue *UIButton::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// TextAlign
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "TextAlign") == 0) {
+ else if (name == "TextAlign") {
_scValue->setInt(_align);
return _scValue;
}
@@ -1103,21 +1104,21 @@ ScValue *UIButton::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Focusable
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Focusable") == 0) {
+ else if (name == "Focusable") {
_scValue->setBool(_canFocus);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// Pressed
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Pressed") == 0) {
+ else if (name == "Pressed") {
_scValue->setBool(_stayPressed);
return _scValue;
}
//////////////////////////////////////////////////////////////////////////
// PixelPerfect
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "PixelPerfect") == 0) {
+ else if (name == "PixelPerfect") {
_scValue->setBool(_pixelPerfect);
return _scValue;
} else {
diff --git a/engines/wintermute/ui/ui_button.h b/engines/wintermute/ui/ui_button.h
index 9342f766cc..93333a2534 100644
--- a/engines/wintermute/ui/ui_button.h
+++ b/engines/wintermute/ui/ui_button.h
@@ -69,7 +69,7 @@ public:
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent);
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
diff --git a/engines/wintermute/ui/ui_edit.cpp b/engines/wintermute/ui/ui_edit.cpp
index 94d11255ce..a3283d5a01 100644
--- a/engines/wintermute/ui/ui_edit.cpp
+++ b/engines/wintermute/ui/ui_edit.cpp
@@ -40,6 +40,7 @@
#include "engines/wintermute/base/base_sprite.h"
#include "engines/wintermute/base/base_string_table.h"
#include "engines/wintermute/base/base_game.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/base/scriptables/script.h"
@@ -397,13 +398,13 @@ bool UIEdit::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack,
//////////////////////////////////////////////////////////////////////////
-ScValue *UIEdit::scGetProperty(const char *name) {
+ScValue *UIEdit::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("editor");
return _scValue;
}
@@ -411,7 +412,7 @@ ScValue *UIEdit::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// SelStart
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SelStart") == 0) {
+ else if (name == "SelStart") {
_scValue->setInt(_selStart);
return _scValue;
}
@@ -419,7 +420,7 @@ ScValue *UIEdit::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// SelEnd
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SelEnd") == 0) {
+ else if (name == "SelEnd") {
_scValue->setInt(_selEnd);
return _scValue;
}
@@ -427,7 +428,7 @@ ScValue *UIEdit::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// CursorBlinkRate
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "CursorBlinkRate") == 0) {
+ else if (name == "CursorBlinkRate") {
_scValue->setInt(_cursorBlinkRate);
return _scValue;
}
@@ -435,7 +436,7 @@ ScValue *UIEdit::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// CursorChar
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "CursorChar") == 0) {
+ else if (name == "CursorChar") {
_scValue->setString(_cursorChar);
return _scValue;
}
@@ -443,7 +444,7 @@ ScValue *UIEdit::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// FrameWidth
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "FrameWidth") == 0) {
+ else if (name == "FrameWidth") {
_scValue->setInt(_frameWidth);
return _scValue;
}
@@ -451,7 +452,7 @@ ScValue *UIEdit::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// MaxLength
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "MaxLength") == 0) {
+ else if (name == "MaxLength") {
_scValue->setInt(_maxLength);
return _scValue;
}
@@ -459,7 +460,7 @@ ScValue *UIEdit::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Text
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Text") == 0) {
+ else if (name == "Text") {
if (_gameRef->_textEncoding == TEXT_UTF8) {
WideString wstr = StringUtil::ansiToWide(_text);
_scValue->setString(StringUtil::wideToUtf8(wstr).c_str());
diff --git a/engines/wintermute/ui/ui_edit.h b/engines/wintermute/ui/ui_edit.h
index 610629afb3..5bb31422b6 100644
--- a/engines/wintermute/ui/ui_edit.h
+++ b/engines/wintermute/ui/ui_edit.h
@@ -61,7 +61,7 @@ public:
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent);
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
diff --git a/engines/wintermute/ui/ui_entity.cpp b/engines/wintermute/ui/ui_entity.cpp
index c49cb5a240..1cb4e0926b 100644
--- a/engines/wintermute/ui/ui_entity.cpp
+++ b/engines/wintermute/ui/ui_entity.cpp
@@ -305,13 +305,13 @@ bool UIEntity::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack
//////////////////////////////////////////////////////////////////////////
-ScValue *UIEntity::scGetProperty(const char *name) {
+ScValue *UIEntity::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("entity container");
return _scValue;
}
@@ -319,7 +319,7 @@ ScValue *UIEntity::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Freezable
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Freezable") == 0) {
+ else if (name == "Freezable") {
if (_entity) {
_scValue->setBool(_entity->_freezable);
} else {
diff --git a/engines/wintermute/ui/ui_entity.h b/engines/wintermute/ui/ui_entity.h
index 3bf8068fd5..b5f4450071 100644
--- a/engines/wintermute/ui/ui_entity.h
+++ b/engines/wintermute/ui/ui_entity.h
@@ -48,7 +48,7 @@ public:
bool setEntity(const char *filename);
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
diff --git a/engines/wintermute/ui/ui_object.cpp b/engines/wintermute/ui/ui_object.cpp
index 85e381c55b..8e5bae993c 100644
--- a/engines/wintermute/ui/ui_object.cpp
+++ b/engines/wintermute/ui/ui_object.cpp
@@ -32,6 +32,7 @@
#include "engines/wintermute/ui/ui_tiled_image.h"
#include "engines/wintermute/ui/ui_window.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/base/font/base_font_storage.h"
@@ -359,13 +360,13 @@ bool UIObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack
//////////////////////////////////////////////////////////////////////////
-ScValue *UIObject::scGetProperty(const char *name) {
+ScValue *UIObject::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("ui_object");
return _scValue;
}
@@ -373,7 +374,7 @@ ScValue *UIObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Name
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Name") == 0) {
+ else if (name == "Name") {
_scValue->setString(getName());
return _scValue;
}
@@ -381,7 +382,7 @@ ScValue *UIObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Parent (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Parent") == 0) {
+ else if (name == "Parent") {
_scValue->setNative(_parent, true);
return _scValue;
}
@@ -389,7 +390,7 @@ ScValue *UIObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// ParentNotify
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ParentNotify") == 0) {
+ else if (name == "ParentNotify") {
_scValue->setBool(_parentNotify);
return _scValue;
}
@@ -397,7 +398,7 @@ ScValue *UIObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Width
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Width") == 0) {
+ else if (name == "Width") {
_scValue->setInt(_width);
return _scValue;
}
@@ -405,7 +406,7 @@ ScValue *UIObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Height
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Height") == 0) {
+ else if (name == "Height") {
_scValue->setInt(_height);
return _scValue;
}
@@ -413,7 +414,7 @@ ScValue *UIObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Visible
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Visible") == 0) {
+ else if (name == "Visible") {
_scValue->setBool(_visible);
return _scValue;
}
@@ -421,7 +422,7 @@ ScValue *UIObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Disabled
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Disabled") == 0) {
+ else if (name == "Disabled") {
_scValue->setBool(_disable);
return _scValue;
}
@@ -429,7 +430,7 @@ ScValue *UIObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Text
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Text") == 0) {
+ else if (name == "Text") {
_scValue->setString(_text);
return _scValue;
}
@@ -437,13 +438,13 @@ ScValue *UIObject::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// NextSibling (RO) / PrevSibling (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "NextSibling") == 0 || strcmp(name, "PrevSibling") == 0) {
+ else if (name == "NextSibling" || name == "PrevSibling") {
_scValue->setNULL();
if (_parent && _parent->_type == UI_WINDOW) {
UIWindow *win = (UIWindow *)_parent;
for (uint32 i = 0; i < win->_widgets.size(); i++) {
if (win->_widgets[i] == this) {
- if (strcmp(name, "NextSibling") == 0) {
+ if (name == "NextSibling") {
if (i < win->_widgets.size() - 1) {
_scValue->setNative(win->_widgets[i + 1], true);
}
diff --git a/engines/wintermute/ui/ui_object.h b/engines/wintermute/ui/ui_object.h
index 81c025d33b..ec2ea33de1 100644
--- a/engines/wintermute/ui/ui_object.h
+++ b/engines/wintermute/ui/ui_object.h
@@ -74,7 +74,7 @@ public:
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent);
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
diff --git a/engines/wintermute/ui/ui_text.cpp b/engines/wintermute/ui/ui_text.cpp
index 1844b640d0..2c10f176c7 100644
--- a/engines/wintermute/ui/ui_text.cpp
+++ b/engines/wintermute/ui/ui_text.cpp
@@ -431,13 +431,13 @@ bool UIText::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack,
//////////////////////////////////////////////////////////////////////////
-ScValue *UIText::scGetProperty(const char *name) {
+ScValue *UIText::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("static");
return _scValue;
}
@@ -445,7 +445,7 @@ ScValue *UIText::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// TextAlign
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "TextAlign") == 0) {
+ else if (name == "TextAlign") {
_scValue->setInt(_textAlign);
return _scValue;
}
@@ -453,7 +453,7 @@ ScValue *UIText::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// VerticalAlign
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "VerticalAlign") == 0) {
+ else if (name == "VerticalAlign") {
_scValue->setInt(_verticalAlign);
return _scValue;
} else {
diff --git a/engines/wintermute/ui/ui_text.h b/engines/wintermute/ui/ui_text.h
index d2f116b44b..da4d113500 100644
--- a/engines/wintermute/ui/ui_text.h
+++ b/engines/wintermute/ui/ui_text.h
@@ -49,7 +49,7 @@ public:
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent);
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
diff --git a/engines/wintermute/ui/ui_tiled_image.cpp b/engines/wintermute/ui/ui_tiled_image.cpp
index cec23cf67e..2b337330c7 100644
--- a/engines/wintermute/ui/ui_tiled_image.cpp
+++ b/engines/wintermute/ui/ui_tiled_image.cpp
@@ -33,6 +33,7 @@
#include "engines/wintermute/base/base_game.h"
#include "engines/wintermute/base/base_sub_frame.h"
#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
#include "engines/wintermute/platform_osystem.h"
namespace Wintermute {
@@ -333,8 +334,8 @@ bool UITiledImage::saveAsText(BaseDynamicBuffer *buffer, int indent) {
buffer->putTextIndent(indent, "TILED_IMAGE\n");
buffer->putTextIndent(indent, "{\n");
- if (_image && _image->_surfaceFilename) {
- buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->_surfaceFilename);
+ if (_image && _image->getSurfaceFilename()) {
+ buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->getSurfaceFilename());
}
int h1, h2, h3;
diff --git a/engines/wintermute/ui/ui_window.cpp b/engines/wintermute/ui/ui_window.cpp
index 65af62141d..9606486efb 100644
--- a/engines/wintermute/ui/ui_window.cpp
+++ b/engines/wintermute/ui/ui_window.cpp
@@ -41,6 +41,7 @@
#include "engines/wintermute/base/font/base_font_storage.h"
#include "engines/wintermute/base/font/base_font.h"
#include "engines/wintermute/base/base_string_table.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
#include "engines/wintermute/base/scriptables/script.h"
#include "engines/wintermute/base/scriptables/script_stack.h"
#include "engines/wintermute/base/base_sprite.h"
@@ -1013,13 +1014,13 @@ bool UIWindow::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack
//////////////////////////////////////////////////////////////////////////
-ScValue *UIWindow::scGetProperty(const char *name) {
+ScValue *UIWindow::scGetProperty(const Common::String &name) {
_scValue->setNULL();
//////////////////////////////////////////////////////////////////////////
// Type
//////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
+ if (name == "Type") {
_scValue->setString("window");
return _scValue;
}
@@ -1027,7 +1028,7 @@ ScValue *UIWindow::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// NumWidgets / NumControls (RO)
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "NumWidgets") == 0 || strcmp(name, "NumControls") == 0) {
+ else if (name == "NumWidgets" || name == "NumControls") {
_scValue->setInt(_widgets.size());
return _scValue;
}
@@ -1035,7 +1036,7 @@ ScValue *UIWindow::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Exclusive
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Exclusive") == 0) {
+ else if (name == "Exclusive") {
_scValue->setBool(_mode == WINDOW_EXCLUSIVE);
return _scValue;
}
@@ -1043,7 +1044,7 @@ ScValue *UIWindow::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// SystemExclusive
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SystemExclusive") == 0) {
+ else if (name == "SystemExclusive") {
_scValue->setBool(_mode == WINDOW_SYSTEM_EXCLUSIVE);
return _scValue;
}
@@ -1051,7 +1052,7 @@ ScValue *UIWindow::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Menu
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Menu") == 0) {
+ else if (name == "Menu") {
_scValue->setBool(_isMenu);
return _scValue;
}
@@ -1059,7 +1060,7 @@ ScValue *UIWindow::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// InGame
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "InGame") == 0) {
+ else if (name == "InGame") {
_scValue->setBool(_inGame);
return _scValue;
}
@@ -1067,7 +1068,7 @@ ScValue *UIWindow::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// PauseMusic
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "PauseMusic") == 0) {
+ else if (name == "PauseMusic") {
_scValue->setBool(_pauseMusic);
return _scValue;
}
@@ -1075,7 +1076,7 @@ ScValue *UIWindow::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// ClipContents
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ClipContents") == 0) {
+ else if (name == "ClipContents") {
_scValue->setBool(_clipContents);
return _scValue;
}
@@ -1083,7 +1084,7 @@ ScValue *UIWindow::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// Transparent
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Transparent") == 0) {
+ else if (name == "Transparent") {
_scValue->setBool(_transparent);
return _scValue;
}
@@ -1091,7 +1092,7 @@ ScValue *UIWindow::scGetProperty(const char *name) {
//////////////////////////////////////////////////////////////////////////
// FadeColor
//////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "FadeColor") == 0) {
+ else if (name == "FadeColor") {
_scValue->setInt((int)_fadeColor);
return _scValue;
} else {
diff --git a/engines/wintermute/ui/ui_window.h b/engines/wintermute/ui/ui_window.h
index cbd417a7d9..ae035c65c7 100644
--- a/engines/wintermute/ui/ui_window.h
+++ b/engines/wintermute/ui/ui_window.h
@@ -83,7 +83,7 @@ public:
virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent);
// scripting interface
- virtual ScValue *scGetProperty(const char *name);
+ virtual ScValue *scGetProperty(const Common::String &name);
virtual bool scSetProperty(const char *name, ScValue *value);
virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
virtual const char *scToString();
diff --git a/engines/wintermute/utils/string_util.cpp b/engines/wintermute/utils/string_util.cpp
index 2c3be8c2f5..7b3b0e1297 100644
--- a/engines/wintermute/utils/string_util.cpp
+++ b/engines/wintermute/utils/string_util.cpp
@@ -148,11 +148,11 @@ Utf8String StringUtil::wideToUtf8(const WideString &WideStr) {
// Currently this only does Ansi->ISO 8859, and only for carets.
char simpleAnsiToWide(const AnsiString &str, uint32 &offset) {
- char c = str[offset];
+ byte c = str[offset];
- if (c == 92) {
+ if (c == 146) {
offset++;
- return '\'';
+ return 39; // Replace right-quote with apostrophe
} else {
offset++;
return c;
@@ -162,11 +162,11 @@ char simpleAnsiToWide(const AnsiString &str, uint32 &offset) {
//////////////////////////////////////////////////////////////////////////
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 = "";
+ Common::String converted = "";
uint32 index = 0;
while (index != str.size()) {
converted += simpleAnsiToWide(str, index);
- }*/
+ }
// using default os locale!
/* setlocale(LC_CTYPE, "");
@@ -176,7 +176,7 @@ WideString StringUtil::ansiToWide(const AnsiString &str) {
WideString ResultString(wstr);
delete[] wstr;
return ResultString;*/
- return WideString(str);
+ return WideString(converted);
}
//////////////////////////////////////////////////////////////////////////
diff --git a/engines/wintermute/video/video_theora_player.cpp b/engines/wintermute/video/video_theora_player.cpp
index 0d23a04af4..d14c807e11 100644
--- a/engines/wintermute/video/video_theora_player.cpp
+++ b/engines/wintermute/video/video_theora_player.cpp
@@ -32,8 +32,8 @@
#include "engines/wintermute/base/base_file_manager.h"
#include "engines/wintermute/base/gfx/osystem/base_surface_osystem.h"
#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/utils/utils.h"
#include "engines/wintermute/platform_osystem.h"
#include "video/theora_decoder.h"
#include "engines/wintermute/wintermute.h"
@@ -151,7 +151,32 @@ bool VideoTheoraPlayer::initialize(const Common::String &filename, const Common:
//////////////////////////////////////////////////////////////////////////
bool VideoTheoraPlayer::resetStream() {
- warning("VidTheoraPlayer::resetStream - stubbed");
+ warning("VidTheoraPlayer::resetStream - hacked");
+ // HACK: Just reopen the same file again.
+ if (_theoraDecoder) {
+ _theoraDecoder->close();
+ }
+ delete _theoraDecoder;
+ _theoraDecoder = NULL;
+
+ _file = BaseFileManager::getEngineInstance()->openFile(_filename, true, false);
+ 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;
+ }
+
+ return play(_playbackType, _posX, _posY, false, false, _looping, 0, _playZoom);
+ // End of hack.
#if 0 // Stubbed for now, as theora isn't seekable
if (_sound) {
_sound->Stop();
@@ -265,8 +290,10 @@ bool VideoTheoraPlayer::update() {
if (_theoraDecoder) {
if (_theoraDecoder->endOfVideo() && _looping) {
- warning("Should loop movie %s", _filename.c_str());
+ warning("Should loop movie %s, hacked for now", _filename.c_str());
_theoraDecoder->rewind();
+ //HACK: Just reinitialize the same video again:
+ return resetStream();
} else if (_theoraDecoder->endOfVideo() && !_looping) {
debugC(kWintermuteDebugLog, "Finished movie %s", _filename.c_str());
_state = THEORA_STATE_FINISHED;
diff --git a/engines/wintermute/wintermute.cpp b/engines/wintermute/wintermute.cpp
index 9ada07293f..c9726e150a 100644
--- a/engines/wintermute/wintermute.cpp
+++ b/engines/wintermute/wintermute.cpp
@@ -39,6 +39,7 @@
#include "engines/wintermute/base/sound/base_sound_manager.h"
#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
#include "engines/wintermute/base/scriptables/script_engine.h"
namespace Wintermute {
diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp
index 30ef9eeeeb..f426dd8c41 100644
--- a/graphics/VectorRenderer.cpp
+++ b/graphics/VectorRenderer.cpp
@@ -80,7 +80,7 @@ void VectorRenderer::stepGetPositions(const DrawStep &step, const Common::Rect &
case Graphics::DrawStep::kVectorAlignManual:
if (step.x >= 0)
in_x = area.left + step.x + step.padding.left;
- else
+ else
in_x = area.left + area.width() + step.x + step.padding.left; // value relative to the opposite corner.
break;
diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h
index e98f4aa761..0467cac946 100644
--- a/graphics/VectorRenderer.h
+++ b/graphics/VectorRenderer.h
@@ -55,7 +55,7 @@ struct DrawStep {
bool autoWidth, autoHeight;
int16 x, y, w, h; /**< width, height and position, if not measured automatically.
negative values mean counting from the opposite direction */
-
+
Common::Rect padding;
enum VectorAlignment {
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index 1ed5a3308a..6a3ee306a5 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -369,12 +369,12 @@ gradientFill(PixelType *ptr, int width, int x, int y) {
int grad = (((y - _gradIndexes[curGrad]) % stripSize) << 2) / stripSize;
// Dithering:
- // +--+ +--+ +--+ +--+
- // | | | | | *| | *|
- // | | | *| |* | |**|
- // +--+ +--+ +--+ +--+
+ // +--+ +--+ +--+ +--+
+ // | | | | | *| | *|
+ // | | | *| |* | |**|
+ // +--+ +--+ +--+ +--+
// 0 1 2 3
- if (grad == 0 ||
+ if (grad == 0 ||
_gradCache[curGrad] == _gradCache[curGrad + 1] || // no color change
stripSize < 2) { // the stip is small
colorFill<PixelType>(ptr, ptr + width, _gradCache[curGrad]);
@@ -873,7 +873,7 @@ drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) {
case kTriangleDown:
drawTriangleVertAlg(x, y, newW, newH, (orient == kTriangleDown), color, Base::_fillMode);
break;
-
+
case kTriangleLeft:
case kTriangleRight:
case kTriangleAuto:
@@ -1206,14 +1206,14 @@ drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color
pitch = -pitch;
y1 += h;
}
-
+
PixelType *ptr_right = (PixelType *)_activeSurface->getBasePtr(x1, y1);
PixelType *floor = ptr_right - 1;
PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + w, y1);
int x2 = x1 + w / 2;
int y2 = y1 + h;
-
+
#if FIXED_POINT
int dx = (x2 - x1) << 8;
int dy = (y2 - y1) << 8;
@@ -1227,7 +1227,7 @@ drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color
#endif
while (floor++ != ptr_left)
blendPixelPtr(floor, color, 50);
-
+
#if FIXED_POINT
int gradient = (dy << 8) / dx;
int intery = (y1 << 8) + gradient;
@@ -1250,7 +1250,7 @@ drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color
ptr_right += pitch;
intery += gradient;
-
+
switch (fill_m) {
case kFillDisabled:
*ptr_left = *ptr_right = color;
@@ -1262,16 +1262,16 @@ drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color
blendPixelPtr(ptr_left, color, rfpart(intery));
break;
case kFillGradient:
- colorFill<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h));
+ colorFill<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h));
blendPixelPtr(ptr_right, color, rfpart(intery));
blendPixelPtr(ptr_left, color, rfpart(intery));
break;
}
}
-
+
return;
}
-
+
#if FIXED_POINT
if (abs(dx) < abs(dy)) {
#else
@@ -1280,7 +1280,7 @@ drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color
ptr_left--;
while (floor++ != ptr_left)
blendPixelPtr(floor, color, 50);
-
+
#if FIXED_POINT
int gradient = (dx << 8) / (dy + 0x100);
int interx = (x1 << 8) + gradient;
@@ -1303,7 +1303,7 @@ drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color
ptr_right += pitch;
interx += gradient;
-
+
switch (fill_m) {
case kFillDisabled:
*ptr_left = *ptr_right = color;
@@ -1315,18 +1315,18 @@ drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color
blendPixelPtr(ptr_left, color, rfpart(interx));
break;
case kFillGradient:
- colorFill<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h));
+ colorFill<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h));
blendPixelPtr(ptr_right, color, rfpart(interx));
blendPixelPtr(ptr_left, color, rfpart(interx));
break;
}
}
-
+
return;
}
-
+
ptr_left--;
-
+
while (floor++ != ptr_left)
blendPixelPtr(floor, color, 50);
@@ -1341,12 +1341,12 @@ drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color
for (int y = y1 + 1; y < y2; y++) {
ptr_right++;
ptr_left--;
-
+
ptr_left += pitch;
ptr_right += pitch;
interx += gradient;
-
+
switch (fill_m) {
case kFillDisabled:
*ptr_left = *ptr_right = color;
@@ -1358,13 +1358,13 @@ drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color
blendPixelPtr(ptr_left, color, rfpart(interx));
break;
case kFillGradient:
- colorFill<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h));
+ colorFill<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h));
blendPixelPtr(ptr_right, color, rfpart(interx));
blendPixelPtr(ptr_left, color, rfpart(interx));
break;
}
}
-
+
}
/** VERTICAL TRIANGLE DRAWING - FAST VERSION FOR SQUARED TRIANGLES */
@@ -1372,12 +1372,12 @@ template<typename PixelType>
void VectorRendererSpec<PixelType>::
drawTriangleFast(int x1, int y1, int size, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) {
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
-
+
if (!inverted) {
pitch = -pitch;
y1 += size;
}
-
+
int gradient_h = 0;
PixelType *ptr_right = (PixelType *)_activeSurface->getBasePtr(x1, y1);
PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + size, y1);
@@ -1388,9 +1388,9 @@ drawTriangleFast(int x1, int y1, int size, bool inverted, PixelType color, Vecto
int signX = x1 < x2 ? 1 : -1;
int signY = y1 < y2 ? 1 : -1;
int error = deltaX - deltaY;
-
+
colorFill<PixelType>(ptr_right, ptr_left, color);
-
+
while (1) {
switch (fill_m) {
case kFillDisabled:
@@ -1401,22 +1401,22 @@ drawTriangleFast(int x1, int y1, int size, bool inverted, PixelType color, Vecto
colorFill<PixelType>(ptr_right, ptr_left, color);
break;
case kFillGradient:
- colorFill<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, size));
+ colorFill<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, size));
break;
}
-
+
if (x1 == x2 && y1 == y2)
break;
-
+
int error2 = error * 2;
-
+
if (error2 > -deltaY) {
error -= deltaY;
x1 += signX;
ptr_right += signX;
ptr_left += -signX;
}
-
+
if (error2 < deltaX) {
error += deltaX;
y1 += signY;
diff --git a/graphics/conversion.cpp b/graphics/conversion.cpp
index 713a06ea74..2da8b6f0ce 100644
--- a/graphics/conversion.cpp
+++ b/graphics/conversion.cpp
@@ -22,123 +22,143 @@
#include "graphics/conversion.h"
#include "graphics/pixelformat.h"
+#include "common/endian.h"
+
namespace Graphics {
// TODO: YUV to RGB conversion function
+namespace {
+
+template<typename SrcColor, typename DstColor, bool backward>
+inline void crossBlitLogic(byte *dst, const byte *src, const uint w, const uint h,
+ const PixelFormat &srcFmt, const PixelFormat &dstFmt,
+ const uint srcDelta, const uint dstDelta) {
+ for (uint y = 0; y < h; ++y) {
+ for (uint x = 0; x < w; ++x) {
+ const uint32 color = *(const SrcColor *)src;
+ byte a, r, g, b;
+ srcFmt.colorToARGB(color, a, r, g, b);
+ *(DstColor *)dst = dstFmt.ARGBToColor(a, r, g, b);
+
+ if (backward) {
+ src -= sizeof(SrcColor);
+ dst -= sizeof(DstColor);
+ } else {
+ src += sizeof(SrcColor);
+ dst += sizeof(DstColor);
+ }
+ }
+
+ if (backward) {
+ src -= srcDelta;
+ dst -= dstDelta;
+ } else {
+ src += srcDelta;
+ dst += dstDelta;
+ }
+ }
+}
+
+template<typename DstColor, bool backward>
+inline void crossBlitLogic3BppSource(byte *dst, const byte *src, const uint w, const uint h,
+ const PixelFormat &srcFmt, const PixelFormat &dstFmt,
+ const uint srcDelta, const uint dstDelta) {
+ uint32 color;
+ byte r, g, b, a;
+ uint8 *col = (uint8 *)&color;
+#ifdef SCUMM_BIG_ENDIAN
+ col++;
+#endif
+ for (uint y = 0; y < h; ++y) {
+ for (uint x = 0; x < w; ++x) {
+ memcpy(col, src, 3);
+ srcFmt.colorToARGB(color, a, r, g, b);
+ *(DstColor *)dst = dstFmt.ARGBToColor(a, r, g, b);
+
+ if (backward) {
+ src -= 3;
+ dst -= sizeof(DstColor);
+ } else {
+ src += 3;
+ dst += sizeof(DstColor);
+ }
+ }
+
+ if (backward) {
+ src -= srcDelta;
+ dst -= dstDelta;
+ } else {
+ src += srcDelta;
+ dst += dstDelta;
+ }
+ }
+}
+
+} // End of anonymous namespace
+
// Function to blit a rect from one color format to another
-bool crossBlit(byte *dst, const byte *src, int dstpitch, int srcpitch,
- int w, int h, const Graphics::PixelFormat &dstFmt, const Graphics::PixelFormat &srcFmt) {
+bool crossBlit(byte *dst, const byte *src,
+ const uint dstPitch, const uint srcPitch,
+ const uint w, const uint h,
+ const Graphics::PixelFormat &dstFmt, const Graphics::PixelFormat &srcFmt) {
// Error out if conversion is impossible
if ((srcFmt.bytesPerPixel == 1) || (dstFmt.bytesPerPixel == 1)
- || (!srcFmt.bytesPerPixel) || (!dstFmt.bytesPerPixel)
- || (srcFmt.bytesPerPixel > dstFmt.bytesPerPixel))
+ || (dstFmt.bytesPerPixel == 3)
+ || (!srcFmt.bytesPerPixel) || (!dstFmt.bytesPerPixel))
return false;
// Don't perform unnecessary conversion
if (srcFmt == dstFmt) {
- if (dst == src)
- return true;
- if (dstpitch == srcpitch && ((w * dstFmt.bytesPerPixel) == dstpitch)) {
- memcpy(dst,src,dstpitch * h);
- return true;
- } else {
- for (int i = 0; i < h; i++) {
- memcpy(dst,src,w * dstFmt.bytesPerPixel);
- dst += dstpitch;
- src += srcpitch;
+ if (dst != src) {
+ if (dstPitch == srcPitch && ((w * dstFmt.bytesPerPixel) == dstPitch)) {
+ memcpy(dst, src, dstPitch * h);
+ } else {
+ for (uint i = 0; i < h; ++i) {
+ memcpy(dst, src, w * dstFmt.bytesPerPixel);
+ dst += dstPitch;
+ src += srcPitch;
+ }
}
- return true;
}
+
+ return true;
}
// Faster, but larger, to provide optimized handling for each case.
- int srcDelta, dstDelta;
- srcDelta = (srcpitch - w * srcFmt.bytesPerPixel);
- dstDelta = (dstpitch - w * dstFmt.bytesPerPixel);
+ const uint srcDelta = (srcPitch - w * srcFmt.bytesPerPixel);
+ const uint dstDelta = (dstPitch - w * dstFmt.bytesPerPixel);
// TODO: optimized cases for dstDelta of 0
- uint8 r, g, b, a;
if (dstFmt.bytesPerPixel == 2) {
- uint16 color;
- for (int y = 0; y < h; y++) {
- for (int x = 0; x < w; x++, src += 2, dst += 2) {
- color = *(const uint16 *)src;
- srcFmt.colorToARGB(color, a, r, g, b);
- color = dstFmt.ARGBToColor(a, r, g, b);
- *(uint16 *)dst = color;
- }
- src += srcDelta;
- dst += dstDelta;
- }
- } else if (dstFmt.bytesPerPixel == 3) {
- uint32 color;
- uint8 *col = (uint8 *) &color;
-#ifdef SCUMM_BIG_ENDIAN
- col++;
-#endif
if (srcFmt.bytesPerPixel == 2) {
- for (int y = 0; y < h; y++) {
- for (int x = 0; x < w; x++, src += 2, dst += 3) {
- color = *(const uint16 *)src;
- srcFmt.colorToARGB(color, a, r, g, b);
- color = dstFmt.ARGBToColor(a, r, g, b);
- memcpy(dst, col, 3);
- }
- src += srcDelta;
- dst += dstDelta;
- }
+ crossBlitLogic<uint16, uint16, false>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
+ } else if (srcFmt.bytesPerPixel == 3) {
+ crossBlitLogic3BppSource<uint16, false>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
} else {
- for (int y = 0; y < h; y++) {
- for (int x = 0; x < w; x++, src += 3, dst += 3) {
- memcpy(col, src, 3);
- srcFmt.colorToARGB(color, a, r, g, b);
- color = dstFmt.ARGBToColor(a, r, g, b);
- memcpy(dst, col, 3);
- }
- src += srcDelta;
- dst += dstDelta;
- }
+ crossBlitLogic<uint32, uint16, false>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
}
} else if (dstFmt.bytesPerPixel == 4) {
- uint32 color;
if (srcFmt.bytesPerPixel == 2) {
- for (int y = 0; y < h; y++) {
- for (int x = 0; x < w; x++, src += 2, dst += 4) {
- color = *(const uint16 *)src;
- srcFmt.colorToARGB(color, a, r, g, b);
- color = dstFmt.ARGBToColor(a, r, g, b);
- *(uint32 *)dst = color;
- }
- src += srcDelta;
- dst += dstDelta;
- }
+ // We need to blit the surface from bottom right to top left here.
+ // This is neeeded, because when we convert to the same memory
+ // buffer copying the surface from top left to bottom right would
+ // overwrite the source, since we have more bits per destination
+ // color than per source color.
+ dst += h * dstPitch - dstDelta - dstFmt.bytesPerPixel;
+ src += h * srcPitch - srcDelta - srcFmt.bytesPerPixel;
+ crossBlitLogic<uint16, uint32, true>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
} else if (srcFmt.bytesPerPixel == 3) {
- uint8 *col = (uint8 *)&color;
-#ifdef SCUMM_BIG_ENDIAN
- col++;
-#endif
- for (int y = 0; y < h; y++) {
- for (int x = 0; x < w; x++, src += 2, dst += 4) {
- memcpy(col, src, 3);
- srcFmt.colorToARGB(color, a, r, g, b);
- color = dstFmt.ARGBToColor(a, r, g, b);
- *(uint32 *)dst = color;
- }
- src += srcDelta;
- dst += dstDelta;
- }
+ // We need to blit the surface from bottom right to top left here.
+ // This is neeeded, because when we convert to the same memory
+ // buffer copying the surface from top left to bottom right would
+ // overwrite the source, since we have more bits per destination
+ // color than per source color.
+ dst += h * dstPitch - dstDelta - dstFmt.bytesPerPixel;
+ src += h * srcPitch - srcDelta - srcFmt.bytesPerPixel;
+ crossBlitLogic3BppSource<uint32, true>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
} else {
- for (int y = 0; y < h; y++) {
- for (int x = 0; x < w; x++, src += 4, dst += 4) {
- color = *(const uint32 *)src;
- srcFmt.colorToARGB(color, a, r, g, b);
- color = dstFmt.ARGBToColor(a, r, g, b);
- *(uint32 *)dst = color;
- }
- src += srcDelta;
- dst += dstDelta;
- }
+ crossBlitLogic<uint32, uint32, false>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
}
} else {
return false;
diff --git a/graphics/conversion.h b/graphics/conversion.h
index 6babc763e2..28e64a94fb 100644
--- a/graphics/conversion.h
+++ b/graphics/conversion.h
@@ -59,15 +59,18 @@ inline static void RGB2YUV(byte r, byte g, byte b, byte &y, byte &u, byte &v) {
* @return true if conversion completes successfully,
* false if there is an error.
*
- * @note This implementation currently arbitrarily requires that the
- * destination's format have at least as high a bytedepth as
- * the source's.
- * @note This can convert a rectangle in place, if the source and
- * destination format have the same bytedepth.
- *
+ * @note Blitting to a 3Bpp destination is not supported
+ * @note This can convert a surface in place, regardless of the
+ * source and destination format, as long as there is enough
+ * space for the destination. The dstPitch / srcPitch ratio
+ * must at least equal the dstBpp / srcBpp ratio for
+ * dstPitch >= srcPitch and at most dstBpp / srcBpp for
+ * dstPitch < srcPitch though.
*/
-bool crossBlit(byte *dst, const byte *src, int dstpitch, int srcpitch,
- int w, int h, const Graphics::PixelFormat &dstFmt, const Graphics::PixelFormat &srcFmt);
+bool crossBlit(byte *dst, const byte *src,
+ const uint dstPitch, const uint srcPitch,
+ const uint w, const uint h,
+ const Graphics::PixelFormat &dstFmt, const Graphics::PixelFormat &srcFmt);
} // End of namespace Graphics
diff --git a/graphics/decoders/bmp.cpp b/graphics/decoders/bmp.cpp
index f15d4e2519..bcfd0abbda 100644
--- a/graphics/decoders/bmp.cpp
+++ b/graphics/decoders/bmp.cpp
@@ -100,10 +100,10 @@ bool BitmapDecoder::loadStream(Common::SeekableReadStream &stream) {
_paletteColorCount = stream.readUint32LE();
/* uint32 colorsImportant = */ stream.readUint32LE();
- if (_paletteColorCount == 0)
- _paletteColorCount = 256;
-
if (bitsPerPixel == 8) {
+ if (_paletteColorCount == 0)
+ _paletteColorCount = 256;
+
// Read the palette
_palette = new byte[_paletteColorCount * 3];
for (uint16 i = 0; i < _paletteColorCount; i++) {
@@ -155,7 +155,7 @@ bool BitmapDecoder::loadStream(Common::SeekableReadStream &stream) {
}
} else { // 32 bpp
byte *dst = (byte *)_surface->pixels + (height - 1) * _surface->pitch;
-
+
for (int32 i = 0; i < height; i++) {
for (uint32 j = 0; j < width; j++) {
byte b = stream.readByte();
@@ -166,11 +166,11 @@ bool BitmapDecoder::loadStream(Common::SeekableReadStream &stream) {
// ref: http://msdn.microsoft.com/en-us/library/windows/desktop/dd183376%28v=vs.85%29.aspx
stream.readByte();
uint32 color = format.RGBToColor(r, g, b);
-
+
*((uint32 *)dst) = color;
dst += format.bytesPerPixel;
}
-
+
stream.skip(extraDataLength);
dst -= _surface->pitch * 2;
}
diff --git a/graphics/decoders/bmp.h b/graphics/decoders/bmp.h
index 59da682e4d..779da352be 100644
--- a/graphics/decoders/bmp.h
+++ b/graphics/decoders/bmp.h
@@ -24,6 +24,7 @@
* Image decoder used in engines:
* - hugo
* - mohawk
+ * - wintermute
*/
#ifndef GRAPHICS_DECODERS_BMP_H
diff --git a/graphics/decoders/image_decoder.h b/graphics/decoders/image_decoder.h
index 830645d361..49e31c6e3a 100644
--- a/graphics/decoders/image_decoder.h
+++ b/graphics/decoders/image_decoder.h
@@ -78,10 +78,15 @@ public:
* The palette's format is the same as PaletteManager's palette
* (interleaved RGB values).
*
- * @return the decoded palette, or 0 if no palette is present
+ * @return the decoded palette, or undefined if no palette is present
*/
virtual const byte *getPalette() const { return 0; }
+ /**
+ * Query if the decoded image has a palette.
+ */
+ virtual bool hasPalette() const { return getPaletteColorCount() != 0; }
+
/** Return the starting index of the palette. */
virtual byte getPaletteStartIndex() const { return 0; }
/** Return the number of colors in the palette. */
diff --git a/graphics/decoders/jpeg.cpp b/graphics/decoders/jpeg.cpp
index a871377ca1..08bc1f7a3d 100644
--- a/graphics/decoders/jpeg.cpp
+++ b/graphics/decoders/jpeg.cpp
@@ -81,7 +81,7 @@ const Surface *JPEGDecoder::getSurface() const {
const Graphics::Surface *uComponent = getComponent(2);
const Graphics::Surface *vComponent = getComponent(3);
- convertYUV444ToRGB(_rgbSurface, (byte *)yComponent->pixels, (byte *)uComponent->pixels, (byte *)vComponent->pixels, yComponent->w, yComponent->h, yComponent->pitch, uComponent->pitch);
+ 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;
}
@@ -452,7 +452,7 @@ bool JPEGDecoder::readSOS() {
_bitsNumber = 0;
for (byte i = 0; i < _numScanComp; i++)
- _scanComp[i]->DCpredictor = 0;
+ _scanComp[i]->DCpredictor = 0;
}
}
}
diff --git a/graphics/decoders/jpeg.h b/graphics/decoders/jpeg.h
index c74aa57ca1..d59b72adf4 100644
--- a/graphics/decoders/jpeg.h
+++ b/graphics/decoders/jpeg.h
@@ -25,6 +25,7 @@
* Image decoder used in engines:
* - groovie
* - mohawk
+ * - wintermute
*/
#ifndef GRAPHICS_JPEG_H
diff --git a/graphics/decoders/pcx.cpp b/graphics/decoders/pcx.cpp
new file mode 100644
index 0000000000..1250398c73
--- /dev/null
+++ b/graphics/decoders/pcx.cpp
@@ -0,0 +1,213 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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/stream.h"
+#include "common/textconsole.h"
+
+#include "graphics/pixelformat.h"
+#include "graphics/surface.h"
+#include "graphics/decoders/pcx.h"
+
+/**
+ * Based on the PCX specs:
+ * http://www.fileformat.info/format/pcx/spec/a10e75307b3a4cc49c3bbe6db4c41fa2/view.htm
+ * and the PCX decoder of FFmpeg (libavcodec/pcx.c):
+ * http://git.videolan.org/?p=ffmpeg.git;a=blob;f=libavcodec/pcx.c
+ */
+
+namespace Graphics {
+
+PCXDecoder::PCXDecoder() {
+ _surface = 0;
+ _palette = 0;
+ _paletteColorCount = 0;
+}
+
+PCXDecoder::~PCXDecoder() {
+ destroy();
+}
+
+void PCXDecoder::destroy() {
+ if (_surface) {
+ _surface->free();
+ delete _surface;
+ _surface = 0;
+ }
+
+ delete[] _palette;
+ _palette = 0;
+ _paletteColorCount = 0;
+}
+
+bool PCXDecoder::loadStream(Common::SeekableReadStream &stream) {
+ destroy();
+
+ if (stream.readByte() != 0x0a) // ZSoft PCX
+ return false;
+
+ byte version = stream.readByte(); // 0 - 5
+ if (version > 5)
+ return false;
+
+ bool compressed = stream.readByte(); // encoding, 1 = run length encoding
+ byte bitsPerPixel = stream.readByte(); // 1, 2, 4 or 8
+
+ // Window
+ uint16 xMin = stream.readUint16LE();
+ uint16 yMin = stream.readUint16LE();
+ uint16 xMax = stream.readUint16LE();
+ uint16 yMax = stream.readUint16LE();
+
+ uint16 width = xMax - xMin + 1;
+ uint16 height = yMax - yMin + 1;
+
+ if (xMax < xMin || yMax < yMin) {
+ warning("Invalid PCX image dimensions");
+ return false;
+ }
+
+ stream.skip(4); // HDpi, VDpi
+
+ // Read the EGA palette (colormap)
+ _palette = new byte[16 * 3];
+ for (uint16 i = 0; i < 16; i++) {
+ _palette[i * 3 + 0] = stream.readByte();
+ _palette[i * 3 + 1] = stream.readByte();
+ _palette[i * 3 + 2] = stream.readByte();
+ }
+
+ if (stream.readByte() != 0) // reserved, should be set to 0
+ return false;
+
+ byte nPlanes = stream.readByte();
+ uint16 bytesPerLine = stream.readUint16LE();
+ uint16 bytesPerscanLine = nPlanes * bytesPerLine;
+
+ if (bytesPerscanLine < width * bitsPerPixel * nPlanes / 8) {
+ warning("PCX data is corrupted");
+ return false;
+ }
+
+ stream.skip(60); // PaletteInfo, HscreenSize, VscreenSize, Filler
+
+ _surface = new Graphics::Surface();
+
+ byte *scanLine = new byte[bytesPerscanLine];
+ byte *dst;
+ int x, y;
+
+ 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;
+ _paletteColorCount = 0;
+
+ for (y = 0; y < height; y++) {
+ decodeRLE(stream, scanLine, bytesPerscanLine, compressed);
+
+ for (x = 0; x < width; x++) {
+ byte b = scanLine[x];
+ byte g = scanLine[x + bytesPerLine];
+ byte r = scanLine[x + (bytesPerLine << 1)];
+ uint32 color = format.RGBToColor(r, g, b);
+
+ *((uint32 *)dst) = color;
+ dst += format.bytesPerPixel;
+ }
+ }
+ } else if (nPlanes == 1 && bitsPerPixel == 8) { // 8bpp indexed
+ _surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+ dst = (byte *)_surface->pixels;
+ _paletteColorCount = 16;
+
+ for (y = 0; y < height; y++, dst += _surface->pitch) {
+ decodeRLE(stream, scanLine, bytesPerscanLine, compressed);
+ memcpy(dst, scanLine, width);
+ }
+
+ if (version == 5) {
+ if (stream.readByte() != 12) {
+ warning("Expected a palette after the PCX image data");
+ delete[] scanLine;
+ return false;
+ }
+
+ // Read the VGA palette
+ delete[] _palette;
+ _palette = new byte[256 * 3];
+ for (uint16 i = 0; i < 256; i++) {
+ _palette[i * 3 + 0] = stream.readByte();
+ _palette[i * 3 + 1] = stream.readByte();
+ _palette[i * 3 + 2] = stream.readByte();
+ }
+
+ _paletteColorCount = 256;
+ }
+ } 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;
+ _paletteColorCount = 16;
+
+ for (y = 0; y < height; y++, dst += _surface->pitch) {
+ decodeRLE(stream, scanLine, bytesPerscanLine, compressed);
+
+ for (x = 0; x < width; x++) {
+ int m = 0x80 >> (x & 7), v = 0;
+ for (int i = nPlanes - 1; i >= 0; i--) {
+ v <<= 1;
+ v += (scanLine[i * bytesPerLine + (x >> 3)] & m) == 0 ? 0 : 1;
+ }
+ dst[x] = v;
+ }
+ }
+ } else {
+ // Known unsupported case: 1 plane and bpp < 8 (1, 2 or 4)
+ warning("Invalid PCX file (%d planes, %d bpp)", nPlanes, bitsPerPixel);
+ delete[] scanLine;
+ return false;
+ }
+
+ delete[] scanLine;
+
+ return true;
+}
+
+void PCXDecoder::decodeRLE(Common::SeekableReadStream &stream, byte *dst, uint32 bytesPerscanLine, bool compressed) {
+ uint32 i = 0;
+ byte run, value;
+
+ if (compressed) {
+ while (i < bytesPerscanLine) {
+ run = 1;
+ value = stream.readByte();
+ if (value >= 0xc0) {
+ run = value & 0x3f;
+ value = stream.readByte();
+ }
+ while (i < bytesPerscanLine && run--)
+ dst[i++] = value;
+ }
+ } else {
+ stream.read(dst, bytesPerscanLine);
+ }
+}
+
+} // End of namespace Graphics
diff --git a/graphics/decoders/pcx.h b/graphics/decoders/pcx.h
new file mode 100644
index 0000000000..b25166b3d9
--- /dev/null
+++ b/graphics/decoders/pcx.h
@@ -0,0 +1,68 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * PCX decoder used in engines:
+ * - dreamweb
+ * - hugo
+ * - queen
+ * - tucker
+ */
+
+#ifndef GRAPHICS_DECODERS_PCX_H
+#define GRAPHICS_DECODERS_PCX_H
+
+#include "common/scummsys.h"
+#include "common/str.h"
+#include "graphics/decoders/image_decoder.h"
+
+namespace Common{
+class SeekableReadStream;
+}
+
+namespace Graphics {
+
+struct PixelFormat;
+struct Surface;
+
+class PCXDecoder : public ImageDecoder {
+public:
+ PCXDecoder();
+ virtual ~PCXDecoder();
+
+ // ImageDecoder API
+ void destroy();
+ virtual bool loadStream(Common::SeekableReadStream &stream);
+ virtual const Surface *getSurface() const { return _surface; }
+ const byte *getPalette() const { return _palette; }
+ uint16 getPaletteColorCount() const { return _paletteColorCount; }
+
+private:
+ void decodeRLE(Common::SeekableReadStream &stream, byte *dst, uint32 bytesPerScanline, bool compressed);
+
+ Surface *_surface;
+ byte *_palette;
+ uint16 _paletteColorCount;
+};
+
+} // End of namespace Graphics
+
+#endif
diff --git a/graphics/decoders/pict.cpp b/graphics/decoders/pict.cpp
index 7eddd3b893..b1d408ebc3 100644
--- a/graphics/decoders/pict.cpp
+++ b/graphics/decoders/pict.cpp
@@ -235,10 +235,13 @@ bool PICTDecoder::loadStream(Common::SeekableReadStream &stream) {
// PICT v2 opcodes are two bytes
uint16 opcode = stream.readUint16BE();
- if (opNum == 0 && opcode != 0x0011)
- error("Cannot find PICT version opcode");
- else if (opNum == 1 && opcode != 0x0C00)
- error("Cannot find PICT header opcode");
+ if (opNum == 0 && opcode != 0x0011) {
+ warning("Cannot find PICT version opcode");
+ return false;
+ } else if (opNum == 1 && opcode != 0x0C00) {
+ warning("Cannot find PICT header opcode");
+ return false;
+ }
// Since opcodes are word-aligned, we need to mark our starting
// position here.
@@ -292,12 +295,12 @@ struct PackBitsRectData {
uint16 mode;
};
-void PICTDecoder::unpackBitsRect(Common::SeekableReadStream &stream, bool hasPalette) {
+void PICTDecoder::unpackBitsRect(Common::SeekableReadStream &stream, bool withPalette) {
PackBitsRectData packBitsData;
- packBitsData.pixMap = readPixMap(stream, !hasPalette);
+ packBitsData.pixMap = readPixMap(stream, !withPalette);
// Read in the palette if there is one present
- if (hasPalette) {
+ if (withPalette) {
// See http://developer.apple.com/legacy/mac/library/documentation/mac/QuickDraw/QuickDraw-267.html
stream.readUint32BE(); // seed
stream.readUint16BE(); // flags
@@ -469,10 +472,10 @@ void PICTDecoder::outputPixelBuffer(byte *&out, byte value, byte bitsPerPixel) {
}
}
-void PICTDecoder::skipBitsRect(Common::SeekableReadStream &stream, bool hasPalette) {
+void PICTDecoder::skipBitsRect(Common::SeekableReadStream &stream, bool withPalette) {
// Step through a PackBitsRect/DirectBitsRect function
- if (!hasPalette)
+ if (!withPalette)
stream.readUint32BE();
uint16 rowBytes = stream.readUint16BE();
@@ -492,7 +495,7 @@ void PICTDecoder::skipBitsRect(Common::SeekableReadStream &stream, bool hasPalet
stream.readUint16BE(); // pixelSize
stream.skip(16);
- if (hasPalette) {
+ if (withPalette) {
stream.readUint32BE();
stream.readUint16BE();
stream.skip((stream.readUint16BE() + 1) * 8);
@@ -543,7 +546,7 @@ void PICTDecoder::decodeCompressedQuickTime(Common::SeekableReadStream &stream)
// Skip the matte and mask
stream.skip(matteSize + maskSize);
-
+
// Now we've reached the image descriptor, so read the relevant data from that
uint32 idStart = stream.pos();
uint32 idSize = stream.readUint32BE();
diff --git a/graphics/decoders/pict.h b/graphics/decoders/pict.h
index 417a7c5134..6f0d86c7a1 100644
--- a/graphics/decoders/pict.h
+++ b/graphics/decoders/pict.h
@@ -24,6 +24,7 @@
* @file
* Image decoder used in engines:
* - mohawk
+ * - pegasus
* - sci
*/
@@ -87,9 +88,9 @@ private:
bool _continueParsing;
// Utility Functions
- void unpackBitsRect(Common::SeekableReadStream &stream, bool hasPalette);
+ void unpackBitsRect(Common::SeekableReadStream &stream, bool withPalette);
void unpackBitsLine(byte *out, uint32 length, Common::SeekableReadStream *stream, byte bitsPerPixel, byte bytesPerPixel);
- void skipBitsRect(Common::SeekableReadStream &stream, bool hasPalette);
+ void skipBitsRect(Common::SeekableReadStream &stream, bool withPalette);
void decodeCompressedQuickTime(Common::SeekableReadStream &stream);
void outputPixelBuffer(byte *&out, byte value, byte bitsPerPixel);
diff --git a/graphics/decoders/png.cpp b/graphics/decoders/png.cpp
index bfaab6dc35..4f917b44b1 100644
--- a/graphics/decoders/png.cpp
+++ b/graphics/decoders/png.cpp
@@ -191,6 +191,7 @@ bool PNGDecoder::loadStream(Common::SeekableReadStream &stream) {
}
// After the transformations have been registered, the image data is read again.
+ png_set_interlace_handling(pngPtr);
png_read_update_info(pngPtr, infoPtr);
png_get_IHDR(pngPtr, infoPtr, &w, &h, &bitDepth, &colorType, NULL, NULL, NULL);
width = w;
diff --git a/graphics/decoders/png.h b/graphics/decoders/png.h
index e52ddabd7d..5e608eb7b1 100644
--- a/graphics/decoders/png.h
+++ b/graphics/decoders/png.h
@@ -23,6 +23,7 @@
/*
* PNG decoder used in engines:
* - sword25
+ * - wintermute
* Dependencies:
* - libpng
*/
diff --git a/graphics/decoders/tga.cpp b/graphics/decoders/tga.cpp
index 0b2318e127..c3b9d84055 100644
--- a/graphics/decoders/tga.cpp
+++ b/graphics/decoders/tga.cpp
@@ -145,7 +145,10 @@ bool TGADecoder::readHeader(Common::SeekableReadStream &tga, byte &imageType, by
if (pixelDepth == 24) {
_format = PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0);
} else if (pixelDepth == 32) {
- _format = PixelFormat(4, 8, 8, 8, attributeBits, 16, 8, 0, 24);
+ // HACK: According to the spec, attributeBits should determine the amount
+ // of alpha-bits, however, as the game files that use this decoder seems
+ // to ignore that fact, we force the amount to 8 for 32bpp files for now.
+ _format = PixelFormat(4, 8, 8, 8, /* attributeBits */ 8, 16, 8, 0, 24);
} else if (pixelDepth == 16 && imageType == TYPE_TRUECOLOR) {
// 16bpp TGA is ARGB1555
_format = PixelFormat(2, 5, 5, 5, attributeBits, 10, 5, 0, 15);
diff --git a/graphics/decoders/tga.h b/graphics/decoders/tga.h
index dfdc5a4da9..d8ccf8f766 100644
--- a/graphics/decoders/tga.h
+++ b/graphics/decoders/tga.h
@@ -25,7 +25,7 @@
/*
* TGA decoder used in engines:
- * - none
+ * - wintermute
*/
#ifndef GRAPHICS_DECODERS_TGA_H
diff --git a/graphics/fonts/consolefont.cpp b/graphics/fonts/consolefont.cpp
index 8244d75fc2..748aa08a5c 100644
--- a/graphics/fonts/consolefont.cpp
+++ b/graphics/fonts/consolefont.cpp
@@ -1,7 +1,7 @@
// Generated by convbdf on Fri Jan 6 14:32:21 2012
#include "graphics/fonts/bdf.h"
-// Font information:
+// Font information:
// Name: -Misc-Fixed-Medium-R-Normal--8-80-75-75-C-50-ISO8859-1
// Size: 5x8
// Box: 5 8 0 -1
diff --git a/graphics/fonts/newfont.cpp b/graphics/fonts/newfont.cpp
index 10af1efb0c..4922e24676 100644
--- a/graphics/fonts/newfont.cpp
+++ b/graphics/fonts/newfont.cpp
@@ -1,7 +1,7 @@
// Generated by convbdf on Fri Jan 6 14:33:07 2012
#include "graphics/fonts/bdf.h"
-// Font information:
+// Font information:
// Name: -Schumacher-Clean-Medium-R-Normal--12-120-75-75-C-60-ISO8859-1
// Size: 6x12
// Box: 6 12 0 -3
diff --git a/graphics/fonts/newfont_big.cpp b/graphics/fonts/newfont_big.cpp
index 0e61068ade..550d6dbfa9 100644
--- a/graphics/fonts/newfont_big.cpp
+++ b/graphics/fonts/newfont_big.cpp
@@ -1,7 +1,7 @@
// Generated by convbdf on Fri Jan 6 14:33:14 2012
#include "graphics/fonts/bdf.h"
-// Font information:
+// Font information:
// Name: -Adobe-Helvetica-Bold-R-Normal--12-120-75-75-P-70-ISO8859-1
// Size: 13x14
// Box: 13 15 -1 -3
diff --git a/graphics/module.mk b/graphics/module.mk
index e67efd2cf5..f560d9dc97 100644
--- a/graphics/module.mk
+++ b/graphics/module.mk
@@ -25,6 +25,7 @@ MODULE_OBJS := \
yuv_to_rgb.o \
decoders/bmp.o \
decoders/jpeg.o \
+ decoders/pcx.o \
decoders/pict.o \
decoders/png.o \
decoders/tga.o
diff --git a/graphics/primitives.cpp b/graphics/primitives.cpp
index 9834af65ba..b88db39f36 100644
--- a/graphics/primitives.cpp
+++ b/graphics/primitives.cpp
@@ -61,59 +61,21 @@ void drawLine(int x0, int y0, int x1, int y1, int color, void (*plotProc)(int, i
}
}
+void drawThickLine(int x0, int y0, int x1, int y1, int penX, int penY, int color, void (*plotProc)(int, int, int, void *), void *data) {
+ assert(penX > 0 && penY > 0);
-// FIXME: This is a limited version of thick line drawing
-// it draws striped lines at some angles. Better algorithm could
-// be found here:
-//
-// http://homepages.enterprise.net/murphy/thickline/index.html
-//
-// Feel free to replace it with better implementation
-void drawThickLine(int x0, int y0, int x1, int y1, int thickness, int color, void (*plotProc)(int, int, int, void *), void *data) {
- const bool steep = ABS(y1 - y0) > ABS(x1 - x0);
-
- if (steep) {
- SWAP(x0, y0);
- SWAP(x1, y1);
- }
-
- float dx = x1 - x0;
- float dy = y1 - y0;
- float d = (float)sqrt(dx * dx + dy * dy);
-
- if (!d)
+ // Shortcut
+ if (penX == 1 && penY == 1) {
+ drawLine(x0, y0, x1, y1, color, plotProc, data);
return;
-
- int thickX = (int)((float)thickness * dy / d / 2);
- int thickY = (int)((float)thickness * dx / d / 2);
-
- const int delta_x = ABS(x1 - x0);
- const int delta_y = ABS(y1 - y0);
- const int delta_err = delta_y;
- int x = x0;
- int y = y0;
- int err = 0;
-
- const int x_step = (x0 < x1) ? 1 : -1;
- const int y_step = (y0 < y1) ? 1 : -1;
-
- if (steep)
- drawLine(y - thickY, x + thickX, y + thickY, x - thickX, color, plotProc, data);
- else
- drawLine(x - thickX, y + thickY, x + thickX, y - thickY, color, plotProc, data);
-
- while (x != x1) {
- x += x_step;
- err += delta_err;
- if (2 * err > delta_x) {
- y += y_step;
- err -= delta_x;
- }
- if (steep)
- drawLine(y - thickY, x + thickX, y + thickY, x - thickX, color, plotProc, data);
- else
- drawLine(x - thickX, y + thickY, x + thickX, y - thickY, color, plotProc, data);
}
+
+ // TODO: Optimize this. It currently is a very naive way of handling
+ // thick lines since quite often it will be drawing to the same pixel
+ // multiple times.
+ for (int x = 0; x < penX; x++)
+ for (int y = 0; y < penY; y++)
+ drawLine(x0 + x, y0 + y, x1 + x, y1 + y, color, plotProc, data);
}
} // End of namespace Graphics
diff --git a/graphics/primitives.h b/graphics/primitives.h
index 0ab2dabcd8..f0780afc2e 100644
--- a/graphics/primitives.h
+++ b/graphics/primitives.h
@@ -25,7 +25,7 @@
namespace Graphics {
void drawLine(int x0, int y0, int x1, int y1, int color, void (*plotProc)(int, int, int, void *), void *data);
-void drawThickLine(int x0, int y0, int x1, int y1, int thickness, int color, void (*plotProc)(int, int, int, void *), void *data);
+void drawThickLine(int x0, int y0, int x1, int y1, int penX, int penY, int color, void (*plotProc)(int, int, int, void *), void *data);
} // End of namespace Graphics
diff --git a/graphics/scaler/aspect.cpp b/graphics/scaler/aspect.cpp
index 2f06b2e4f6..92d6c5777e 100644
--- a/graphics/scaler/aspect.cpp
+++ b/graphics/scaler/aspect.cpp
@@ -23,6 +23,9 @@
#include "graphics/scaler/intern.h"
#include "graphics/scaler/aspect.h"
+#ifdef USE_ARM_NEON_ASPECT_CORRECTOR
+#include <arm_neon.h>
+#endif
#define kSuperFastAndUglyAspectMode 0 // No interpolation at all, but super-fast
#define kVeryFastAndGoodAspectMode 1 // Good quality with very good speed
@@ -55,13 +58,66 @@ static inline void interpolate5Line(uint16 *dst, const uint16 *srcA, const uint1
#if ASPECT_MODE == kVeryFastAndGoodAspectMode
+#ifdef USE_ARM_NEON_ASPECT_CORRECTOR
+
+template<typename ColorMask>
+static void interpolate5LineNeon(uint16 *dst, const uint16 *srcA, const uint16 *srcB, int width, int k1, int k2) {
+ uint16x4_t kRedBlueMask_4 = vdup_n_u16(ColorMask::kRedBlueMask);
+ uint16x4_t kGreenMask_4 = vdup_n_u16(ColorMask::kGreenMask);
+ uint16x4_t k1_4 = vdup_n_u16(k1);
+ uint16x4_t k2_4 = vdup_n_u16(k2);
+ while (width >= 4) {
+ uint16x4_t srcA_4 = vld1_u16(srcA);
+ uint16x4_t srcB_4 = vld1_u16(srcB);
+ uint16x4_t p1_4 = srcB_4;
+ uint16x4_t p2_4 = srcA_4;
+
+ uint16x4_t p1_rb_4 = vand_u16(p1_4, kRedBlueMask_4);
+ uint16x4_t p1_g_4 = vand_u16(p1_4, kGreenMask_4);
+ uint16x4_t p2_rb_4 = vand_u16(p2_4, kRedBlueMask_4);
+ uint16x4_t p2_g_4 = vand_u16(p2_4, kGreenMask_4);
+
+ uint32x4_t tmp_rb_4 = vshrq_n_u32(vmlal_u16(vmull_u16(p2_rb_4, k2_4), p1_rb_4, k1_4), 3);
+ uint32x4_t tmp_g_4 = vshrq_n_u32(vmlal_u16(vmull_u16(p2_g_4, k2_4), p1_g_4, k1_4), 3);
+ uint16x4_t p_rb_4 = vmovn_u32(tmp_rb_4);
+ p_rb_4 = vand_u16(p_rb_4, kRedBlueMask_4);
+ uint16x4_t p_g_4 = vmovn_u32(tmp_g_4);
+ p_g_4 = vand_u16(p_g_4, kGreenMask_4);
+
+ uint16x4_t result_4 = p_rb_4 | p_g_4;
+ vst1_u16(dst, result_4);
+
+ dst += 4;
+ srcA += 4;
+ srcB += 4;
+ width -= 4;
+ }
+}
+#endif // USE_ARM_NEON_ASPECT_CORRECTOR
+
template<typename ColorMask, int scale>
static void interpolate5Line(uint16 *dst, const uint16 *srcA, const uint16 *srcB, int width) {
if (scale == 1) {
+#ifdef USE_NEON_ASPECT_CORRECTOR
+ int width4 = width & ~3;
+ interpolate5LineNeon<ColorMask>(dst, srcA, srcB, width4, 7, 1);
+ srcA += width4;
+ srcB += width4;
+ dst += width4;
+ width -= width4;
+#endif // USE_ARM_NEON_ASPECT_CORRECTOR
while (width--) {
*dst++ = interpolate16_7_1<ColorMask>(*srcB++, *srcA++);
}
} else {
+#ifdef USE_ARM_NEON_ASPECT_CORRECTOR
+ int width4 = width & ~3;
+ interpolate5LineNeon<ColorMask>(dst, srcA, srcB, width4, 5, 3);
+ srcA += width4;
+ srcB += width4;
+ dst += width4;
+ width -= width4;
+#endif // USE_ARM_NEON_ASPECT_CORRECTOR
while (width--) {
*dst++ = interpolate16_5_3<ColorMask>(*srcB++, *srcA++);
}
diff --git a/graphics/sjis.h b/graphics/sjis.h
index 2d05005fc3..928332f712 100644
--- a/graphics/sjis.h
+++ b/graphics/sjis.h
@@ -169,7 +169,7 @@ protected:
bool _flippedMode;
int _fontWidth, _fontHeight;
uint8 _bitPosNewLineMask;
-
+
bool isASCII(uint16 ch) const;
virtual const uint8 *getCharData(uint16 c) const = 0;
diff --git a/graphics/surface.cpp b/graphics/surface.cpp
index c0f1046eae..41ae8dcebb 100644
--- a/graphics/surface.cpp
+++ b/graphics/surface.cpp
@@ -26,6 +26,7 @@
#include "common/textconsole.h"
#include "graphics/primitives.h"
#include "graphics/surface.h"
+#include "graphics/conversion.h"
namespace Graphics {
@@ -49,6 +50,17 @@ void Surface::drawLine(int x0, int y0, int x1, int y1, uint32 color) {
error("Surface::drawLine: bytesPerPixel must be 1, 2, or 4");
}
+void Surface::drawThickLine(int x0, int y0, int x1, int y1, int penX, int penY, uint32 color) {
+ if (format.bytesPerPixel == 1)
+ Graphics::drawThickLine(x0, y0, x1, y1, penX, penY, color, plotPoint<byte>, this);
+ else if (format.bytesPerPixel == 2)
+ Graphics::drawThickLine(x0, y0, x1, y1, penX, penY, color, plotPoint<uint16>, this);
+ else if (format.bytesPerPixel == 4)
+ Graphics::drawThickLine(x0, y0, x1, y1, penX, penY, color, plotPoint<uint32>, this);
+ else
+ error("Surface::drawThickLine: bytesPerPixel must be 1, 2, or 4");
+}
+
void Surface::create(uint16 width, uint16 height, const PixelFormat &f) {
free();
@@ -271,6 +283,72 @@ void Surface::move(int dx, int dy, int height) {
}
}
+void Surface::convertToInPlace(const PixelFormat &dstFormat, const byte *palette) {
+ // Do not convert to the same format and ignore empty surfaces.
+ if (format == dstFormat || pixels == 0) {
+ return;
+ }
+
+ if (format.bytesPerPixel == 0 || format.bytesPerPixel > 4)
+ error("Surface::convertToInPlace(): Can only convert from 1Bpp, 2Bpp, 3Bpp, and 4Bpp");
+
+ if (dstFormat.bytesPerPixel != 2 && dstFormat.bytesPerPixel != 4)
+ error("Surface::convertToInPlace(): Can only convert to 2Bpp and 4Bpp");
+
+ // In case the surface data needs more space allocate it.
+ if (dstFormat.bytesPerPixel > format.bytesPerPixel) {
+ void *const newPixels = realloc(pixels, w * h * dstFormat.bytesPerPixel);
+ if (!newPixels) {
+ error("Surface::convertToInPlace(): Out of memory");
+ }
+ pixels = newPixels;
+ }
+
+ // We take advantage of the fact that pitch is always w * format.bytesPerPixel.
+ // This is assured by the logic of Surface::create.
+
+ // We need to handle 1 Bpp surfaces special here.
+ if (format.bytesPerPixel == 1) {
+ assert(palette);
+
+ for (int y = h; y > 0; --y) {
+ const byte *srcRow = (const byte *)pixels + y * pitch - 1;
+ byte *dstRow = (byte *)pixels + y * w * dstFormat.bytesPerPixel - dstFormat.bytesPerPixel;
+
+ for (int x = 0; x < w; x++) {
+ byte index = *srcRow--;
+ byte r = palette[index * 3];
+ byte g = palette[index * 3 + 1];
+ byte b = palette[index * 3 + 2];
+
+ uint32 color = dstFormat.RGBToColor(r, g, b);
+
+ if (dstFormat.bytesPerPixel == 2)
+ *((uint16 *)dstRow) = color;
+ else
+ *((uint32 *)dstRow) = color;
+
+ dstRow -= dstFormat.bytesPerPixel;
+ }
+ }
+ } else {
+ crossBlit((byte *)pixels, (const byte *)pixels, w * dstFormat.bytesPerPixel, pitch, w, h, dstFormat, format);
+ }
+
+ // In case the surface data got smaller, free up some memory.
+ if (dstFormat.bytesPerPixel < format.bytesPerPixel) {
+ void *const newPixels = realloc(pixels, w * h * dstFormat.bytesPerPixel);
+ if (!newPixels) {
+ error("Surface::convertToInPlace(): Freeing memory failed");
+ }
+ pixels = newPixels;
+ }
+
+ // Update the surface specific data.
+ format = dstFormat;
+ pitch = w * dstFormat.bytesPerPixel;
+}
+
Graphics::Surface *Surface::convertTo(const PixelFormat &dstFormat, const byte *palette) const {
assert(pixels);
diff --git a/graphics/surface.h b/graphics/surface.h
index eb8d1ac42e..6c9e464657 100644
--- a/graphics/surface.h
+++ b/graphics/surface.h
@@ -137,6 +137,20 @@ struct Surface {
/**
* 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.
+ *
+ * Note that you should only use this, when you created the Surface data via
+ * create! Otherwise this function has undefined behavior.
+ *
+ * @param dstFormat The desired format
+ * @param palette The palette (in RGB888), if the source format has a Bpp of 1
+ */
+ void convertToInPlace(const PixelFormat &dstFormat, const byte *palette = 0);
+
+ /**
+ * Convert the data to another pixel format.
+ *
* The calling code must call free on the returned surface and then delete
* it.
*
@@ -153,10 +167,26 @@ struct Surface {
* @param x1 The x coordinate of the end point.
* @param y1 The y coordinate of the end point.
* @param color The color of the line.
+ * @note This is just a wrapper around Graphics::drawLine
*/
void drawLine(int x0, int y0, int x1, int y1, uint32 color);
/**
+ * Draw a thick line.
+ *
+ * @param x0 The x coordinate of the start point.
+ * @param y0 The y coordiante of the start point.
+ * @param x1 The x coordinate of the end point.
+ * @param y1 The y coordinate of the end point.
+ * @param penX The width of the pen (thickness in the x direction)
+ * @param penY The height of the pen (thickness in the y direction)
+ * @param color The color of the line.
+ * @note This is just a wrapper around Graphics::drawThickLine
+ * @note The x/y coordinates of the start and end points are the upper-left most part of the pen
+ */
+ void drawThickLine(int x0, int y0, int x1, int y1, int penX, int penY, uint32 color);
+
+ /**
* Draw a horizontal line.
*
* @param x The start x coordinate of the line.
diff --git a/graphics/yuv_to_rgb.cpp b/graphics/yuv_to_rgb.cpp
index 78903d0cd8..6043315a13 100644
--- a/graphics/yuv_to_rgb.cpp
+++ b/graphics/yuv_to_rgb.cpp
@@ -83,129 +83,127 @@
// BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
// SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-#include "common/scummsys.h"
-#include "common/singleton.h"
-
#include "graphics/surface.h"
+#include "graphics/yuv_to_rgb.h"
+
+namespace Common {
+DECLARE_SINGLETON(Graphics::YUVToRGBManager);
+}
namespace Graphics {
class YUVToRGBLookup {
public:
- YUVToRGBLookup(Graphics::PixelFormat format);
- ~YUVToRGBLookup();
-
- int16 *_colorTab;
- uint32 *_rgbToPix;
-};
+ YUVToRGBLookup(Graphics::PixelFormat format, YUVToRGBManager::LuminanceScale scale);
-YUVToRGBLookup::YUVToRGBLookup(Graphics::PixelFormat format) {
- _colorTab = new int16[4 * 256]; // 2048 bytes
+ Graphics::PixelFormat getFormat() const { return _format; }
+ YUVToRGBManager::LuminanceScale getScale() const { return _scale; }
+ const uint32 *getRGBToPix() const { return _rgbToPix; }
- int16 *Cr_r_tab = &_colorTab[0 * 256];
- int16 *Cr_g_tab = &_colorTab[1 * 256];
- int16 *Cb_g_tab = &_colorTab[2 * 256];
- int16 *Cb_b_tab = &_colorTab[3 * 256];
+private:
+ Graphics::PixelFormat _format;
+ YUVToRGBManager::LuminanceScale _scale;
+ uint32 _rgbToPix[3 * 768]; // 9216 bytes
+};
- _rgbToPix = new uint32[3 * 768]; // 9216 bytes
+YUVToRGBLookup::YUVToRGBLookup(Graphics::PixelFormat format, YUVToRGBManager::LuminanceScale scale) {
+ _format = format;
+ _scale = scale;
uint32 *r_2_pix_alloc = &_rgbToPix[0 * 768];
uint32 *g_2_pix_alloc = &_rgbToPix[1 * 768];
uint32 *b_2_pix_alloc = &_rgbToPix[2 * 768];
- int16 CR, CB;
- int i;
+ if (scale == YUVToRGBManager::kScaleFull) {
+ // Set up entries 0-255 in rgb-to-pixel value tables.
+ for (int i = 0; i < 256; i++) {
+ r_2_pix_alloc[i + 256] = format.RGBToColor(i, 0, 0);
+ g_2_pix_alloc[i + 256] = format.RGBToColor(0, i, 0);
+ b_2_pix_alloc[i + 256] = format.RGBToColor(0, 0, i);
+ }
+
+ // Spread out the values we have to the rest of the array so that we do
+ // not need to check for overflow.
+ for (int i = 0; i < 256; i++) {
+ r_2_pix_alloc[i] = r_2_pix_alloc[256];
+ r_2_pix_alloc[i + 512] = r_2_pix_alloc[511];
+ g_2_pix_alloc[i] = g_2_pix_alloc[256];
+ g_2_pix_alloc[i + 512] = g_2_pix_alloc[511];
+ b_2_pix_alloc[i] = b_2_pix_alloc[256];
+ b_2_pix_alloc[i + 512] = b_2_pix_alloc[511];
+ }
+ } else {
+ // Set up entries 16-235 in rgb-to-pixel value tables
+ for (int i = 16; i < 236; i++) {
+ int scaledValue = (i - 16) * 255 / 219;
+ r_2_pix_alloc[i + 256] = format.RGBToColor(scaledValue, 0, 0);
+ g_2_pix_alloc[i + 256] = format.RGBToColor(0, scaledValue, 0);
+ b_2_pix_alloc[i + 256] = format.RGBToColor(0, 0, scaledValue);
+ }
+
+ // Spread out the values we have to the rest of the array so that we do
+ // not need to check for overflow. We have to do it here in two steps.
+ for (int i = 0; i < 256 + 16; i++) {
+ r_2_pix_alloc[i] = r_2_pix_alloc[256 + 16];
+ g_2_pix_alloc[i] = g_2_pix_alloc[256 + 16];
+ b_2_pix_alloc[i] = b_2_pix_alloc[256 + 16];
+ }
+
+ for (int i = 256 + 236; i < 768; i++) {
+ r_2_pix_alloc[i] = r_2_pix_alloc[256 + 236 - 1];
+ g_2_pix_alloc[i] = g_2_pix_alloc[256 + 236 - 1];
+ b_2_pix_alloc[i] = b_2_pix_alloc[256 + 236 - 1];
+ }
+ }
+}
+
+YUVToRGBManager::YUVToRGBManager() {
+ _lookup = 0;
+
+ int16 *Cr_r_tab = &_colorTab[0 * 256];
+ int16 *Cr_g_tab = &_colorTab[1 * 256];
+ int16 *Cb_g_tab = &_colorTab[2 * 256];
+ int16 *Cb_b_tab = &_colorTab[3 * 256];
// Generate the tables for the display surface
- for (i = 0; i < 256; i++) {
+ for (int i = 0; i < 256; i++) {
// Gamma correction (luminescence table) and chroma correction
// would be done here. See the Berkeley mpeg_play sources.
- CR = CB = (i - 128);
+ int16 CR = (i - 128), CB = CR;
Cr_r_tab[i] = (int16) ( (0.419 / 0.299) * CR) + 0 * 768 + 256;
Cr_g_tab[i] = (int16) (-(0.299 / 0.419) * CR) + 1 * 768 + 256;
Cb_g_tab[i] = (int16) (-(0.114 / 0.331) * CB);
Cb_b_tab[i] = (int16) ( (0.587 / 0.331) * CB) + 2 * 768 + 256;
}
-
- // Set up entries 0-255 in rgb-to-pixel value tables.
- for (i = 0; i < 256; i++) {
- r_2_pix_alloc[i + 256] = format.RGBToColor(i, 0, 0);
- g_2_pix_alloc[i + 256] = format.RGBToColor(0, i, 0);
- b_2_pix_alloc[i + 256] = format.RGBToColor(0, 0, i);
- }
-
- // Spread out the values we have to the rest of the array so that we do
- // not need to check for overflow.
- for (i = 0; i < 256; i++) {
- r_2_pix_alloc[i] = r_2_pix_alloc[256];
- r_2_pix_alloc[i + 512] = r_2_pix_alloc[511];
- g_2_pix_alloc[i] = g_2_pix_alloc[256];
- g_2_pix_alloc[i + 512] = g_2_pix_alloc[511];
- b_2_pix_alloc[i] = b_2_pix_alloc[256];
- b_2_pix_alloc[i + 512] = b_2_pix_alloc[511];
- }
-}
-
-YUVToRGBLookup::~YUVToRGBLookup() {
- delete[] _rgbToPix;
- delete[] _colorTab;
-}
-
-class YUVToRGBManager : public Common::Singleton<YUVToRGBManager> {
-public:
- const YUVToRGBLookup *getLookup(Graphics::PixelFormat format);
-
-private:
- friend class Common::Singleton<SingletonBaseType>;
- YUVToRGBManager();
- ~YUVToRGBManager();
-
- Graphics::PixelFormat _lastFormat;
- YUVToRGBLookup *_lookup;
-};
-
-YUVToRGBManager::YUVToRGBManager() {
- _lookup = 0;
}
YUVToRGBManager::~YUVToRGBManager() {
delete _lookup;
}
-const YUVToRGBLookup *YUVToRGBManager::getLookup(Graphics::PixelFormat format) {
- if (_lastFormat == format)
+const YUVToRGBLookup *YUVToRGBManager::getLookup(Graphics::PixelFormat format, YUVToRGBManager::LuminanceScale scale) {
+ if (_lookup && _lookup->getFormat() == format && _lookup->getScale() == scale)
return _lookup;
delete _lookup;
- _lookup = new YUVToRGBLookup(format);
- _lastFormat = format;
+ _lookup = new YUVToRGBLookup(format, scale);
return _lookup;
}
-} // End of namespace Graphics
-
-namespace Common {
-DECLARE_SINGLETON(Graphics::YUVToRGBManager);
-}
-
-#define YUVToRGBMan (Graphics::YUVToRGBManager::instance())
-
-namespace Graphics {
-
#define PUT_PIXEL(s, d) \
L = &rgbToPix[(s)]; \
*((PixelInt *)(d)) = (L[cr_r] | L[crb_g] | L[cb_b])
template<typename PixelInt>
-void convertYUV444ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
+void convertYUV444ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup, int16 *colorTab, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
// Keep the tables in pointers here to avoid a dereference on each pixel
- const int16 *Cr_r_tab = lookup->_colorTab;
+ const int16 *Cr_r_tab = colorTab;
const int16 *Cr_g_tab = Cr_r_tab + 256;
const int16 *Cb_g_tab = Cr_g_tab + 256;
const int16 *Cb_b_tab = Cb_g_tab + 256;
- const uint32 *rgbToPix = lookup->_rgbToPix;
+ const uint32 *rgbToPix = lookup->getRGBToPix();
for (int h = 0; h < yHeight; h++) {
for (int w = 0; w < yWidth; w++) {
@@ -229,32 +227,32 @@ void convertYUV444ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup
}
}
-void convertYUV444ToRGB(Graphics::Surface *dst, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
+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->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4);
assert(ySrc && uSrc && vSrc);
- const YUVToRGBLookup *lookup = YUVToRGBMan.getLookup(dst->format);
+ const YUVToRGBLookup *lookup = getLookup(dst->format, scale);
// 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, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
+ convertYUV444ToRGB<uint16>((byte *)dst->pixels, dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
else
- convertYUV444ToRGB<uint32>((byte *)dst->pixels, dst->pitch, lookup, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
+ convertYUV444ToRGB<uint32>((byte *)dst->pixels, dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
}
template<typename PixelInt>
-void convertYUV420ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
+void convertYUV420ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup, int16 *colorTab, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
int halfHeight = yHeight >> 1;
int halfWidth = yWidth >> 1;
// Keep the tables in pointers here to avoid a dereference on each pixel
- const int16 *Cr_r_tab = lookup->_colorTab;
+ const int16 *Cr_r_tab = colorTab;
const int16 *Cr_g_tab = Cr_r_tab + 256;
const int16 *Cb_g_tab = Cr_g_tab + 256;
const int16 *Cb_b_tab = Cb_g_tab + 256;
- const uint32 *rgbToPix = lookup->_rgbToPix;
+ const uint32 *rgbToPix = lookup->getRGBToPix();
for (int h = 0; h < halfHeight; h++) {
for (int w = 0; w < halfWidth; w++) {
@@ -283,7 +281,7 @@ void convertYUV420ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup
}
}
-void convertYUV420ToRGB(Graphics::Surface *dst, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
+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->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4);
@@ -291,13 +289,13 @@ void convertYUV420ToRGB(Graphics::Surface *dst, const byte *ySrc, const byte *uS
assert((yWidth & 1) == 0);
assert((yHeight & 1) == 0);
- const YUVToRGBLookup *lookup = YUVToRGBMan.getLookup(dst->format);
+ const YUVToRGBLookup *lookup = getLookup(dst->format, scale);
// 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, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
+ convertYUV420ToRGB<uint16>((byte *)dst->pixels, dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
else
- convertYUV420ToRGB<uint32>((byte *)dst->pixels, dst->pitch, lookup, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
+ convertYUV420ToRGB<uint32>((byte *)dst->pixels, dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
}
#define READ_QUAD(ptr, prefix) \
@@ -325,13 +323,13 @@ void convertYUV420ToRGB(Graphics::Surface *dst, const byte *ySrc, const byte *uS
xDiff++
template<typename PixelInt>
-void convertYUV410ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
+void convertYUV410ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup, int16 *colorTab, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
// Keep the tables in pointers here to avoid a dereference on each pixel
- const int16 *Cr_r_tab = lookup->_colorTab;
+ const int16 *Cr_r_tab = colorTab;
const int16 *Cr_g_tab = Cr_r_tab + 256;
const int16 *Cb_g_tab = Cr_g_tab + 256;
const int16 *Cb_b_tab = Cb_g_tab + 256;
- const uint32 *rgbToPix = lookup->_rgbToPix;
+ const uint32 *rgbToPix = lookup->getRGBToPix();
int quarterWidth = yWidth >> 2;
@@ -368,7 +366,7 @@ void convertYUV410ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup
#undef DO_INTERPOLATION
#undef DO_YUV410_PIXEL
-void convertYUV410ToRGB(Graphics::Surface *dst, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) {
+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->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4);
@@ -376,13 +374,13 @@ void convertYUV410ToRGB(Graphics::Surface *dst, const byte *ySrc, const byte *uS
assert((yWidth & 3) == 0);
assert((yHeight & 3) == 0);
- const YUVToRGBLookup *lookup = YUVToRGBMan.getLookup(dst->format);
+ const YUVToRGBLookup *lookup = getLookup(dst->format, scale);
// 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, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
+ convertYUV410ToRGB<uint16>((byte *)dst->pixels, dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
else
- convertYUV410ToRGB<uint32>((byte *)dst->pixels, dst->pitch, lookup, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch);
+ convertYUV410ToRGB<uint32>((byte *)dst->pixels, 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 73a2c69d7d..f785422c5a 100644
--- a/graphics/yuv_to_rgb.h
+++ b/graphics/yuv_to_rgb.h
@@ -32,57 +32,85 @@
#define GRAPHICS_YUV_TO_RGB_H
#include "common/scummsys.h"
+#include "common/singleton.h"
#include "graphics/surface.h"
namespace Graphics {
-/**
- * Convert a YUV444 image to an RGB surface
- *
- * @param dst the destination surface
- * @param ySrc the source of the y component
- * @param uSrc the source of the u component
- * @param vSrc the source of the v component
- * @param yWidth the width of the y surface
- * @param yHeight the height of the y surface
- * @param yPitch the pitch of the y surface
- * @param uvPitch the pitch of the u and v surfaces
- */
-void convertYUV444ToRGB(Graphics::Surface *dst, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch);
+class YUVToRGBLookup;
-/**
- * Convert a YUV420 image to an RGB surface
- *
- * @param dst the destination surface
- * @param ySrc the source of the y component
- * @param uSrc the source of the u component
- * @param vSrc the source of the v component
- * @param yWidth the width of the y surface (must be divisible by 2)
- * @param yHeight the height of the y surface (must be divisible by 2)
- * @param yPitch the pitch of the y surface
- * @param uvPitch the pitch of the u and v surfaces
- */
-void convertYUV420ToRGB(Graphics::Surface *dst, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch);
+class YUVToRGBManager : public Common::Singleton<YUVToRGBManager> {
+public:
+ /** The scale of the luminance values */
+ enum LuminanceScale {
+ kScaleFull, /** Luminance values range from [0, 255] */
+ kScaleITU /** Luminance values range from [16, 235], the range from ITU-R BT.601 */
+ };
-/**
- * Convert a YUV410 image to an RGB surface
- *
- * Since the chroma has a very low resolution in 410, we perform bilinear scaling
- * on the two chroma planes to produce the image. The chroma planes must have
- * at least one extra row that can be read from in order to produce a proper
- * image (filled with 0x80). This is required in order to speed up this function.
- *
- * @param dst the destination surface
- * @param ySrc the source of the y component
- * @param uSrc the source of the u component
- * @param vSrc the source of the v component
- * @param yWidth the width of the y surface (must be divisible by 4)
- * @param yHeight the height of the y surface (must be divisible by 4)
- * @param yPitch the pitch of the y surface
- * @param uvPitch the pitch of the u and v surfaces
- */
-void convertYUV410ToRGB(Graphics::Surface *dst, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch);
+ /**
+ * Convert a YUV444 image to an RGB surface
+ *
+ * @param dst the destination surface
+ * @param scale the scale of the luminance values
+ * @param ySrc the source of the y component
+ * @param uSrc the source of the u component
+ * @param vSrc the source of the v component
+ * @param yWidth the width of the y surface
+ * @param yHeight the height of the y surface
+ * @param yPitch the pitch of the y surface
+ * @param uvPitch the pitch of the u and v surfaces
+ */
+ void convert444(Graphics::Surface *dst, LuminanceScale scale, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch);
+
+ /**
+ * Convert a YUV420 image to an RGB surface
+ *
+ * @param dst the destination surface
+ * @param scale the scale of the luminance values
+ * @param ySrc the source of the y component
+ * @param uSrc the source of the u component
+ * @param vSrc the source of the v component
+ * @param yWidth the width of the y surface (must be divisible by 2)
+ * @param yHeight the height of the y surface (must be divisible by 2)
+ * @param yPitch the pitch of the y surface
+ * @param uvPitch the pitch of the u and v surfaces
+ */
+ void convert420(Graphics::Surface *dst, LuminanceScale scale, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch);
+
+ /**
+ * Convert a YUV410 image to an RGB surface
+ *
+ * Since the chroma has a very low resolution in 410, we perform bilinear scaling
+ * on the two chroma planes to produce the image. The chroma planes must have
+ * at least one extra row and one extra column that can be read from in order to
+ * produce a proper image. It is suggested that you fill these in with the previous
+ * row and column's data. This is required in order to speed up this function.
+ *
+ * @param dst the destination surface
+ * @param scale the scale of the luminance values
+ * @param ySrc the source of the y component
+ * @param uSrc the source of the u component
+ * @param vSrc the source of the v component
+ * @param yWidth the width of the y surface (must be divisible by 4)
+ * @param yHeight the height of the y surface (must be divisible by 4)
+ * @param yPitch the pitch of the y surface
+ * @param uvPitch the pitch of the u and v surfaces
+ */
+ void convert410(Graphics::Surface *dst, LuminanceScale scale, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch);
+
+private:
+ friend class Common::Singleton<SingletonBaseType>;
+ YUVToRGBManager();
+ ~YUVToRGBManager();
+
+ const YUVToRGBLookup *getLookup(Graphics::PixelFormat format, LuminanceScale scale);
+
+ YUVToRGBLookup *_lookup;
+ int16 _colorTab[4 * 256]; // 2048 bytes
+};
} // End of namespace Graphics
+#define YUVToRGBMan (::Graphics::YUVToRGBManager::instance())
+
#endif
diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp
index 9a85399ed1..8285aff7ca 100644
--- a/gui/ThemeParser.cpp
+++ b/gui/ThemeParser.cpp
@@ -548,11 +548,11 @@ bool ThemeParser::parseDrawStep(ParserNode *stepNode, Graphics::DrawStep *drawst
else
return parserError("'" + stepNode->values["fill"] + "' is not a valid fill mode for a shape.");
}
-
+
if (stepNode->values.contains("padding")) {
val = stepNode->values["padding"];
int pr, pt, pl, pb;
- if (parseIntegerKey(val, 4, &pl, &pt, &pr, &pb))
+ if (parseIntegerKey(val, 4, &pl, &pt, &pr, &pb))
drawstep->padding.left = pl,
drawstep->padding.top = pt,
drawstep->padding.right = pr,
diff --git a/gui/ThemeParser.h b/gui/ThemeParser.h
index 82f774b803..360e3da009 100644
--- a/gui/ThemeParser.h
+++ b/gui/ThemeParser.h
@@ -139,7 +139,7 @@ protected:
XML_PROP(height, false)
XML_PROP(xpos, false)
XML_PROP(ypos, false)
- XML_PROP(padding, false)
+ XML_PROP(padding, false)
XML_PROP(orientation, false)
XML_PROP(file, false)
KEY_END()
diff --git a/gui/credits.h b/gui/credits.h
index fdde2da821..37c5a7bd95 100644
--- a/gui/credits.h
+++ b/gui/credits.h
@@ -159,6 +159,9 @@ static const char *credits[] = {
"C1""Parallaction",
"C0""peres",
"",
+"C1""Pegasus",
+"C0""Matthew Hoops",
+"",
"C1""Queen",
"C0""David Eriksson",
"C2""(retired)",
@@ -234,6 +237,11 @@ static const char *credits[] = {
"C0""Filippos Karapetis",
"C0""Joost Peters",
"",
+"C1""Tony",
+"C0""Arnaud Boutonn\351",
+"C0""Paul Gilbert",
+"C0""Alyssa Milburn",
+"",
"C1""Toon",
"C0""Sylvain Dupont",
"",
@@ -249,6 +257,9 @@ static const char *credits[] = {
"C0""Gregory Montoir",
"C2""(retired)",
"",
+"C1""Wintermute",
+"C0""Einar Johan T. S\370m\345en",
+"",
"",
"C1""Backend Teams",
"C1""Android",
@@ -482,6 +493,7 @@ static const char *credits[] = {
"C1""German",
"C0""Simon Sawatzki",
"C0""Lothar Serra Mari",
+"C2""(retired)",
"",
"C1""Hungarian",
"C0""Alex Bevilacqua",
@@ -679,6 +691,8 @@ static const char *credits[] = {
"C2""For generously providing hosting for our buildbot, SVN repository, planet and doxygen sites as well as tons of HD space",
"C0""DOSBox Team",
"C2""For their awesome OPL2 and OPL3 emulator",
+"C0""Yusuke Kamiyamane",
+"C2""For contributing some GUI icons ",
"C0""Till Kresslein",
"C2""For design of modern ScummVM GUI",
"C0""Jezar",
@@ -695,8 +709,6 @@ static const char *credits[] = {
"C2""For additional work on the original MT-32 emulator",
"C0""James Woodcock",
"C2""Soundtrack enhancements",
-"C0""Some icons by Yusuke Kamiyamane",
-"C0""",
"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.",
@@ -717,7 +729,11 @@ static const char *credits[] = {
"C0""",
"C0""Neil Dodwell and David Dew from Creative Reality for providing the source of Dreamweb and for their tremendous support.",
"C0""",
-"C0""Janusz Wisniewski and Miroslaw Liminowicz from Laboratorium Komputerowe Avalon for providing full source code for Soltys and letting us to redistribute the game.",
+"C0""Janusz Wisniewski and Miroslaw Liminowicz from Laboratorium Komputerowe Avalon for providing full source code for Soltys and letting us redistribute the game.",
+"C0""",
+"C0""Jan Nedoma for providing the sources to the Wintermute-engine, and for his support while porting the engine to ScummVM.",
+"C0""",
+"C0""Bob Bell, Michel Kripalani, Tommy Yune, from Presto Studios for providing the source code of The Journeyman Project: Pegasus Prime.",
"C0""",
"",
};
diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index 26fafa5279..0f4867ced5 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -166,7 +166,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc)
} else {
warning("Plugin for target \"%s\" not found! Game specific settings might be missing", domain.c_str());
}
-
+
// GAME: Path to game data (r/o), extra data (r/o), and save data (r/w)
String gamePath(ConfMan.get("path", _domain));
String extraPath(ConfMan.get("extrapath", _domain));
diff --git a/gui/options.cpp b/gui/options.cpp
index 4fc37c93da..4868f1876d 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -992,7 +992,7 @@ void OptionsDialog::addEngineControls(GuiObject *boss, const Common::String &pre
ExtraGuiOptions::const_iterator iter;
for (iter = engineOptions.begin(); iter != engineOptions.end(); ++iter, ++i) {
Common::String id = Common::String::format("%d", i);
- _engineCheckboxes.push_back(new CheckboxWidget(boss,
+ _engineCheckboxes.push_back(new CheckboxWidget(boss,
prefix + "customOption" + id + "Checkbox", _(iter->label), _(iter->tooltip)));
}
}
diff --git a/gui/predictivedialog.cpp b/gui/predictivedialog.cpp
index b827d49416..ed18847a40 100644
--- a/gui/predictivedialog.cpp
+++ b/gui/predictivedialog.cpp
@@ -71,7 +71,7 @@ PredictiveDialog::PredictiveDialog() : Dialog("Predictive") {
_btns = (ButtonWidget **)calloc(1, sizeof(ButtonWidget *) * 16);
- _btns[kCancelAct] = new ButtonWidget(this, "Predictive.Cancel", _("Cancel") , 0, kCancelCmd);
+ _btns[kCancelAct] = new ButtonWidget(this, "Predictive.Cancel", _("Cancel") , 0, kCancelCmd);
_btns[kOkAct] = new ButtonWidget(this, "Predictive.OK", _("Ok") , 0, kOkCmd);
_btns[kBtn1Act] = new ButtonWidget(this, "Predictive.Button1", "1 `-.&" , 0, kBut1Cmd);
_btns[kBtn2Act] = new ButtonWidget(this, "Predictive.Button2", "2 abc" , 0, kBut2Cmd);
@@ -84,10 +84,10 @@ PredictiveDialog::PredictiveDialog() : Dialog("Predictive") {
_btns[kBtn9Act] = new ButtonWidget(this, "Predictive.Button9", "9 wxyz" , 0, kBut9Cmd);
_btns[kBtn0Act] = new ButtonWidget(this, "Predictive.Button0", "0" , 0, kBut0Cmd);
// I18N: You must leave "#" as is, only word 'next' is translatable
- _btns[kNextAct] = new ButtonWidget(this, "Predictive.Next", _("# next") , 0, kNextCmd);
+ _btns[kNextAct] = new ButtonWidget(this, "Predictive.Next", _("# next") , 0, kNextCmd);
_btns[kAddAct] = new ButtonWidget(this, "Predictive.Add", _("add") , 0, kAddCmd);
_btns[kAddAct]->setEnabled(false);
-
+
#ifndef DISABLE_FANCY_THEMES
_btns[kDelAct] = new PicButtonWidget(this, "Predictive.Delete", _("Delete char"), kDelCmd);
((PicButtonWidget *)_btns[kDelAct])->useThemeTransparency(true);
@@ -214,7 +214,7 @@ void PredictiveDialog::handleKeyDown(Common::KeyState state) {
_navigationwithkeys = true;
if (_lastbutton == kBtn1Act || _lastbutton == kBtn4Act || _lastbutton == kBtn7Act)
_currBtn = ButtonId(_lastbutton + 2);
- else if (_lastbutton == kDelAct)
+ else if (_lastbutton == kDelAct)
_currBtn = kBtn1Act;
else if (_lastbutton == kModeAct)
_currBtn = kNextAct;
@@ -227,7 +227,7 @@ void PredictiveDialog::handleKeyDown(Common::KeyState state) {
else
_currBtn = ButtonId(_lastbutton - 1);
-
+
if (_mode != kModeAbc && _lastbutton == kCancelAct)
_currBtn = kOkAct;
@@ -237,7 +237,7 @@ void PredictiveDialog::handleKeyDown(Common::KeyState state) {
_navigationwithkeys = true;
if (_lastbutton == kBtn3Act || _lastbutton == kBtn6Act || _lastbutton == kBtn9Act || _lastbutton == kOkAct)
_currBtn = ButtonId(_lastbutton - 2);
- else if (_lastbutton == kDelAct)
+ else if (_lastbutton == kDelAct)
_currBtn = kBtn3Act;
else if (_lastbutton == kBtn0Act)
_currBtn = kNextAct;
@@ -249,7 +249,7 @@ void PredictiveDialog::handleKeyDown(Common::KeyState state) {
_currBtn = kAddAct;
else
_currBtn = ButtonId(_lastbutton + 1);
-
+
if (_mode != kModeAbc && _lastbutton == kOkAct)
_currBtn = kCancelAct;
_needRefresh = true;
@@ -260,7 +260,7 @@ void PredictiveDialog::handleKeyDown(Common::KeyState state) {
_currBtn = kDelAct;
else if (_lastbutton == kDelAct)
_currBtn = kOkAct;
- else if (_lastbutton == kModeAct)
+ else if (_lastbutton == kModeAct)
_currBtn = kBtn7Act;
else if (_lastbutton == kBtn0Act)
_currBtn = kBtn8Act;
@@ -286,7 +286,7 @@ void PredictiveDialog::handleKeyDown(Common::KeyState state) {
_currBtn = kBtn0Act;
else if (_lastbutton == kBtn9Act)
_currBtn = kNextAct;
- else if (_lastbutton == kModeAct)
+ else if (_lastbutton == kModeAct)
_currBtn = kAddAct;
else if (_lastbutton == kBtn0Act)
_currBtn = kCancelAct;
diff --git a/gui/saveload-dialog.cpp b/gui/saveload-dialog.cpp
index 850dfcc78f..c7dd62b6c6 100644
--- a/gui/saveload-dialog.cpp
+++ b/gui/saveload-dialog.cpp
@@ -35,6 +35,14 @@ namespace GUI {
#ifndef DISABLE_SAVELOADCHOOSER_GRID
SaveLoadChooserType getRequestedSaveLoadDialog(const MetaEngine &metaEngine) {
const Common::String &userConfig = ConfMan.get("gui_saveload_chooser", Common::ConfigManager::kApplicationDomain);
+
+ // Check (and update if necessary) the theme config here. This catches
+ // resolution changes, which happened after the GUI was closed. This
+ // should assure that the correct GUI width/height are returned below and
+ // prevent the logic from picking the grid dialog, even though it is not
+ // possible to use it.
+ g_gui.checkScreenChange();
+
if (g_gui.getWidth() >= 640 && g_gui.getHeight() >= 400
&& metaEngine.hasFeature(MetaEngine::kSavesSupportMetaInfo)
&& metaEngine.hasFeature(MetaEngine::kSavesSupportThumbnail)
@@ -422,7 +430,28 @@ void SaveLoadChooserSimple::updateSelection(bool redraw) {
}
}
+void SaveLoadChooserSimple::open() {
+ SaveLoadChooserDialog::open();
+
+ // Scroll the list to the last used entry.
+ _list->scrollTo(ConfMan.getInt("gui_saveload_last_pos"));
+}
+
void SaveLoadChooserSimple::close() {
+ // Save the current scroll position/used entry.
+ const int result = getResult();
+ if (result >= 0) {
+ ConfMan.setInt("gui_saveload_last_pos", result);
+ } else {
+ // Use the current scroll position here.
+ // TODO: This means we canceled the dialog (or switch to the grid). Do
+ // we want to save this position here? Does the user want that?
+ // TODO: Do we want to save the current scroll position or the
+ // currently selected item here? The scroll position is what the user
+ // currently sees and seems to make more sense.
+ ConfMan.setInt("gui_saveload_last_pos", _list->getCurrentScrollPos());
+ }
+
_metaEngine = 0;
_target.clear();
_saveList.clear();
@@ -590,10 +619,29 @@ void SaveLoadChooserGrid::handleMouseWheel(int x, int y, int direction) {
void SaveLoadChooserGrid::open() {
SaveLoadChooserDialog::open();
- _curPage = 0;
_saveList = _metaEngine->listSaves(_target.c_str());
_resultString.clear();
+ // Load information to restore the last page the user had open.
+ assert(_entriesPerPage != 0);
+ const uint lastPos = ConfMan.getInt("gui_saveload_last_pos");
+ const uint listSize = _saveList.size();
+ uint bestMatch = 0;
+ uint diff = 0xFFFFFFFF;
+
+ // We look for the nearest available slot, since a slot might be missing
+ // due to the user deleting it via the list based chooser, by deleting
+ // it by hand, etc.
+ for (uint i = 0; i < listSize; ++i) {
+ uint curDiff = ABS(_saveList[i].getSaveSlot() - (int)lastPos);
+ if (curDiff < diff) {
+ diff = curDiff;
+ bestMatch = i;
+ }
+ }
+
+ _curPage = bestMatch / _entriesPerPage;
+
// Determine the next free save slot for save mode
if (_saveMode) {
int lastSlot = -1;
@@ -703,7 +751,7 @@ void SaveLoadChooserGrid::reflowLayout() {
if (!_saveMode) {
buttonCmd += 1;
}
-
+
PicButtonWidget *button = new PicButtonWidget(container, dstX, dstY, buttonWidth, buttonHeight, 0, buttonCmd);
dstY += buttonHeight;
@@ -718,6 +766,24 @@ void SaveLoadChooserGrid::reflowLayout() {
}
void SaveLoadChooserGrid::close() {
+ // Save the current page.
+ const int result = getResult();
+ if (result >= 0 && result != _nextFreeSaveSlot) {
+ // If the user selected a slot we use that one. We ignore new slots
+ // here, since otherwise the dialog would reset to page 0 when the
+ // user cancels the savename dialog.
+ ConfMan.setInt("gui_saveload_last_pos", result);
+ } else {
+ // Otherwise save the first entry on the current page.
+ // This is less precise than the solution above, since the number of
+ // entries shown differs between save and load version of the dialog,
+ // thus it might wrap to a different page than expected.
+ // Similar things happen on resolution changes.
+ // TODO: Should we ignore this here? Is the user likely to be
+ // interested in having this page restored when he canceled?
+ ConfMan.setInt("gui_saveload_last_pos", !_saveList.empty() ? _saveList[_curPage * _entriesPerPage].getSaveSlot() : 0);
+ }
+
SaveLoadChooserDialog::close();
hideButtons();
}
@@ -737,6 +803,12 @@ int SaveLoadChooserGrid::runIntern() {
slot = runModal();
} while (_saveMode && slot >= 0 && !selectDescription());
+ // Special case for new save games. We need to handle this here, since
+ // we cannot handle it in close() without problems.
+ if (slot == _nextFreeSaveSlot) {
+ ConfMan.setInt("gui_saveload_last_pos", slot);
+ }
+
return slot;
}
@@ -826,7 +898,7 @@ void SaveLoadChooserGrid::updateSaves() {
}
}
- const uint numPages = (_entriesPerPage != 0) ? (_saveList.size() / _entriesPerPage + 1) : 1;
+ const uint numPages = (_entriesPerPage != 0 && !_saveList.empty()) ? ((_saveList.size() + _entriesPerPage - 1) / _entriesPerPage) : 1;
_pageDisplay->setLabel(Common::String::format("%u/%u", _curPage + 1, numPages));
if (_curPage > 0)
diff --git a/gui/saveload-dialog.h b/gui/saveload-dialog.h
index 9d0350d69d..6f7d95f73f 100644
--- a/gui/saveload-dialog.h
+++ b/gui/saveload-dialog.h
@@ -103,6 +103,7 @@ public:
virtual SaveLoadChooserType getType() const { return kSaveLoadDialogList; }
#endif // !DISABLE_SAVELOADCHOOSER_GRID
+ virtual void open();
virtual void close();
private:
virtual int runIntern();
diff --git a/gui/themes/translations.dat b/gui/themes/translations.dat
index 1c3abf84a8..7b51dec980 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 9046bcc9c1..4ffb63e945 100644
--- a/gui/widget.cpp
+++ b/gui/widget.cpp
@@ -366,7 +366,7 @@ void ButtonWidget::startAnimatePressedState() {
}
void ButtonWidget::wantTickle(bool tickled) {
- if (tickled)
+ if (tickled)
((GUI::Dialog *)_boss)->setTickleWidget(this);
else
((GUI::Dialog *)_boss)->unSetTickleWidget();
@@ -376,7 +376,7 @@ void ButtonWidget::wantTickle(bool tickled) {
PicButtonWidget::PicButtonWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip, uint32 cmd, uint8 hotkey)
: ButtonWidget(boss, x, y, w, h, "", tooltip, cmd, hotkey),
- _gfx(new Graphics::Surface()), _alpha(256), _transparency(false) {
+ _gfx(), _alpha(256), _transparency(false) {
setFlags(WIDGET_ENABLED/* | WIDGET_BORDER*/ | WIDGET_CLEARBG);
_type = kButtonWidget;
@@ -384,18 +384,17 @@ PicButtonWidget::PicButtonWidget(GuiObject *boss, int x, int y, int w, int h, co
PicButtonWidget::PicButtonWidget(GuiObject *boss, const Common::String &name, const char *tooltip, uint32 cmd, uint8 hotkey)
: ButtonWidget(boss, name, "", tooltip, cmd, hotkey),
- _gfx(new Graphics::Surface()), _alpha(256), _transparency(false) {
+ _gfx(), _alpha(256), _transparency(false) {
setFlags(WIDGET_ENABLED/* | WIDGET_BORDER*/ | WIDGET_CLEARBG);
_type = kButtonWidget;
}
PicButtonWidget::~PicButtonWidget() {
- _gfx->free();
- delete _gfx;
+ _gfx.free();
}
void PicButtonWidget::setGfx(const Graphics::Surface *gfx) {
- _gfx->free();
+ _gfx.free();
if (!gfx || !gfx->pixels)
return;
@@ -411,7 +410,7 @@ void PicButtonWidget::setGfx(const Graphics::Surface *gfx) {
return;
}
- _gfx->copyFrom(*gfx);
+ _gfx.copyFrom(*gfx);
}
void PicButtonWidget::setGfx(int w, int h, int r, int g, int b) {
@@ -422,29 +421,26 @@ void PicButtonWidget::setGfx(int w, int h, int r, int g, int b) {
const Graphics::PixelFormat &requiredFormat = g_gui.theme()->getPixelFormat();
- _gfx->free();
- _gfx->create(w, h, requiredFormat);
- _gfx->fillRect(Common::Rect(0, 0, w, h), _gfx->format.RGBToColor(r, g, b));
+ _gfx.free();
+ _gfx.create(w, h, requiredFormat);
+ _gfx.fillRect(Common::Rect(0, 0, w, h), _gfx.format.RGBToColor(r, g, b));
}
void PicButtonWidget::drawWidget() {
g_gui.theme()->drawButton(Common::Rect(_x, _y, _x+_w, _y+_h), "", _state, getFlags());
- if (_gfx->pixels) {
+ if (_gfx.pixels) {
// Check whether the set up surface needs to be converted to the GUI
// color format.
const Graphics::PixelFormat &requiredFormat = g_gui.theme()->getPixelFormat();
- if (_gfx->format != requiredFormat) {
- Graphics::Surface *converted = _gfx->convertTo(requiredFormat);
- _gfx->free();
- delete _gfx;
- _gfx = converted;
+ if (_gfx.format != requiredFormat) {
+ _gfx.convertToInPlace(requiredFormat);
}
- const int x = _x + (_w - _gfx->w) / 2;
- const int y = _y + (_h - _gfx->h) / 2;
+ const int x = _x + (_w - _gfx.w) / 2;
+ const int y = _y + (_h - _gfx.h) / 2;
- g_gui.theme()->drawSurface(Common::Rect(x, y, x + _gfx->w, y + _gfx->h), *_gfx, _state, _alpha, _transparency);
+ g_gui.theme()->drawSurface(Common::Rect(x, y, x + _gfx.w, y + _gfx.h), _gfx, _state, _alpha, _transparency);
}
}
@@ -632,24 +628,23 @@ int SliderWidget::posToValue(int pos) {
#pragma mark -
GraphicsWidget::GraphicsWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip)
- : Widget(boss, x, y, w, h, tooltip), _gfx(new Graphics::Surface()), _alpha(256), _transparency(false) {
+ : Widget(boss, x, y, w, h, tooltip), _gfx(), _alpha(256), _transparency(false) {
setFlags(WIDGET_ENABLED | WIDGET_CLEARBG);
_type = kGraphicsWidget;
}
GraphicsWidget::GraphicsWidget(GuiObject *boss, const Common::String &name, const char *tooltip)
- : Widget(boss, name, tooltip), _gfx(new Graphics::Surface()), _alpha(256), _transparency(false) {
+ : Widget(boss, name, tooltip), _gfx(), _alpha(256), _transparency(false) {
setFlags(WIDGET_ENABLED | WIDGET_CLEARBG);
_type = kGraphicsWidget;
}
GraphicsWidget::~GraphicsWidget() {
- _gfx->free();
- delete _gfx;
+ _gfx.free();
}
void GraphicsWidget::setGfx(const Graphics::Surface *gfx) {
- _gfx->free();
+ _gfx.free();
if (!gfx || !gfx->pixels)
return;
@@ -664,7 +659,7 @@ void GraphicsWidget::setGfx(const Graphics::Surface *gfx) {
return;
}
- _gfx->copyFrom(*gfx);
+ _gfx.copyFrom(*gfx);
}
void GraphicsWidget::setGfx(int w, int h, int r, int g, int b) {
@@ -675,27 +670,24 @@ void GraphicsWidget::setGfx(int w, int h, int r, int g, int b) {
const Graphics::PixelFormat &requiredFormat = g_gui.theme()->getPixelFormat();
- _gfx->free();
- _gfx->create(w, h, requiredFormat);
- _gfx->fillRect(Common::Rect(0, 0, w, h), _gfx->format.RGBToColor(r, g, b));
+ _gfx.free();
+ _gfx.create(w, h, requiredFormat);
+ _gfx.fillRect(Common::Rect(0, 0, w, h), _gfx.format.RGBToColor(r, g, b));
}
void GraphicsWidget::drawWidget() {
- if (_gfx->pixels) {
+ if (_gfx.pixels) {
// Check whether the set up surface needs to be converted to the GUI
// color format.
const Graphics::PixelFormat &requiredFormat = g_gui.theme()->getPixelFormat();
- if (_gfx->format != requiredFormat) {
- Graphics::Surface *converted = _gfx->convertTo(requiredFormat);
- _gfx->free();
- delete _gfx;
- _gfx = converted;
+ if (_gfx.format != requiredFormat) {
+ _gfx.convertToInPlace(requiredFormat);
}
- const int x = _x + (_w - _gfx->w) / 2;
- const int y = _y + (_h - _gfx->h) / 2;
+ const int x = _x + (_w - _gfx.w) / 2;
+ const int y = _y + (_h - _gfx.h) / 2;
- g_gui.theme()->drawSurface(Common::Rect(x, y, x + _gfx->w, y + _gfx->h), *_gfx, _state, _alpha, _transparency);
+ g_gui.theme()->drawSurface(Common::Rect(x, y, x + _gfx.w, y + _gfx.h), _gfx, _state, _alpha, _transparency);
}
}
diff --git a/gui/widget.h b/gui/widget.h
index 6f710f302f..e3f712564f 100644
--- a/gui/widget.h
+++ b/gui/widget.h
@@ -230,7 +230,7 @@ public:
protected:
void drawWidget();
- Graphics::Surface *_gfx;
+ Graphics::Surface _gfx;
int _alpha;
bool _transparency;
};
@@ -358,7 +358,7 @@ public:
protected:
void drawWidget();
- Graphics::Surface *_gfx;
+ Graphics::Surface _gfx;
int _alpha;
bool _transparency;
};
diff --git a/gui/widgets/editable.h b/gui/widgets/editable.h
index 7e453c1204..4a18d5e689 100644
--- a/gui/widgets/editable.h
+++ b/gui/widgets/editable.h
@@ -77,10 +77,10 @@ public:
protected:
virtual void startEditMode() = 0;
virtual void endEditMode() = 0;
- virtual void abortEditMode() = 0;
+ virtual void abortEditMode() = 0;
virtual Common::Rect getEditRect() const = 0;
virtual int getCaretOffset() const;
- void drawCaret(bool erase);
+ void drawCaret(bool erase);
bool adjustOffset();
void makeCaretVisible();
diff --git a/gui/widgets/list.h b/gui/widgets/list.h
index 41fae37a71..47613b79f3 100644
--- a/gui/widgets/list.h
+++ b/gui/widgets/list.h
@@ -105,6 +105,7 @@ public:
void scrollTo(int item);
void scrollToEnd();
+ int getCurrentScrollPos() const { return _currentPos; }
void enableQuickSelect(bool enable) { _quickSelect = enable; }
String getQuickSelectString() const { return _quickSelectStr; }
diff --git a/po/ru_RU.po b/po/ru_RU.po
index 3a80d9fd7b..2774dc8c74 100644
--- a/po/ru_RU.po
+++ b/po/ru_RU.po
@@ -927,11 +927,11 @@ msgstr ""
#: gui/saveload-dialog.cpp:158
msgid "List view"
-msgstr ""
+msgstr "Вид списка"
#: gui/saveload-dialog.cpp:159
msgid "Grid view"
-msgstr ""
+msgstr "Вид сетки"
#: gui/saveload-dialog.cpp:202 gui/saveload-dialog.cpp:350
msgid "No date saved"
@@ -971,31 +971,28 @@ msgstr "Сохранение без имени"
#: gui/saveload-dialog.cpp:517
msgid "Next"
-msgstr ""
+msgstr "Следующий"
#: gui/saveload-dialog.cpp:520
msgid "Prev"
-msgstr ""
+msgstr "Предыдущий"
#: gui/saveload-dialog.cpp:684
-#, fuzzy
msgid "New Save"
-msgstr "Сохранить"
+msgstr "Новое сохранение"
#: gui/saveload-dialog.cpp:684
-#, fuzzy
msgid "Create a new save game"
-msgstr "Не удалось сохранить игру"
+msgstr "Создать новую запись игры"
#: gui/saveload-dialog.cpp:789
-#, fuzzy
msgid "Name: "
-msgstr "Название:"
+msgstr "Название: "
#: gui/saveload-dialog.cpp:861
#, c-format
msgid "Enter a description for slot %d:"
-msgstr ""
+msgstr "Введите описание слота %d:"
#: gui/themebrowser.cpp:44
msgid "Select a Theme"
@@ -2250,12 +2247,11 @@ msgstr ""
#: engines/queen/queen.cpp:59
msgid "Alternative intro"
-msgstr ""
+msgstr "Альтернативное вступление"
#: engines/queen/queen.cpp:60
-#, fuzzy
msgid "Use an alternative game intro (CD version only)"
-msgstr "Использовать вступление с гибких дисков (только для CD версии игры)"
+msgstr "Использовать альтернативное вступление (только для CD версии игры)"
#: engines/sky/compact.cpp:130
msgid ""
@@ -2357,12 +2353,15 @@ msgstr "Показывает названия объектов пр инаведении курсора мыши"
msgid ""
"You're missing the 'teenagent.dat' file. Get it from the ScummVM website"
msgstr ""
+"У вас отсутствует файл 'teenagent.dat'. Скачайте его с веб-сайта ScummVM"
#: engines/teenagent/resources.cpp:89
msgid ""
"The teenagent.dat file is compressed and zlib hasn't been included in this "
"executable. Please decompress it"
msgstr ""
+"Файл teenagent.dat сжат, но zlib не включено в эту программу. Пожалуйста,"
+"распакуйте его"
#: engines/parallaction/saveload.cpp:133
#, c-format
diff --git a/po/uk_UA.po b/po/uk_UA.po
index be7935518b..ea71a51d52 100644
--- a/po/uk_UA.po
+++ b/po/uk_UA.po
@@ -926,11 +926,11 @@ msgstr ""
#: gui/saveload-dialog.cpp:158
msgid "List view"
-msgstr ""
+msgstr "Вигляд списку"
#: gui/saveload-dialog.cpp:159
msgid "Grid view"
-msgstr ""
+msgstr "Вигляд сітки"
#: gui/saveload-dialog.cpp:202 gui/saveload-dialog.cpp:350
msgid "No date saved"
@@ -970,31 +970,28 @@ msgstr "Збереження без імені"
#: gui/saveload-dialog.cpp:517
msgid "Next"
-msgstr ""
+msgstr "Насутпний"
#: gui/saveload-dialog.cpp:520
msgid "Prev"
-msgstr ""
+msgstr "Попередній"
#: gui/saveload-dialog.cpp:684
-#, fuzzy
msgid "New Save"
-msgstr "Записати"
+msgstr "Нове збереження"
#: gui/saveload-dialog.cpp:684
-#, fuzzy
msgid "Create a new save game"
-msgstr "Не вдалося записати гру"
+msgstr "Створити новий запис гри"
#: gui/saveload-dialog.cpp:789
-#, fuzzy
msgid "Name: "
-msgstr "Назва:"
+msgstr "Назва: "
#: gui/saveload-dialog.cpp:861
#, c-format
msgid "Enter a description for slot %d:"
-msgstr ""
+msgstr "Введіть опис для слоту %d:"
#: gui/themebrowser.cpp:44
msgid "Select a Theme"
@@ -1339,6 +1336,8 @@ msgid ""
"Use an IBM Music Feature card or a Yamaha FB-01 FM synth module for MIDI "
"output"
msgstr ""
+"Використовувати дляв виводу MIDI режим карти IBM Feature або FM "
+"сінтез Yamaha FB-01"
#: engines/sci/detection.cpp:411
msgid "Use CD audio"
@@ -2167,11 +2166,11 @@ msgstr "Увімкнути плаваючі курсори"
#. I18N: HP stands for Hit Points
#: engines/kyra/detection.cpp:127
msgid "HP bar graphs"
-msgstr ""
+msgstr "Стовпчики здоров'я"
#: engines/kyra/detection.cpp:128
msgid "Enable hit point bar graphs"
-msgstr ""
+msgstr "Уиімкнути графічні стовпички здоров'я"
#: engines/kyra/lol.cpp:478
msgid "Attack 1"
@@ -2237,12 +2236,11 @@ msgstr ""
#: engines/queen/queen.cpp:59
msgid "Alternative intro"
-msgstr ""
+msgstr "Алтернативний вступ"
#: engines/queen/queen.cpp:60
-#, fuzzy
msgid "Use an alternative game intro (CD version only)"
-msgstr "Використовувати дискетні версії введення (тільки CD версія)"
+msgstr "Використовувати альтернативний вступ гри (тільки CD версія)"
#: engines/sky/compact.cpp:130
msgid ""
@@ -2341,12 +2339,15 @@ msgstr "Показувати мітки для об'єктів при наведенні миші"
msgid ""
"You're missing the 'teenagent.dat' file. Get it from the ScummVM website"
msgstr ""
+"У вас відстуній файл 'teenagent.dat'. Візьміть його на вебсайті ScummVM"
#: engines/teenagent/resources.cpp:89
msgid ""
"The teenagent.dat file is compressed and zlib hasn't been included in this "
"executable. Please decompress it"
msgstr ""
+"Файл teenagent.dat запаковано, але zlib не було включено в цю программу."
+"Будь-ласка розпакуйте його"
#: engines/parallaction/saveload.cpp:133
#, c-format
diff --git a/ports.mk b/ports.mk
index ed6781a1a9..4d7d6f6e60 100644
--- a/ports.mk
+++ b/ports.mk
@@ -224,9 +224,6 @@ win32dist: $(EXECUTABLE)
mkdir -p $(WIN32PATH)/doc/se
$(STRIP) $(EXECUTABLE) -o $(WIN32PATH)/$(EXECUTABLE)
cp $(DIST_FILES_THEMES) $(WIN32PATH)
-ifdef DIST_FILES_ENGINEDATA
- cp $(DIST_FILES_ENGINEDATA) $(WIN32PATH)
-endif
cp $(srcdir)/AUTHORS $(WIN32PATH)/AUTHORS.txt
cp $(srcdir)/COPYING $(WIN32PATH)/COPYING.txt
cp $(srcdir)/COPYING.BSD $(WIN32PATH)/COPYING.BSD.txt
diff --git a/test/common/memorywritestream.h b/test/common/memorywritestream.h
new file mode 100644
index 0000000000..43a137a9f3
--- /dev/null
+++ b/test/common/memorywritestream.h
@@ -0,0 +1,31 @@
+#include <cxxtest/TestSuite.h>
+
+#include "common/memstream.h"
+
+class MemoryWriteStreamTestSuite : public CxxTest::TestSuite {
+ public:
+ void test_err() {
+ byte temp = 0;
+
+ Common::MemoryWriteStream stream(&temp, 0);
+ TS_ASSERT(!stream.err());
+
+ // Make sure the error indicator gets set
+ stream.write(&temp, 1);
+ TS_ASSERT(stream.err());
+
+ // Test whether the error indicator can be cleared
+ stream.clearErr();
+ TS_ASSERT(!stream.err());
+ }
+
+ void test_write() {
+ byte buffer[7] = {};
+ Common::MemoryWriteStream stream(buffer, sizeof(buffer));
+
+ const byte data[7] = { 7, 4, 3, 0, 10, 12, 1 };
+ stream.write(data, sizeof(data));
+ TS_ASSERT(memcmp(buffer, data, sizeof(data)) == 0);
+ TS_ASSERT(!stream.err());
+ }
+};
diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp
index 0d51f5b130..6062049b72 100644
--- a/video/avi_decoder.cpp
+++ b/video/avi_decoder.cpp
@@ -379,7 +379,7 @@ void AVIDecoder::readNextPacket() {
}
}
-AVIDecoder::AVIVideoTrack::AVIVideoTrack(int frameCount, const AVIStreamHeader &streamHeader, const BitmapInfoHeader &bitmapInfoHeader)
+AVIDecoder::AVIVideoTrack::AVIVideoTrack(int frameCount, const AVIStreamHeader &streamHeader, const BitmapInfoHeader &bitmapInfoHeader)
: _frameCount(frameCount), _vidsHeader(streamHeader), _bmInfo(bitmapInfoHeader) {
memset(_palette, 0, sizeof(_palette));
_videoCodec = createCodec();
diff --git a/video/avi_decoder.h b/video/avi_decoder.h
index a3a262db36..3bdc0561d1 100644
--- a/video/avi_decoder.h
+++ b/video/avi_decoder.h
@@ -214,7 +214,7 @@ private:
};
OldIndex _ixInfo;
- AVIHeader _header;
+ AVIHeader _header;
Common::SeekableReadStream *_fileStream;
bool _decodedHeader;
diff --git a/video/bink_decoder.cpp b/video/bink_decoder.cpp
index 620316806f..1ece22c963 100644
--- a/video/bink_decoder.cpp
+++ b/video/bink_decoder.cpp
@@ -236,7 +236,7 @@ BinkDecoder::AudioInfo::~AudioInfo() {
BinkDecoder::BinkVideoTrack::BinkVideoTrack(uint32 width, uint32 height, const Graphics::PixelFormat &format, uint32 frameCount, const Common::Rational &frameRate, bool swapPlanes, bool hasAlpha, uint32 id) :
_frameCount(frameCount), _frameRate(frameRate), _swapPlanes(swapPlanes), _hasAlpha(hasAlpha), _id(id) {
- _curFrame = -1;
+ _curFrame = -1;
for (int i = 0; i < 16; i++)
_huffman[i] = 0;
@@ -260,7 +260,23 @@ BinkDecoder::BinkVideoTrack::BinkVideoTrack(uint32 width, uint32 height, const G
_colHighHuffman[i].symbols[j] = j;
}
- _surface.create(width, height, format);
+ // Make the surface even-sized:
+ _surfaceHeight = height;
+ _surfaceWidth = width;
+
+ if (height & 1) {
+ _surfaceHeight++;
+ }
+ if (width & 1) {
+ _surfaceWidth++;
+ }
+
+ _surface.create(_surfaceWidth, _surfaceHeight, format);
+ // Since we over-allocate to make surfaces even-sized
+ // we need to set the actual VIDEO size back into the
+ // surface.
+ _surface.h = height;
+ _surface.w = width;
// Give the planes a bit extra space
width = _surface.w + 32;
@@ -329,9 +345,11 @@ void BinkDecoder::BinkVideoTrack::decodePacket(VideoFrame &frame) {
// Convert the YUV data we have to our format
// We're ignoring alpha for now
+ // The width used here is the surface-width, and not the video-width
+ // to allow for odd-sized videos.
assert(_curPlanes[0] && _curPlanes[1] && _curPlanes[2]);
- Graphics::convertYUV420ToRGB(&_surface, _curPlanes[0], _curPlanes[1], _curPlanes[2],
- _surface.w, _surface.h, _surface.w, _surface.w >> 1);
+ YUVToRGBMan.convert420(&_surface, Graphics::YUVToRGBManager::kScaleITU, _curPlanes[0], _curPlanes[1], _curPlanes[2],
+ _surfaceWidth, _surfaceHeight, _surfaceWidth, _surfaceWidth >> 1);
// And swap the planes with the reference planes
for (int i = 0; i < 4; i++)
diff --git a/video/bink_decoder.h b/video/bink_decoder.h
index 150e91aab7..27d3aa3691 100644
--- a/video/bink_decoder.h
+++ b/video/bink_decoder.h
@@ -231,6 +231,8 @@ private:
int _frameCount;
Graphics::Surface _surface;
+ int _surfaceWidth; ///< The actual surface width
+ int _surfaceHeight; ///< The actual surface height
uint32 _id; ///< The BIK FourCC.
diff --git a/video/codecs/svq1.cpp b/video/codecs/svq1.cpp
index 14452ab15b..56b376f590 100644
--- a/video/codecs/svq1.cpp
+++ b/video/codecs/svq1.cpp
@@ -180,28 +180,29 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st
frameData.skip(8);
}
- int yWidth = ALIGN(_frameWidth, 16);
- int yHeight = ALIGN(_frameHeight, 16);
- int uvWidth = ALIGN(yWidth / 4, 16);
- int uvHeight = ALIGN(yHeight / 4, 16);
+ uint yWidth = ALIGN(_frameWidth, 16);
+ uint yHeight = ALIGN(_frameHeight, 16);
+ uint uvWidth = ALIGN(yWidth / 4, 16);
+ uint uvHeight = ALIGN(yHeight / 4, 16);
+ uint uvPitch = uvWidth + 4; // we need at least one extra column and pitch must be divisible by 4
byte *current[3];
// Decode Y, U and V component planes
for (int i = 0; i < 3; i++) {
- int width, height;
+ uint width, height, pitch;
if (i == 0) {
width = yWidth;
height = yHeight;
+ pitch = width;
current[i] = new byte[width * height];
} else {
width = uvWidth;
height = uvHeight;
+ pitch = uvPitch;
- // Add an extra row's worth of data to not go out-of-bounds in the
- // color conversion. Then fill that with "empty" data.
- current[i] = new byte[width * (height + 1)];
- memset(current[i] + width * height, 0x80, width);
+ // Add an extra row here. See below for more information.
+ current[i] = new byte[pitch * (height + 1)];
}
if (frameType == 0) { // I Frame
@@ -209,12 +210,12 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st
byte *currentP = current[i];
for (uint16 y = 0; y < height; y += 16) {
for (uint16 x = 0; x < width; x += 16) {
- if (!svq1DecodeBlockIntra(&frameData, &currentP[x], width)) {
+ if (!svq1DecodeBlockIntra(&frameData, &currentP[x], pitch)) {
warning("svq1DecodeBlockIntra decode failure");
return _surface;
}
}
- currentP += 16 * width;
+ currentP += 16 * pitch;
}
} else {
// Delta frame (P or B)
@@ -233,7 +234,7 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st
byte *currentP = current[i];
for (uint16 y = 0; y < height; y += 16) {
for (uint16 x = 0; x < width; x += 16) {
- if (!svq1DecodeDeltaBlock(&frameData, &currentP[x], previous, width, pmv, x, y)) {
+ if (!svq1DecodeDeltaBlock(&frameData, &currentP[x], previous, pitch, pmv, x, y)) {
warning("svq1DecodeDeltaBlock decode failure");
return _surface;
}
@@ -241,7 +242,7 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st
pmv[0].x = pmv[0].y = 0;
- currentP += 16 * width;
+ currentP += 16 * pitch;
}
delete[] pmv;
@@ -256,7 +257,21 @@ const Graphics::Surface *SVQ1Decoder::decodeImage(Common::SeekableReadStream *st
_surface->h = _height;
}
- convertYUV410ToRGB(_surface, current[0], current[1], current[2], yWidth, yHeight, yWidth, uvWidth);
+ // We need to massage the chrominance data a bit to be able to be used by the converter
+ // Since the thing peeks at values one column and one row beyond the data, we need to fill it in
+
+ // First, fill in the column-after-last with the last column's value
+ for (uint i = 0; i < uvHeight; i++) {
+ current[1][i * uvPitch + uvWidth] = current[1][i * uvPitch + uvWidth - 1];
+ current[2][i * uvPitch + uvWidth] = current[2][i * uvPitch + uvWidth - 1];
+ }
+
+ // Then, copy the last row to the one after the last row
+ memcpy(current[1] + uvHeight * uvPitch, current[1] + (uvHeight - 1) * uvPitch, uvWidth + 1);
+ memcpy(current[2] + uvHeight * uvPitch, current[2] + (uvHeight - 1) * uvPitch, uvWidth + 1);
+
+ // Finally, actually do the conversion ;)
+ YUVToRGBMan.convert410(_surface, Graphics::YUVToRGBManager::kScaleFull, current[0], current[1], current[2], yWidth, yHeight, yWidth, uvPitch);
// Store the current surfaces for later and free the old ones
for (int i = 0; i < 3; i++) {
diff --git a/video/coktel_decoder.cpp b/video/coktel_decoder.cpp
index 5d7efe87af..08340a19a6 100644
--- a/video/coktel_decoder.cpp
+++ b/video/coktel_decoder.cpp
@@ -1317,7 +1317,7 @@ void IMDDecoder::processFrame() {
// Set palette
if (cmd == kCommandPalette) {
_stream->skip(2);
-
+
_paletteDirty = true;
for (int i = 0; i < 768; i++)
diff --git a/video/psx_decoder.cpp b/video/psx_decoder.cpp
index fa7f1e8cfe..57c8972ee5 100644
--- a/video/psx_decoder.cpp
+++ b/video/psx_decoder.cpp
@@ -234,7 +234,7 @@ void PSXStreamDecoder::readNextPacket() {
Common::SeekableReadStream *frame = new Common::MemoryReadStream(partialFrame, frameSize, DisposeAfterUse::YES);
_videoTrack->decodeFrame(frame, sectorsRead);
-
+
delete frame;
delete sector;
return;
@@ -297,7 +297,7 @@ Common::SeekableReadStream *PSXStreamDecoder::readSector() {
// Ha! It's palindromic!
#define AUDIO_DATA_CHUNK_SIZE 2304
-#define AUDIO_DATA_SAMPLE_COUNT 4032
+#define AUDIO_DATA_SAMPLE_COUNT 4032
static const int s_xaTable[5][2] = {
{ 0, 0 },
@@ -483,7 +483,7 @@ void PSXStreamDecoder::PSXVideoTrack::decodeFrame(Common::SeekableReadStream *fr
decodeMacroBlock(&bits, mbX, mbY, scale, version);
// Output data onto the frame
- Graphics::convertYUV420ToRGB(_surface, _yBuffer, _cbBuffer, _crBuffer, _surface->w, _surface->h, _macroBlocksW * 16, _macroBlocksW * 8);
+ YUVToRGBMan.convert420(_surface, Graphics::YUVToRGBManager::kScaleFull, _yBuffer, _cbBuffer, _crBuffer, _surface->w, _surface->h, _macroBlocksW * 16, _macroBlocksW * 8);
_curFrame++;
diff --git a/video/psx_decoder.h b/video/psx_decoder.h
index 11f311594d..d1d5204e37 100644
--- a/video/psx_decoder.h
+++ b/video/psx_decoder.h
@@ -149,7 +149,7 @@ private:
uint32 _frameCount;
Common::SeekableReadStream *_stream;
PSXVideoTrack *_videoTrack;
- PSXAudioTrack *_audioTrack;
+ PSXAudioTrack *_audioTrack;
Common::SeekableReadStream *readSector();
};
diff --git a/video/qt_decoder.cpp b/video/qt_decoder.cpp
index b4dab9ddfb..c5fcab4b49 100644
--- a/video/qt_decoder.cpp
+++ b/video/qt_decoder.cpp
@@ -348,18 +348,27 @@ bool QuickTimeDecoder::VideoTrackHandler::endOfTrack() const {
}
bool QuickTimeDecoder::VideoTrackHandler::seek(const Audio::Timestamp &requestedTime) {
- // First, figure out what edit we're in
- Audio::Timestamp time = requestedTime.convertToFramerate(_parent->timeScale);
-
- // Continue until we get to where we need to be
+ uint32 convertedFrames = requestedTime.convertToFramerate(_decoder->_timeScale).totalNumberOfFrames();
for (_curEdit = 0; !endOfTrack(); _curEdit++)
- if ((uint32)time.totalNumberOfFrames() >= getCurEditTimeOffset() && (uint32)time.totalNumberOfFrames() < getCurEditTimeOffset() + getCurEditTrackDuration())
+ if (convertedFrames >= _parent->editList[_curEdit].timeOffset && convertedFrames < _parent->editList[_curEdit].timeOffset + _parent->editList[_curEdit].trackDuration)
break;
- // This track is done
+ // If we did reach the end of the track, break out
if (endOfTrack())
return true;
+ // If this track is in an empty edit, position us at the next non-empty
+ // edit. There's nothing else to do after this.
+ if (_parent->editList[_curEdit].mediaTime == -1) {
+ while (!endOfTrack() && _parent->editList[_curEdit].mediaTime == -1)
+ _curEdit++;
+
+ if (!endOfTrack())
+ enterNewEditList(true);
+
+ return true;
+ }
+
enterNewEditList(false);
// One extra check for the end of a track
@@ -367,6 +376,7 @@ bool QuickTimeDecoder::VideoTrackHandler::seek(const Audio::Timestamp &requested
return true;
// Now we're in the edit and need to figure out what frame we need
+ Audio::Timestamp time = requestedTime.convertToFramerate(_parent->timeScale);
while (getRateAdjustedFrameTime() < (uint32)time.totalNumberOfFrames()) {
_curFrame++;
if (_durationOverride >= 0) {
@@ -557,6 +567,8 @@ void QuickTimeDecoder::VideoTrackHandler::enterNewEditList(bool bufferFrames) {
uint32 prevDuration = 0;
// Track down where the mediaTime is in the media
+ // This is basically time -> frame mapping
+ // Note that this code uses first frame = 0
for (int32 i = 0; i < _parent->timeToSampleCount && !done; i++) {
for (int32 j = 0; j < _parent->timeToSample[i].count; j++) {
if (totalDuration == (uint32)_parent->editList[_curEdit].mediaTime) {
@@ -577,10 +589,13 @@ void QuickTimeDecoder::VideoTrackHandler::enterNewEditList(bool bufferFrames) {
if (bufferFrames) {
// Track down the keyframe
+ // Then decode until the frame before target
_curFrame = findKeyFrame(frameNum) - 1;
while (_curFrame < (int32)frameNum - 1)
bufferNextFrame();
} else {
+ // Since frameNum is the frame that needs to be displayed
+ // we'll set _curFrame to be the "last frame displayed"
_curFrame = frameNum - 1;
}
@@ -589,6 +604,8 @@ void QuickTimeDecoder::VideoTrackHandler::enterNewEditList(bool bufferFrames) {
// Set an override for the duration since we came up in-between two frames
if (prevDuration != totalDuration)
_durationOverride = totalDuration - prevDuration;
+ else
+ _durationOverride = -1;
}
const Graphics::Surface *QuickTimeDecoder::VideoTrackHandler::bufferNextFrame() {
@@ -638,7 +655,19 @@ uint32 QuickTimeDecoder::VideoTrackHandler::getRateAdjustedFrameTime() const {
uint32 QuickTimeDecoder::VideoTrackHandler::getCurEditTimeOffset() const {
// Need to convert to the track scale
- return _parent->editList[_curEdit].timeOffset * _parent->timeScale / _decoder->_timeScale;
+
+ // We have to round the time off to the nearest in the scale, otherwise
+ // bad things happen. QuickTime docs are pretty silent on all this stuff,
+ // so this was found from samples. It doesn't help that this is really
+ // the only open source implementation of QuickTime edits.
+
+ uint32 mult = _parent->editList[_curEdit].timeOffset * _parent->timeScale;
+ uint32 result = mult / _decoder->_timeScale;
+
+ if ((mult % _decoder->_timeScale) > (_decoder->_timeScale / 2))
+ result++;
+
+ return result;
}
uint32 QuickTimeDecoder::VideoTrackHandler::getCurEditTrackDuration() const {
diff --git a/video/qt_decoder.h b/video/qt_decoder.h
index 71d33711a6..45ab155c2c 100644
--- a/video/qt_decoder.h
+++ b/video/qt_decoder.h
@@ -53,6 +53,7 @@ class Codec;
*
* Video decoder used in engines:
* - mohawk
+ * - pegasus
* - sci
*/
class QuickTimeDecoder : public VideoDecoder, public Audio::QuickTimeAudioDecoder {
diff --git a/video/smk_decoder.cpp b/video/smk_decoder.cpp
index bea65142a1..c49791100d 100644
--- a/video/smk_decoder.cpp
+++ b/video/smk_decoder.cpp
@@ -318,7 +318,7 @@ bool SmackerDecoder::loadStream(Common::SeekableReadStream *stream) {
// 1 - set to 1 if file is Y-interlaced
// 2 - set to 1 if file is Y-doubled
// If bits 1 or 2 are set, the frame should be scaled to twice its height
- // before it is displayed.
+ // before it is displayed.
_header.flags = _fileStream->readUint32LE();
SmackerVideoTrack *videoTrack = createVideoTrack(width, height, frameCount, frameRate, _header.flags, _header.signature);
diff --git a/video/theora_decoder.cpp b/video/theora_decoder.cpp
index d7260469e6..63aa93e2f5 100644
--- a/video/theora_decoder.cpp
+++ b/video/theora_decoder.cpp
@@ -302,7 +302,7 @@ bool TheoraDecoder::TheoraVideoTrack::decodePacket(ogg_packet &oggPacket) {
_nextFrameStartTime += _frameRate.getInverse().toDouble();
else
_nextFrameStartTime = time;
-
+
return true;
}
@@ -328,7 +328,7 @@ void TheoraDecoder::TheoraVideoTrack::translateYUVtoRGBA(th_ycbcr_buffer &YUVBuf
assert(YUVBuffer[kBufferU].height == YUVBuffer[kBufferY].height >> 1);
assert(YUVBuffer[kBufferV].height == YUVBuffer[kBufferY].height >> 1);
- Graphics::convertYUV420ToRGB(&_surface, YUVBuffer[kBufferY].data, YUVBuffer[kBufferU].data, YUVBuffer[kBufferV].data, YUVBuffer[kBufferY].width, YUVBuffer[kBufferY].height, YUVBuffer[kBufferY].stride, YUVBuffer[kBufferU].stride);
+ YUVToRGBMan.convert420(&_surface, Graphics::YUVToRGBManager::kScaleITU, YUVBuffer[kBufferY].data, YUVBuffer[kBufferU].data, YUVBuffer[kBufferV].data, YUVBuffer[kBufferY].width, YUVBuffer[kBufferY].height, YUVBuffer[kBufferY].stride, YUVBuffer[kBufferU].stride);
}
static vorbis_info *info = 0;
diff --git a/video/theora_decoder.h b/video/theora_decoder.h
index 7e36d829e7..ac808cdfe6 100644
--- a/video/theora_decoder.h
+++ b/video/theora_decoder.h
@@ -51,6 +51,7 @@ namespace Video {
* Decoder for Theora videos.
* Video decoder used in engines:
* - sword25
+ * - wintermute
*/
class TheoraDecoder : public VideoDecoder {
public:
diff --git a/video/video_decoder.cpp b/video/video_decoder.cpp
index e79043629c..110afa7755 100644
--- a/video/video_decoder.cpp
+++ b/video/video_decoder.cpp
@@ -35,7 +35,6 @@ namespace Video {
VideoDecoder::VideoDecoder() {
_startTime = 0;
- _needsRewind = false;
_dirtyPalette = false;
_palette = 0;
_isPlaying = false;
@@ -62,7 +61,6 @@ void VideoDecoder::close() {
delete *it;
_tracks.clear();
- _needsRewind = false;
_dirtyPalette = false;
_palette = 0;
_startTime = 0;
@@ -250,7 +248,7 @@ uint32 VideoDecoder::getTimeToNextFrame() const {
bool VideoDecoder::endOfVideo() const {
for (TrackList::const_iterator it = _tracks.begin(); it != _tracks.end(); it++)
- if (!(*it)->endOfTrack() && ((*it)->getTrackType() != Track::kTrackTypeVideo || !_endTimeSet || ((VideoTrack *)*it)->getNextFrameStartTime() < (uint)_endTime.msecs()))
+ if (!(*it)->endOfTrack() && (!isPlaying() || (*it)->getTrackType() != Track::kTrackTypeVideo || !_endTimeSet || ((VideoTrack *)*it)->getNextFrameStartTime() < (uint)_endTime.msecs()))
return false;
return true;
@@ -271,8 +269,6 @@ bool VideoDecoder::rewind() {
if (!isRewindable())
return false;
- _needsRewind = false;
-
// Stop all tracks so they can be rewound
if (isPlaying())
stopAudio();
@@ -306,8 +302,6 @@ bool VideoDecoder::seek(const Audio::Timestamp &time) {
if (!isSeekable())
return false;
- _needsRewind = false;
-
// Stop all tracks so they can be seeked
if (isPlaying())
stopAudio();
@@ -337,10 +331,6 @@ void VideoDecoder::start() {
_isPlaying = true;
_startTime = g_system->getMillis();
- // If someone previously called stop(), we'll rewind it.
- if (_needsRewind)
- rewind();
-
// Adjust start time if we've seeked to something besides zero time
if (_lastTimeChange.totalNumberOfFrames() != 0)
_startTime -= _lastTimeChange.msecs();
@@ -352,26 +342,27 @@ void VideoDecoder::stop() {
if (!isPlaying())
return;
+ // Stop audio here so we don't have it affect getTime()
+ stopAudio();
+
+ // Keep the time marked down in case we start up again
+ // We do this before _isPlaying is set so we don't get
+ // _lastTimeChange returned, but before _pauseLevel is
+ // reset.
+ _lastTimeChange = getTime();
+
_isPlaying = false;
_startTime = 0;
_palette = 0;
_dirtyPalette = false;
_needsUpdate = false;
- stopAudio();
-
// Also reset the pause state.
_pauseLevel = 0;
- // If this is a rewindable video, don't close it too. We'll just rewind() the video
- // the next time someone calls start(). Otherwise, since it can't be rewound, we
- // just close it.
- if (isRewindable()) {
- _lastTimeChange = getTime();
- _needsRewind = true;
- } else {
- close();
- }
+ // Reset the pause state of the tracks too
+ for (TrackList::iterator it = _tracks.begin(); it != _tracks.end(); it++)
+ (*it)->pause(false);
}
Audio::Timestamp VideoDecoder::getDuration() const {
@@ -399,6 +390,11 @@ bool VideoDecoder::Track::rewind() {
return seek(Audio::Timestamp(0, 1000));
}
+void VideoDecoder::Track::pause(bool shouldPause) {
+ _paused = shouldPause;
+ pauseIntern(shouldPause);
+}
+
Audio::Timestamp VideoDecoder::Track::getDuration() const {
return Audio::Timestamp(0, 1000);
}
@@ -674,7 +670,7 @@ bool VideoDecoder::hasFramesLeft() const {
// This is only used for needsUpdate() atm so that setEndTime() works properly
// And unlike endOfVideoTracks(), this takes into account _endTime
for (TrackList::const_iterator it = _tracks.begin(); it != _tracks.end(); it++)
- if ((*it)->getTrackType() == Track::kTrackTypeVideo && !(*it)->endOfTrack() && (!_endTimeSet || ((VideoTrack *)*it)->getNextFrameStartTime() < (uint)_endTime.msecs()))
+ if ((*it)->getTrackType() == Track::kTrackTypeVideo && !(*it)->endOfTrack() && (!isPlaying() || !_endTimeSet || ((VideoTrack *)*it)->getNextFrameStartTime() < (uint)_endTime.msecs()))
return true;
return false;
diff --git a/video/video_decoder.h b/video/video_decoder.h
index 7ccf49a0af..cc7d1df51b 100644
--- a/video/video_decoder.h
+++ b/video/video_decoder.h
@@ -102,16 +102,14 @@ public:
/**
* Begin playback of the video.
*
- * @note This has no effect is the video is already playing.
+ * @note This has no effect if the video is already playing.
*/
void start();
/**
* Stop playback of the video.
*
- * @note This will close() the video if it is not rewindable.
- * @note If the video is rewindable, the video will be rewound on the
- * next start() call unless rewind() or seek() is called before then.
+ * @note This has no effect if the video is not playing.
*/
void stop();
@@ -180,6 +178,9 @@ public:
/**
* Set the time for this video to end at. At this time in the video,
* all audio will stop and endOfVideo() will return true.
+ *
+ * While the setting is stored even if a video is not playing,
+ * endOfVideo() is only affected when the video is playing.
*/
void setEndTime(const Audio::Timestamp &endTime);
@@ -203,7 +204,7 @@ public:
* Returns the current frame number of the video.
* @return the last frame decoded by the video
*/
- int32 getCurFrame() const;
+ int getCurFrame() const;
/**
* Returns the number of frames in the video.
@@ -432,7 +433,7 @@ protected:
/**
* Set the pause status of the track.
*/
- void pause(bool shouldPause) {}
+ void pause(bool shouldPause);
/**
* Return if the track is paused.
@@ -450,7 +451,7 @@ protected:
/**
* Function called by pause() for subclasses to implement.
*/
- void pauseIntern(bool pause);
+ virtual void pauseIntern(bool shouldPause) {}
private:
bool _paused;
@@ -596,7 +597,7 @@ protected:
virtual Audio::Mixer::SoundType getSoundType() const { return Audio::Mixer::kPlainSoundType; }
protected:
- void pauseIntern(bool pause);
+ void pauseIntern(bool shouldPause);
/**
* Get the AudioStream that is the representation of this AudioTrack
@@ -762,7 +763,7 @@ private:
TrackList _tracks;
// Current playback status
- bool _isPlaying, _needsRewind, _needsUpdate;
+ bool _isPlaying, _needsUpdate;
Audio::Timestamp _lastTimeChange, _endTime;
bool _endTimeSet;